【问题标题】:How to match second time when using sscanf使用 sscanf 时如何进行第二次匹配
【发布时间】:2019-03-31 10:43:48
【问题描述】:

我是 C 新手,在 C 中使用 sscanf() 时遇到问题。

我的代码提示用户输入几行数据。单个数据就像一个 Python 元组 (1, 3) 或 (-3, 2),每行可能包含多个由零个或多个空格分隔的“元组”,我的代码如下,

char buffer[100];

while(fgets(buffer, sizeof buffer, stdin) != NULL) {
    while(sscanf(&buffer, "%*[^0-9|-]%i%*[^0-9|-]%i", &key, &value) != 1) {
        break;
    }
    printf("key==%d, value==%d\n", key, value);
}

我使用 fgets 读取用户输入的每一行,并使用 sscanf 获取一个元组,但似乎 sscanf 无法匹配一行中的第二个元组(或如何匹配)。为什么?还是有一些更明智的解决方案来解决我的问题?

【问题讨论】:

  • 更简单的格式字符串" (%d ,%d )%n" 也应该可以工作,每个标点符号前包含的空格将过滤任何空格。
  • @WeatherVane 这似乎无法正常工作,因为 fgets 函数读取了用户的所有键盘输入。如果用户在键盘上按向左或向右,fgets 也会将它们读入缓冲区...
  • @JasperZhou 但你试过了吗?它与接受的答案结合在一起,因为它获取扫描的字节数。它不会过滤掉意外按下的键,只有空格:垃圾输入 - 垃圾输出!理想情况下,您拒绝任何无意义的行。

标签: c scanf fgets


【解决方案1】:

%n 说明符将给出扫描处理的字符数并将其存储在 int 中。
累积偏移量以遍历该行。
sscanf 可能返回 EOF、0、1 或 2。考虑使用 == 2,因为您要扫描两个整数。

char buffer[100];
int offset = 0;
int scanned = 0;
while ( fgets ( buffer, sizeof buffer, stdin) != NULL) {
    offset = 0;
    scanned = 0;
    while ( sscanf ( buffer + offset, "%*[^0-9|-]%i%*[^0-9|-]%i%n", &key, &value, &scanned) == 2) {
        offset += scanned;
        printf("key==%d,value==%d\n",key,value);
    }
}

如果%n不起作用,strchr可用于查找(、sscanf (和两个整数,然后找到关闭的)。重复。
这使用了@WeatherVane 对更简单格式字符串的建议。

char buffer[100];
char *begin = NULL;
char *end = NULL;
while ( fgets ( buffer, sizeof buffer, stdin) != NULL) {
    end = buffer;
    while ( begin = strchr ( end, '(')) {//get pointer to (
        if ( sscanf ( begin, "(%d ,%d", &key, &value) == 2) {//scan ( and two integers
            printf("key==%d,value==%d\n",key,value);
        }
        end = strchr ( begin, ')');//get pointer to )
        if ( ! end) {
            break;//did not find )
        }
    }
}

另一种策略可以使用strspnstrcspn

char buffer[100];
size_t begin = 0;
size_t count = 0;
while ( fgets ( buffer, sizeof buffer, stdin) != NULL) {
    begin = 0;
    while ( buffer[begin]) {// not zero
        count = strcspn ( &buffer[begin], "-0123456789");//count of non digit or -
        begin += count;
        if ( sscanf ( &buffer[begin], "%d ,%d", &key, &value) == 2) {//scan ( and two integers
            printf("key==%d,value==%d\n",key,value);
        }
        count = strspn ( &buffer[begin], " ,-0123456789");//count space , - or digit
        begin += count;
    }
}

【讨论】:

  • 需要注意的是,由于超出本问题范围的有争议的原因,微软版本的sscanf()不支持%n
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多