到达文件末尾后,fgetc是否在每次通话时都返回EOF?

Ale*_*dre 4 c std

给出以下C代码:

int eofCount = 0;
while (true) {
    int c = fgetc(stdin); 
    if (c == EOF) eofCount++;
}
Run Code Online (Sandbox Code Playgroud)

eofCount会不会超过1?

我找不到C文档中的任何内容,描述了在达到EOF之后fgetc会发生什么.我知道我可以自己做这本书,但如果stdlib为我做的那就太好了.

我不是在寻找代码片段,因为我已经用glibc尝试了这个,实际上eofCount在EOF之后增加了.我想stdlib源代码参考或规范,确认这是定义的行为.依赖未定义的行为可能会导致问题.

chu*_*ica 6

到达文件结尾后,fgetc 是否在每次调用时都返回 EOF?

它取决于 2 个指标和 I/O 函数调用。


尽管 OP 没有提到,但fgetc(stdin);返回EOF以及它们如何影响后续fgetc()调用的原因不对称有两个原因。此外,使用各种 I/O 函数会影响 2 个指标,进而影响后续fgetc()调用

文件结束。
输入错误。


C 规范在文件结束指示符上是明确的,导致后续的EOF.

如果 stream 指向的输入流的文件结束指示符未设置并且存在下一个字符,则 fgetc 函数获取该字符... C11 §7.21.7.1 2

当文件结束发生或已经发生时,设置一个持久标志:文件结束指示符,因此后续调用fgetc()将返回EOF

如果设置了流的文件尾指示符,或者如果流位于文件尾,则设置流的文件尾指示符并且fgetc函数返回EOF... §7.21 .7.1 3


当发生罕见的输入错误时,fgetc()返回EOF,但该事件不会设置文件结束指示符,但会设置错误指示符EOF即使设置了错误指示符,后续调用也不一定返回。IMO,C 规范在这一点上不够明确。

如果发生读取错误,则设置流的错误指示符,fgetc函数返回EOF§7.21.7.1 3


feof()、 和的调用ferror()可用于区分导致 的原因EOF,但也可反映先前的 I/O 活动。因此,好的代码会在EOF返回an 后立即检查这些函数,并在发生后续 I/O 时清除它们。


文件结束指示符错误指示符可以清除void clearerr(FILE *stream);

rewind()函数清除 错误指示器

ungetc()将清除文件结束指示符

其他 I/O 功能也会影响这些指标。


如果导致第一个的条件被删除并且相应的指示符被清除,则后续调用fgetc()可能不会返回。EOFEOF


dbu*_*ush 5

只要您没有从交互式Linux终端读取(即您没有从其他文件/进程打开文件或管道stdin),一旦您阅读EOF,所有未来的读取也将读取EOF.

如果您正在从Linux终端读取,按下EOF的键序列(Linux上的CTRL-D)将显示为EOF,但您仍然可以输入更多字符并阅读它们.

C标准的第7.21.7.1节开始:

3如果设置了流的文件结束指示符,或者流位于文件结尾,则设置流的文件结束指示符并fgetc返回该函数EOF.否则,该fgetc 函数返回stream指向的输入流中的下一个字符.如果发生读取错误,则设置流的错误指示符并fgetc返回该函数EOF.