C标准:如果fgets返回非NULL,但已经遇到文件末尾,feof会返回真吗?

编程语言 2026-07-09
while (fgets(s, sizeof(s), f) != NULL) {
    if (feof(f)) {
        break;
    }
}

请考虑以下情形:对 fgets 的调用将一个或多个字符读入到 s,但随后停止读取,恰恰因为遇到了文件结束。C标准规定,在这种情况下,fgets 不会返回空指针,因此循环体将执行。在那次迭代中,按照标准,feof 是否一定会返回true?这大概是个傻问题,但我一直觉得只有当I/O函数的返回值真正指示失败时,才应该调用 feof(以及 ferror)。

解决方案

设想这样的情形:fgets 到达 EOF,但确实向 s 读入了一些内容,

fgets 将最多向 s 读取 sizeof(s)-1 字节。如果它读取的字节数少于该值、且未读取到换行符,但至少读取了1 字节,那么 fgets 将返回 s,并且EOF标记将被设置,这意味着对 feof 的调用将保证返回true。

The fgets 函数被归类为 字节输入函数,按 [C23草案标准] 第7.23.1p6段的定义。第7.23.3p11节进一步指出:

字节输入函数从流中读取字符,仿佛是通过连续调用 fgetc 函数

And section 7.23.7p3 regarding the fgetc function states:

如果流的end-of-file指示符被设定,或者流已经到达end-of-file,则该流的end-of-file指示符被设定,fgetc函数返回EOF。

这意味着如果 fgets 尝试读取超出文件结束的内容,那么EOF指示符将被设定,随后 feof 将返回true。

例如,如果 s 被定义为 char s[5],且文件中还剩下3 个字节要读取,则 s 将包含这3 个字节,后跟一个空字节(null字节),并且EOF指示符将被设定。

请注意,读取到文件结束但不越过它并不会设置EOF标志。因此,在上面的例子中,如果文件中还剩下4 个字节要读取,或者少于4 个但最后一个字节是换行符,则不会设置EOF;对 fgets 的下一次调用将返回 NULL,并设置EOF标记。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章