如果输入不符合指定的格式,sscanf 在 C 中有什么作用?

What does sscanf do in C if the input doesn't meet the specified format?

提问人:A Lumpkin 提问时间:11/7/2023 最后编辑:chqrlieA Lumpkin 更新时间:11/8/2023 访问量:110

问:

#include <stdio.h>

int main(int argc, const char *argv[]) {
    FILE *fp = fopen("input.txt", "r");
    char buffer[256];
    int n, a, b;
    n = a = b = 0;
    while (fgets(buffer, 250, fp)) {
        n = sscanf(buffer, "%d %d", &a, &b);
        printf("%d %d %d\n", a, b, n);
    }
    fclose(fp);
    printf("Next Part\n");
    fp = fopen("input.txt", "r");
    n = a = b = 0;
    while (0 < (n = fscanf(fp, "%d %d", &a, &b))){
        printf("%d %d %d\n", a, b, n);
    }

    return 0;
}

input.txt 包含以下行:

1 2 3
4 abc 5 6
7 8
the 1 next 2 line 3 is blank

4 5 the above line is blank 6
7 8

我知道第一行打印将是因为被设置为的返回值(由于我假设两个整数都被读取,因此返回)。但是,我不确定第二条线会产生什么?如果我能找人为我解决并解释第二行,我将不胜感激。我也对当循环遇到空行时会发生什么感到困惑?1 2 2nsscanf2

c while-loop scanf fgets

评论

0赞 jxh 11/8/2023
scanf可能很奇怪。格式字符串中的空格表示跳过任何空格。如果输入不能用于满足格式说明符,则不会从输入流中使用输入。
1赞 Jabberwocky 11/8/2023
@jxh这是关于 ,而不是.没有输入流。sscanfscanf
0赞 John Bollinger 11/8/2023
没错,@Jabberwocky,但相当迂腐。从 jxh 的注释中删除“stream”,它同样适用于 和 。scanfsscanf
0赞 John Bollinger 11/8/2023
如何阅读 sscanf 的文档?我知道,这些特定的文档需要吸收很多东西,但阅读技术文档是成为一名优秀程序员需要培养的技能。
0赞 Andrew Henle 11/8/2023
@JohnBollinger 为什么该页面将大部分转换说明符显示为“已弃用”?C23 标准草案中提到的任何转换说明符都没有弃用 iso-9899.info/n3047.html*scanf()

答:

2赞 Jabberwocky 11/8/2023 #1

诚然,该文档阅读起来很乏味。sscanf

这个小示例显示了如果输入与格式字符串不匹配会发生什么情况。

#include <stdio.h>

int main(void)
{
  int a = 100, b = 200;
  char input1[] = "1 2 3 4 whatever";
  int n = sscanf(input1, "%d %d", &a, &b);
  printf("sscanf has read %d items. a = %d, b = %d\n", n, a, b);

  char input2[] = "11 foo bar";
  n = sscanf(input2, "%d %d", &a, &b);
  printf("sscanf has read %d items. a = %d, b = %d\n", n, a, b);
}

输出为:

sscanf has read 2 items. a = 1, b = 2
sscanf has read 1 items. a = 11, b = 2

在第一个 中,有 2 个项目被读取为并匹配格式字符串。sscanf12%d %d

在第二阶段,只有1项被读取为只与第一项匹配,但与第二项不匹配。 未修改。sscanf11%dfoo%db

它让你弄清楚如果你给它一个空行会做什么。提示:这并不完全明显,但它在文档中。sscanf

评论

1赞 Jabberwocky 11/8/2023
@chux-恢复莫妮卡完成了。
0赞 A Lumpkin 11/8/2023
谢谢!我不确定这是否正确,但我会说当循环遇到空行时 n = 0?
1赞 chqrlie 11/8/2023
@ALumpkin:不是的。对于空行,无论是否带有空格字符(例如换行符),尝试解析 for 将读取并使用初始空格,并在第一次转换产生 之前到达字符串的末尾,因此将返回 。(答案在文档中,但恕我直言,这并不完全明显)sscanf()int%dintsscanf()EOF
4赞 chux - Reinstate Monica 11/8/2023 #2

如果输入不符合指定的格式,在 C 中怎么办?sscanf

int sscanf(const char * restrict s, const char * restrict format, ...);

sscanf()处理格式字符串一次一个字符,如果不是。否则,它将读取单个扫描说明符(如 )。这些是针对字符串处理的,但不超过字符串的末尾。 然后继续向下,直到读取空字符或扫描说明符转换失败。然后:format%"%d"sssscanf()format

  • 扫描停止。

  • 的后续部分不使用。format

  • 转化次数(返回值)没有进一步变化。

  • ...尚未使用的参数将保持未读状态,因此它们指向的任何内容都不会被赋值。

  • sscanf()返回转化计数。

评论

0赞 chqrlie 11/8/2023
您应该提到,格式字符串中的空格与字符串中的任何空格序列匹配,包括 none。
1赞 chux - Reinstate Monica 11/8/2023
@chqrlie 也许吧,但随后我开始沿着规范车道行驶,这是 C 规范中最长的车道之一。人们可以在那个驱动器上写一本巨著。(注意:中的空格仅匹配空格,因此“格式字符串中的空与空格的任何序列匹配”需要限定)。*scanf()"%[ ]"