为什么 scanf 可以使用 for 循环读取一行中的多个输入?

Stu*_*ers -1 c

我想将给定的 n 个值(n 已知)存储在一个数组中,但我不知道该怎么做,所以我查看并找到了这篇文章:C, read multiple numbers from single input line (scanf?),还有这个回答:

int main()
{
    int i, size, *v;
    scanf("%d", &size);
    v = malloc(size * sizeof(int));
    for (i=0; i<size; i++)
        scanf("%d", &v[i]);
    printf("%d %d %d", v[0], v[1], v[2]);
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么 scanf 可以这样做,函数不应该在循环的每次迭代中要求另一个输入吗?只要它们以空格分隔,它如何读取一个int,然后读取另一个等等?scanf 怎么会这样呢?因为好像不应该。

PS:为了简单起见,我只用 3 个值编写了最终的打印语句,在“我的情况”中,大小为 3。

先感谢您!

Ste*_*ocy 5

当您在控制台上输入一些数字并按 ENTER 时,您正在通过 stdin 向您的代码提供输入流。您输入的全部内容都保存在该输入流中。所以如果你输入

2 4 6 8

然后按回车,输入流包含:2 4 6 8

现在,您的每个 scanfs 仅从该输入流中读取(并删除)一个整数,因此在单个 scanf 之后,stdin 输入流现在包含:4 6 8

额外的输入不会被丢弃,它在输入流中仍然可用,所以你的下一个 scanf 可以出现并从流中获取下一个整数,下一个,下一个......直到输入中的数据流耗尽。

  • 换行符也将是输入流的一部分。这对于像“%s”这样的转换说明符特别重要,因为换行符将保留在输入缓冲区中。 (2认同)

Ste*_*mit 5

这是令人惊讶的事情之一scanf

如果我写

scanf("%d %d %d", &a, &b, &c);
Run Code Online (Sandbox Code Playgroud)

看起来我期待读到一行包含三个数字的内容。但如果用户实际输入的是

1
2
3
Run Code Online (Sandbox Code Playgroud)

(即,在三个单独的行上),它会“工作”得很好。 scanf它想要三个整数,并且找到了它们,但它必须读取三行才能做到这一点。

相反,如果我写

scanf("%d", &a);
scanf("%d", &b);
scanf("%d", &c);
Run Code Online (Sandbox Code Playgroud)

用户输入

4 5 6
Run Code Online (Sandbox Code Playgroud)

在一行上,这再次“工作”得很好,有三个scanf调用总共要求三个整数,并且那里有三个整数 - 尽管它们碰巧在一行上。

在您的情况下,scanf循环中的调用与多个单独的scanf调用具有大致相同的效果。

最重要的是,这不是scanf基于线路的。对输入的调用和预期的输入行之间不存在一对一的对应关系。 不会特殊对待换行符——它们只是被视为空格,分隔其他输入字段。scanfscanf

(相比之下,printf它也不是基于行的,尽管它至少会\n特殊对待字符。但是两者之间的输出没有什么不同

printf("one ");
printf("two ");
printf("three\n");
Run Code Online (Sandbox Code Playgroud)

printf("one two three\n");
Run Code Online (Sandbox Code Playgroud)

.)