fgetc return EOF 是否在到达文件末尾后每次调用?
Does fgetc return EOF on every call after end-of-file reached?
给定以下 C 代码:
int eofCount = 0;
while (true) {
int c = fgetc(stdin);
if (c == EOF) eofCount++;
}
eofCount 会大于 1 吗?
我在 C 文档中找不到任何描述达到 EOF 后 fgetc 会发生什么的内容。我知道我可以自己记账,但如果 stdlib 帮我做,那就太好了。
我不是在寻找代码片段,因为我已经用 glibc 尝试过这个,事实上 eofCount 递增超过了 EOF。我想要 stdlib 源代码参考或规范来确认这是定义的行为。依赖未定义的行为可能会导致问题。
是的,计数会大于 1,因为您有一个无限 while
循环。你会发现 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf and http://pubs.opengroup.org/onlinepubs/9699919799/ 很有用。
试试这个:
#include <stdio.h>
#include <stdbool.h>
int main() {
int eofCount = 0;
/*while (true) {*/
int c = fgetc(stdin);
if (c == EOF) eofCount++;
c = fgetc(stdin);
if (c == EOF) eofCount++;
c = fgetc(stdin);
if (c == EOF) eofCount++;
/*}*/
printf("%d\n", eofCount);
return 0;
}
编译并运行。在 Linux 上按 ctrl+D 两次,然后输入。你会得到2.
这是用 gcc -ansi -Wall -Werror -pedantic test.c
编译的,因此它满足 ANSI,即 C89 标准。
只要您不是从交互式 Linux 终端读取(即您不打开文件或从其他 file/process 传输标准输入),一旦您读取 EOF,所有未来的读取也将读取 EOF。
如果您从 Linux 终端阅读,按下 EOF 键序列(Linux 上的 CTRL-D)将读作 EOF,但您仍然可以输入更多字符并阅读它们.
来自 C standard 的第 7.21.7.1 节:
3 If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is
set and the fgetc
function returns EOF
. Otherwise, the fgetc
function returns the next character from the input stream pointed to
by stream. If a read error occurs, the error indicator for
the stream is set and the fgetc
function returns EOF
.
Does fgetc return EOF on every call after end-of-file reached?
这取决于 2 个 指标 和 I/O 函数调用。
尽管 OP 未提及,但有两个原因导致 fgetc(stdin);
returns EOF
以及它们如何影响后续 fgetc()
调用不对称。此外,使用各种 I/O 函数会影响 2 指标 ,进而影响后续 fgetc()
调用
文件结束。
输入错误。
C 规范在 文件结束指示器 上是明确的,导致后续 EOF
。
If the end-of-file indicator for the input stream pointed to by stream is not set and a next character is present, the fgetc function obtains that character ... C11 §7.21.7.1 2
当文件结束发生或已经发生时,将设置持久标志:文件结束指示器,因此对fgetc()
的后续调用将return EOF
.
If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc
function returnsEOF
... §7.21.7.1 3
当发生罕见的输入错误时,fgetc()
returns EOF
,但该事件不会设置 文件结束指示器 ,但设置了 错误指示符 。后续调用不一定 return EOF
,即使设置了 错误指示符 。 IMO,C 规范在这一点上不够明确。
If a read error occurs, the error indicator for the stream is set and the fgetc
function returns EOF
§7.21.7.1 3
对 feof()
和 ferror()
的调用可用于区分导致 EOF
的原因,但也可能反映先前的 I/O activity。因此,好的代码会在 EOF
被 returned 后立即检查这些函数,并在 I/O 之后清除它们。
文件结束指示符和错误指示符可以用void clearerr(FILE *stream);
清除
rewind()
函数清除错误指示器。
ungetc()
将清除 文件结束指示符。
其他 I/O 函数也会影响这些指标。
如果导致第一个 EOF
的条件被移除并且相应的指示符被清除,则对 fgetc()
的后续调用可能不会 return EOF
。
给定以下 C 代码:
int eofCount = 0;
while (true) {
int c = fgetc(stdin);
if (c == EOF) eofCount++;
}
eofCount 会大于 1 吗?
我在 C 文档中找不到任何描述达到 EOF 后 fgetc 会发生什么的内容。我知道我可以自己记账,但如果 stdlib 帮我做,那就太好了。
我不是在寻找代码片段,因为我已经用 glibc 尝试过这个,事实上 eofCount 递增超过了 EOF。我想要 stdlib 源代码参考或规范来确认这是定义的行为。依赖未定义的行为可能会导致问题。
是的,计数会大于 1,因为您有一个无限 while
循环。你会发现 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf and http://pubs.opengroup.org/onlinepubs/9699919799/ 很有用。
试试这个:
#include <stdio.h>
#include <stdbool.h>
int main() {
int eofCount = 0;
/*while (true) {*/
int c = fgetc(stdin);
if (c == EOF) eofCount++;
c = fgetc(stdin);
if (c == EOF) eofCount++;
c = fgetc(stdin);
if (c == EOF) eofCount++;
/*}*/
printf("%d\n", eofCount);
return 0;
}
编译并运行。在 Linux 上按 ctrl+D 两次,然后输入。你会得到2.
这是用 gcc -ansi -Wall -Werror -pedantic test.c
编译的,因此它满足 ANSI,即 C89 标准。
只要您不是从交互式 Linux 终端读取(即您不打开文件或从其他 file/process 传输标准输入),一旦您读取 EOF,所有未来的读取也将读取 EOF。
如果您从 Linux 终端阅读,按下 EOF 键序列(Linux 上的 CTRL-D)将读作 EOF,但您仍然可以输入更多字符并阅读它们.
来自 C standard 的第 7.21.7.1 节:
3 If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the
fgetc
function returnsEOF
. Otherwise, thefgetc
function returns the next character from the input stream pointed to by stream. If a read error occurs, the error indicator for the stream is set and thefgetc
function returnsEOF
.
Does fgetc return EOF on every call after end-of-file reached?
这取决于 2 个 指标 和 I/O 函数调用。
尽管 OP 未提及,但有两个原因导致 fgetc(stdin);
returns EOF
以及它们如何影响后续 fgetc()
调用不对称。此外,使用各种 I/O 函数会影响 2 指标 ,进而影响后续 fgetc()
调用
文件结束。
输入错误。
C 规范在 文件结束指示器 上是明确的,导致后续 EOF
。
If the end-of-file indicator for the input stream pointed to by stream is not set and a next character is present, the fgetc function obtains that character ... C11 §7.21.7.1 2
当文件结束发生或已经发生时,将设置持久标志:文件结束指示器,因此对fgetc()
的后续调用将return EOF
.
If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the
fgetc
function returnsEOF
... §7.21.7.1 3
当发生罕见的输入错误时,fgetc()
returns EOF
,但该事件不会设置 文件结束指示器 ,但设置了 错误指示符 。后续调用不一定 return EOF
,即使设置了 错误指示符 。 IMO,C 规范在这一点上不够明确。
If a read error occurs, the error indicator for the stream is set and the
fgetc
function returnsEOF
§7.21.7.1 3
对 feof()
和 ferror()
的调用可用于区分导致 EOF
的原因,但也可能反映先前的 I/O activity。因此,好的代码会在 EOF
被 returned 后立即检查这些函数,并在 I/O 之后清除它们。
文件结束指示符和错误指示符可以用void clearerr(FILE *stream);
rewind()
函数清除错误指示器。
ungetc()
将清除 文件结束指示符。
其他 I/O 函数也会影响这些指标。
如果导致第一个 EOF
的条件被移除并且相应的指示符被清除,则对 fgetc()
的后续调用可能不会 return EOF
。