是否可以区分 fgets 返回的错误

Is it possible to distinguish the error returned by fgets

提问人:Miket25 提问时间:7/23/2017 最后编辑:Antti Haapala -- Слава УкраїніMiket25 更新时间:9/10/2020 访问量:2257

问:

在查看 §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

c fgets eof feof ferror

评论

0赞 too honest for this site 7/23/2017
我怀疑这是有原因的。ferror()
4赞 Jonathan Leffler 7/23/2017
函数 feof() 和 ferror() 就是为此而设计的。请注意,while (!feof(file)) 总是错误的
0赞 Pushan Gupta 7/23/2017
当心,在你回答之前......“JUST from fgets,以及返回的空指针”
0赞 Frankie_C 7/23/2017
无论如何,如果将输入缓冲区设置为全部 0,您还可以看到部分读取的内容。
1赞 ad absurdum 7/23/2017
@Frankie_C-- “如果在操作过程中发生读取错误,则数组内容不确定”。

答:

9赞 Nothing Nothing 7/23/2017 #1

如果故障是由文件结束条件引起的,则在流上额外设置 eof 指示符(参见 feof())。在这种情况下,str 指向的数组的内容不会改变。 如果失败是由其他错误引起的,请在流上设置错误指示器(参见 ferror())。str 指向的数组的内容是不确定的(它甚至可能不是以 null 结尾的)。

因此,您需要检查并确定错误。feof()ferror()

这个网站

9赞 chux - Reinstate Monica 7/23/2017 #2

有没有办法区分这两种情况中的哪一种导致了错误?

是的,使用和区分。@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)streamfgets()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。NULLfeof()ferror()NULL

评论

0赞 Zerumi 11/9/2023
也许返回字符串不是一个好习惯,因为程序可能包含 i18n 元素,因此更喜欢定义带有错误代码的枚举并返回枚举值。