在查看fgets
§7.21.7.2, 3 的 ISO C11 标准时,返回值是关于概要代码的
#include <stdio.h>
char *fgets(char* restrict s, int n, FILE* restrict stream);
如果成功,fgets函数将返回s。如果遇到文件结尾,并且没有字符读入数组,则数组的内容保持不变,并返回空指针。如果在操作过程中发生读取错误,则数组内容不确定,并返回空指针。
该标准规定,为文件结尾返回空指针,并且没有读入任何字符或发生读取错误。我的问题是,仅从fgets
和返回的 null 指针来看,有没有办法区分这两种情况中的哪一种导致了错误?
有没有办法区分这两种情况中的哪一种导致了错误?
是的,使用feof()
和ferror()
来区分。 @Nothing 什么都没有
然而,正确使用很重要。 考虑两个代码:
char buf[100];
fgets(s, sizeof s, stream);
if (feof(stream)) return "End-of-file occurred";
if (ferror(stream)) return "Input error occurred";
if (fgets(s, sizeof s, stream) == NULL) {
if (feof(stream)) return "End-of-file occurred";
if (ferror(stream)) return "Input error occurred";
return "Should never get here";
}
第二个正确地测试了针对NULL
的返回值,如OP所建议的那样。
第一个可能会遇到一个罕见的问题。ferror(stream)
测试标志。此标志可能是由先前对stream
的 I/O 函数调用设置的,因此此fgets()
不一定是导致错误的原因。 最好检查fgets()
的结果,看看这个函数是否失败。
如果代码要在检测到错误后继续使用stream
,请确保在继续之前清除错误 - 例如尝试重试。
if (ferror(stream)) {
clearerr(stream);
return "Input error occurred");
}
请注意,clearerr()
会清除错误和文件结束标志。
这同样适用于feof()
,但大多数代码都是为了在文件结尾为真后退出使用stream
。
有第三种病理方法来接收NULL
,feof()
和ferror()
都不会返回NULL
如 fgets(( 返回带有短缓冲区的 NULL 是否兼容?中所述。 仔细阅读 C 规范有 3 个"如果",其中可能不是真的,因为缺少规范 - 这意味着 UB。
如果失败是由文件结束条件引起的,则在流中另外设置 eof 指示器(请参阅 feof(((。在这种情况下,str 指向的数组的内容不会更改。 如果故障是由其他错误引起的,则在流中设置错误指示器(请参阅 ferror(((。str 指向的数组的内容是不确定的(它甚至可能不是以 null 结尾的(。
因此,您需要检查feof()
和ferror()
以确定错误。
从本网站