C:从用户读取成对的整数直到换行(scanf、sscanf、fgets 和朋友)

C: Reading pairs of ints from user until newline (scanf, sscanf, fgets and friends)

我正在尝试从标准输入读取未知对,直到输入新行。

输入示例:

Enter something:

5

Enter pairs:

1 3 4 2 5 2 5 4

最好的方法是什么?我已经尝试了几种方法,包括 fgets 和 sscanf - 但无法获得预期的结果。

这是我试过的方法,但我总是错过\n:

方法一:

while (1)
{
    scanf("%d %d", &a, &b);

    // do something with a,b

    if (getchar() == '\n')
        break;
}

方法二:

while (scanf("%d %d", &a, &b) == 2)
{
    // do something with a,b

    if (getchar() == '\n')
        break;
}

我一直陷入无限循环 - 我做错了什么?

你得到一个无限循环,因为读取的最后一个数字后的下一个字符不是换行符而是 space

所以如果你输入这个输入

1 3 4 2 5 2 5 4 

1<space>3<space>4<space>2<space>5<space>2<space>5<space>4<Enter>

你可以让它工作(请注意输入中最后一个数字 4 之后的最后一个字符)

我们来分析一下上面的例子

1<space>3<space>
|       |  |-----> will be stored in getchar()
|       |--------> will be stored in b 
|----------------> will be stored in a 

所以对于最后两位数字,如果您点击 space 而不是输入按钮,就会发生这种情况

5<space>4<space>
|       |  |-----> will be stored in getchar() which is not newline 
|       |          so it will generate another loop 
|       |--------> will be stored in b 
|----------------> will be stored in a 

所以程序将等待输入数字,因为创建了另一个循环并卡在那里,因为没有数字了!!

要解决这个问题,您可以使用 fgets() 函数将整行存储在一个字符串中,然后使用 sscanf() 函数从中获取一对数字

我认为处理行尾空格的最简单方法(这可能是导致您出现问题的原因)是提前阅读该行并使用 sscanf 对其进行解析。它可能看起来大致像这样:

#include <stdio.h>

int main() {
  char line[1024];
  char const *p;
  int x, y;
  int n;

  fgets(line, 1024, stdin);

  for(p = line; sscanf(p, " %d %d%n", &x, &y, &n) == 2; p += n) {
    printf("%d %d %d\n", x, y, n); // to show you what happens
  }

  return 0;
}

此处 %n 使 sscanf 告诉您到目前为止已处理的字符数,我们使用该数字在每次迭代中推进我们的读取指针。

这会通过忽略最后一个数字来处理一行中数量不均匀的数字,这可能是也可能不是您想要发生的情况。