2

我浏览了有关此 K&R 示例的网站,答案似乎围绕着“为什么这是一个类型 int 或什么是 EOF?” 有点家伙。我相信我理解这些。这是我不明白的结果。我曾期望此代码采用单个字符,打印它然后等待另一个字符或 EOF。

我看到的结果是输入等到我按回车键,然后我输入的所有内容都会显示出来,等待输入的时间越长。

while 循环是否只是“循环”,直到我用 carrage return 结束文本流,然后显示 putchar(c) 隐藏在某处的内容?

代码是:

#include <stdio.h>

/* copy input to output: 1st version */
main()
{
    int c;

    c = getchar();
    while(c != EOF) {
        putchar(c);
        c = getchar();
    }  
}

现在,如果我在刚才上线之前偷偷输入一个 putchar(c),我就会得到我所期望的。我仍然必须输入文本流并按回车键。结果是流的第一个字符,程序退出。

显然对我来说还有很大的差距。

谢谢您的帮助

4

2 回答 2

2

默认情况下,stdin 和 stdout 被缓冲。这意味着他们会保存成批的字符并立即发送它们以提高效率。通常,批处理会一直保存到缓冲区中没有更多空间或流中出现换行符或 EOF 为止。

当您调用 时getchar(),您是从标准输入中询问字符。假设您键入A,该字符将保存在缓冲区中,然后系统等待更多输入。如果您键入B,则该字符接下来会进入缓冲区。也许在那之后,您按 Enter 键,并且在缓冲区中放入了一个换行符。但是换行符也中断了缓冲过程,所以最初的调用getchar()返回缓冲区中的第一个字符(A)。在下一次迭代中,您getchar()再次调用,它会立即返回缓冲区中的下一个字符 ( B)。等等。

因此,并不是您的 while 循环一直在运行,直到您结束该行,而是第一次调用getchar()(当缓冲区为空时)正在等待,直到它有一个完整的缓冲区或它已经看到一个换行符。

当您交错输出函数时putchar(),大多数 C 运行时库会在您执行将数据发送到标准输出的操作时“刷新”标准输入(反之亦然)。(目的是确保用户在程序等待输入之前看到提示。)这就是为什么您在添加putchar()调用时开始看到不同的行为。

flush()您可以使用该函数手动刷新缓冲区。您还可以使用 控制标准流使用的缓冲区大小setvbuf()

正如 Han Passant 在评论中指出的那样,换行符不会“终止流”。要在标准输入上获得 EOF,您必须键入 Ctrl+D(或者,在某些系统上,为 Ctrl+Z)。EOF 也会刷新缓冲区。如果您将文件或来自另一个程序的输出重定向到标准输入,则一旦输入用尽,就会发生 EOF。

虽然 K&R C 确实非常古老,甚至 ANSI C 在今天也不像以前那么普遍,但在当前标准甚至 C++ 中,关于使用 stdin 和 stdout 进行缓冲的所有内容实际上都是相同的。我认为唯一显着的变化是 C 标准现在明确指出了让 stdin 和 stdout 导致另一个刷新的可取性。

于 2016-04-18T21:09:08.023 回答
0

感谢您的回答,您描述的缓冲非常有用且有趣。

显然,我也一定有误读/理解,K&R。他们将文本流定义为“......由零个或多个字符组成,后跟一个换行符”,我认为这意味着返回/输入键;结束它,然后允许输出。

另外,我要感谢所有提供有用意见的人。

顺便说一句,我清楚地知道我必须输入^D才能生成EOF,从而终止程序。感谢你们都是顶级程序员,感谢你们的时间。我想我需要找到另一个地方来讨论 R&R 写的关于这个练习的文本是关于什么的。

于 2016-04-21T00:19:13.257 回答