提问人:Miket25 提问时间:7/23/2017 最后编辑:Antti Haapala -- Слава УкраїніMiket25 更新时间:9/10/2020 访问量:2257
是否可以区分 fgets 返回的错误
Is it possible to distinguish the error returned by fgets
问:
在查看 §7.21.7.2, 3 的 ISO C11 标准时,返回值是关于概要代码的:fgets
#include <stdio.h>
char *fgets(char* restrict s, int n, FILE* restrict stream);
如果成功,fgets 函数返回 s。如果遇到文件末尾,并且没有将任何字符读入数组,则数组的内容保持不变,并返回 null 指针。如果在操作过程中发生读取错误,则数组内容不确定,并返回 null 指针。
该标准规定,对于文件末尾返回一个空指针,并且没有读入任何字符或发生读取错误。我的问题是,仅从 和 返回的空指针中,有没有办法区分这两种情况中的哪一种导致了错误?fgets
答:
如果故障是由文件结束条件引起的,则在流上额外设置 eof 指示符(参见 feof())。在这种情况下,str 指向的数组的内容不会改变。 如果失败是由其他错误引起的,请在流上设置错误指示器(参见 ferror())。str 指向的数组的内容是不确定的(它甚至可能不是以 null 结尾的)。
因此,您需要检查并确定错误。feof()
ferror()
从这个网站
有没有办法区分这两种情况中的哪一种导致了错误?
是的,使用和区分。@Nothing什么都没有feof()
ferror()
然而,正确使用很重要。请考虑以下两个代码:
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";
}
第二个正确地测试返回值,如 OP 所建议的那样。NULL
第一个可能会遇到一个罕见的问题。测试一个标志。此标志可能是由先前的 I/O 函数调用设置的,因此这不一定是错误的原因。最好检查结果,看看这个函数是否失败。ferror(stream)
stream
fgets()
fgets()
如果代码在检测到错误后要继续使用,请确保在继续之前清除错误 - 例如尝试重试。stream
if (ferror(stream)) {
clearerr(stream);
return "Input error occurred");
}
请注意,这将清除错误标志和文件末尾标志。clearerr()
这同样适用于 ,但大多数代码都编写为在文件结束为 true 后退出。feof()
stream
有第三种病态的接收方式,既不返回也不返回,详见 fgets() 返回 NULL with a short buffer compliant?。仔细阅读 C 规范有 3 个“如果”,其中可能没有一个是真的,因为规范缺乏 - 这意味着 UB。NULL
feof()
ferror()
NULL
评论
ferror()
feof(
) 和ferror()
就是为此而设计的。请注意,while (!feof(file))
总是错误的。