混淆 == EOF 与 feof

Confusion with == EOF vs feof

我打开了一个文件,在指针ptr的地址找到了流。我正在尝试查看文件是否为空白。使用以下

if (fgetc(ptr) != EOF)

按预期工作。当文件为空时,不执行该语句。当文件不为空时,语句不执行

但是,使用

if (!feof(ptr))

总是执行语句。

为什么会这样?有没有办法使用feof函数?

feof(f) 在您打开文件后将始终 return false 因为如果给您一个标志的值,该标志被初始化为 false 并且仅在至少之后才设置为 true一次读取操作失败。

您可以这样使用 feof

fgetc(fp);
if (feof(fp))
  ...

feof 在尝试读取文件末尾或超过文件末尾的读取之后检查文件结束指示符集。这在您控制的代码正在从文件中读取,并且您希望在文件耗尽后停止处理的情况下很有用。

在C标准库中"end of file"不是一个独立的自检测条件。 "End of file" 只是前面的读取操作 设置的文件状态 。在执行读取操作并且读取操作碰到文件的实际末尾之前,不会设置 "eof" 状态并且 feof() returns 0.

C 标准库中的许多(大多数)标准 I/O 函数已经 return 一些可用于检测 "end of file" 条件的完成代码(如 fgetc() returning EOF 值)。这意味着大多数时候调用 feof() 是不必要的。

换句话说,如果您将 "end of file" 视为一堵砖墙,在 C 标准库中,仅仅站在那堵墙的正前方以检测它是不够的。必须用你的额头真正撞到那堵墙才能发现它的存在。

当您打开一个空文件时,您开始时处于 "right before the wall" 状态。此时尚未检测到 "end of file" 条件。你必须尝试阅读一些东西才能撞到那堵墙上,从而检测到它的存在。

这种设计的原因是完全合乎逻辑的。 C 语言旨在支持各种输入流和文件系统,包括 1) 根本不存储文件大小的文件系统,以及 2) 仅知道近似文件大小(如四舍五入到最近的簇)的文件系统。在这样的文件系统中,文件的结尾通常由一个特殊的标记指定。在阅读文件时 运行 之前,您不知道该标记在哪里。 (出于同样的原因,C 流不保证支持 fseek 函数中来自 SEEK_END 的定位。)

正如@Barmar 在评论中指出的那样,没有预先确定 "end of file" 位置的输入流的一个更好的例子是链接到终端的标准输入。

Is there a way to use the feof function?

是的,有。 一个输入函数返回一个值表明它没有更多的输入需要处理之后,你可以调用feof()and/orferror()来判断是否该情况是由到达输入末尾或某些错误情况引起的。

这是 feof()ferror() 函数的唯一有效用途。

指示不再有输入剩余的结果因函数而异。例如fgetc()returns的值EOFfgets()returns一个空指针,而fread()returns某个值小于请求的记录数。您需要阅读每个输入函数的文档以了解其工作原理。

迟到的答案,但是要添加 Stephen Kochan 的 Programming in C(第 4 版)中的有用引述,p。 367:

Remember, feof() tells you that an attempt has been made to read past the end of a file, which is not the same as telling you that you just read the last data item from a file. You have to read one past the last data item for feof() to return nonzero.

我的斜体。