我总是为系统调用的返回值而苦苦挣扎——它们是如此不一致! 通常我检查它们是否为 NULL 或 -1,然后调用
perror
。然而,对于 fgets
,手册页显示:
和gets()
成功时返回 s,出错时或在未读取字符的情况下发生文件末尾时返回fgets()
。NULL
这意味着返回值
NULL
不一定是错误 - 它也可以是 EOF。当到达文件末尾时是否设置 errno?这种情况我还可以打电话给perror
吗?
如果没有,判断调用是否返回错误与 EOF 的常用方法是什么。我想将
perror
与 NULL 字符串一起使用来表示错误,并使用自定义字符串表示 EOF。
使用
ferror
和 feof
来区分错误和 EOF。如果有错误,没有通用方法可以准确找出错误是什么,但您可以知道确实存在错误。
标准 C
(f)gets
(和 (f)getc
)不需要设置 errno
,尽管符合标准的库实现可以随意将 errno
设置为非零值。
Posix 确实要求
(f)get{c,s}
在读取错误时设置 errno
,但这仅在您确定存在读取错误后(通过调用 ferror
)对您有帮助。同样重要的是要记住,库函数永远不会将 errno
设置为 0,但即使没有发生错误,也可能将 errno
设置为非零值。因此,您不能测试 errno
来替代检查任何库函数(包括 fgets
)的错误返回。并且由于文件结尾不是一个错误,errno
(可能)不会在EOF上被修改,所以在这种情况下它的值是没有意义的。
根据fputs自己的文档,是的,EOF确实设置了errno。手册页间接暗示了这一点,而不是直接说明,希望能够对其进行修改。函数 fputs 返回一个整数,成功时为正数,失败时为 EOF。因此,错误处理 fputs 的关键是设置一个代码块,在调用 fputs 时检查它的返回值。以下是我如何处理 fputs 错误的片段。
if (fputs(buffer, stdout) == EOF)
{
fprintf(stderr, "fputs returned EOF: %s\n", strerror(errno));
// .. and now do whatever cleanup you need to do.
// or be lazy and exit(-1)
}
这里我将缓冲区的内容写入标准输出并检查 fputs 是否返回 EOF。 EOF 表示设置了错误代码,因此只要您遵循 fputs 手册页上的文档,您应该能够创建一堆 if 语句来检查 errno 可以设置的各种错误代码。
(1)什么是缓冲区?我在其他地方声明的一些字符数组。
(2) fprintf 的作用是什么?它将输出打印到传入的文件描述符,在本例中是标准错误(stderr...它像 stdout 一样打印到控制台,但针对错误)。
(3)什么是strerror?它是 string.h 标头中定义的函数,用于打印传入的错误代码的错误信息。它包含 errno 可设置的每个错误代码的信息。头文件 string.h 不应与 strings.h 混淆,后者是一个不包含 strerror(3) 的 BSD linux 头文件。
编辑:好吧,我搞砸了。您正在寻找有关 fgets 的答案,而不是 fputs。
要检查 fgets 上的错误,请执行以下操作
if (fgets(buffer, BUF_SIZE, myFile) == NULL)
{
// print out error as a string to stderr
fprintf(stderr, "fgets error occurred: %s\n", strerror(errno));
// do cleanup
}
// special: you also need to check errno AFTER the if statement...
问题是,出现错误的唯一方法是流变得不可读,这要么是由于权限原因,要么是尝试读取处于写入模式的内容。在有网络的情况下,有可能在读取过程中某些东西切断了您的连接,在这种情况下,您还需要检查 fgets if 语句后面的错误代码。但如果出现问题,它会设置错误代码。
至少在手册页正确的情况下是这样。有关详细信息,请参阅 Linux 手册页。唯一可以设置的错误代码是“我无法读取这个东西”代码,即 errno == EBADF