You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

终端命令行游戏命令拆分问题:sscanf/strtok使用求助

解决命令行输入按空格拆分的问题

问题根源

你遇到的sscanf逐次截断问题,大概率是循环处理时错误地手动递增指针(比如ptr++),导致每次从下一个字符开始读取,而非跳到当前命令段的末尾。

可行解决方案

1. 正确使用sscanf结合%n

%n是sscanf的格式符,会记录本次读取的字符总数,用它来移动指针就能避免截断问题:

#include <stdio.h>
#include <string.h>

int main() {
    char input[256];
    printf("Enter command: ");
    fgets(input, sizeof(input), stdin);
    
    // 移除输入末尾的换行符
    input[strcspn(input, "\n")] = '\0';
    
    char part[64];
    char *ptr = input;
    int read_len;
    int part_num = 1;
    
    while (sscanf(ptr, "%s%n", part, &read_len) == 1) {
        printf("part%d = \"%s\"\n", part_num++, part);
        ptr += read_len;
        // 跳过连续的空格
        while (*ptr == ' ') ptr++;
    }
    return 0;
}
  • %s读取连续非空白字符作为命令段
  • %n记录本次读取的字符数,让指针直接跳到当前命令段之后
  • 额外跳过连续空格,处理多个空格分隔的情况

2. 用strtok(推荐,更简洁)

strtok是C标准库专门用于字符串拆分的函数,自动处理连续分隔符,代码更简洁:

#include <stdio.h>
#include <string.h>

int main() {
    char input[256];
    printf("Enter command: ");
    fgets(input, sizeof(input), stdin);
    
    input[strcspn(input, "\n")] = '\0';
    
    char *token = strtok(input, " ");
    int part_num = 1;
    
    while (token != NULL) {
        printf("part%d = \"%s\"\n", part_num++, token);
        token = strtok(NULL, " ");
    }
    return 0;
}
  • 第一次调用strtok传入原始字符串和分隔符(空格)
  • 后续调用传入NULL,继续拆分剩余的字符串部分

3. 手动解析(适合自定义规则场景)

如果需要更精细的控制(比如支持带引号的参数),可以手动遍历字符串:

#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main() {
    char input[256];
    printf("Enter command: ");
    fgets(input, sizeof(input), stdin);
    
    input[strcspn(input, "\n")] = '\0';
    
    char parts[10][64]; // 最多存储10个命令段,每个长度不超过63
    int part_count = 0;
    char *ptr = input;
    
    while (*ptr != '\0' && part_count < 10) {
        // 跳过前导空格
        while (isspace((unsigned char)*ptr)) ptr++;
        if (*ptr == '\0') break;
        
        // 定位当前命令段的结束位置
        char *segment_start = ptr;
        while (*ptr != '\0' && !isspace((unsigned char)*ptr)) ptr++;
        
        // 复制命令段到数组
        int segment_len = ptr - segment_start;
        if (segment_len > 63) segment_len = 63; // 防止缓冲区溢出
        strncpy(parts[part_count], segment_start, segment_len);
        parts[part_count][segment_len] = '\0';
        part_count++;
    }
    
    // 输出拆分结果
    for (int i = 0; i < part_count; i++) {
        printf("part%d = \"%s\"\n", i+1, parts[i]);
    }
    return 0;
}

命令匹配优化建议

拆分完命令段后,你可以用命令-函数映射表替代逐个strcmp的低效方式,新增命令只需添加条目,更易维护:

#include <stdio.h>
#include <string.h>

// 命令处理函数类型
typedef void (*CmdHandler)(char **args, int arg_count);

// 命令结构体
typedef struct {
    const char *cmd;
    CmdHandler handler;
} Command;

// 示例处理函数
void debug_handler(char **args, int arg_count) {
    printf("Debug mode activated, args count: %d\n", arg_count);
    if (arg_count > 0) printf("First arg: %s\n", args[0]);
}

void test_handler(char **args, int arg_count) {
    printf("Test command executed\n");
}

// 命令列表
Command cmds[] = {
    {"debug", debug_handler},
    {"test", test_handler},
    // 更多命令...
};
const int cmd_count = sizeof(cmds)/sizeof(cmds[0]);

// 查找命令并执行
void execute_cmd(char **parts, int part_count) {
    if (part_count == 0) return;
    for (int i = 0; i < cmd_count; i++) {
        if (strcmp(parts[0], cmds[i].cmd) == 0) {
            cmds[i].handler(parts + 1, part_count - 1);
            return;
        }
    }
    printf("Unknown command: %s\n", parts[0]);
}

内容的提问来源于stack exchange,提问作者some guy who likes C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 17:43:17