我总是在努力处理系统调用的返回值 - 它们只是如此不一致!
通常我会检查它们是否为NULL或-1,然后调用perror
。但是,对于fgets
,手册页说:
gets()
和fgets()
成功返回,NULL
出错,或者文件结束时没有读取任何字符。
表示返回值NULL
不一定是错误 - 它也可以是EOF。到达文件末尾时是否设置了错误?在这种情况下我还可以拨打perror
吗?
如果没有,告诉调用是否返回错误与EOF的常见方法是什么。我希望perror
使用NULL字符串表示错误,并使用自定义字符串表示EOF。
答案 0 :(得分:6)
使用ferror
和feof
区分错误和EOF。没有一般方法可以确切地找出错误是什么,如果有错误,但你可以告诉它有错误。
标准C (f)gets
(和(f)getc
)不需要设置errno
,尽管符合标准的库实现可以将errno
设置为非零值将。
Posix确实要求(f)get{c,s}
设置errno
读取错误,但这只会在您确定存在读取错误(通过调用ferror
)后帮助您。同样重要的是要记住库函数永远不会将errno
设置为0,但即使没有错误发生,也可以将errno
设置为非零值。因此,您无法测试errno
作为检查任何库函数(包括fgets
)的错误返回的替代。由于文件结尾不是一个错误,errno
将(可能)不会在EOF上修改,因此在这种情况下它的值是没有意义的。
答案 1 :(得分:1)
根据fputs自己的文档,是的,EOF确实设置了errno。手册间接地推断它,而不是直接说明它,希望将被修改。函数fputs返回一个整数,该函数在成功时为正,在失败时为EOF。因此,错误处理fput的关键是设置一个代码块,用于检查fput被调用时的返回值。以下是我如何被教导处理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表示设置了错误代码,因此只要您按照fput手册页上的文档进行操作,就应该能够创建一堆if语句来检查errno可以设置的各种错误代码。
(1)什么是缓冲?我在其他地方声明了一些字符数组。
(2)fprintf做什么?它将输出打印到传入的文件描述符,在这种情况下是标准错误(stderr ...它打印到控制台,如stdout,但是出错)。
(3)什么是strerror?它是string.h头文件中定义的函数,它打印传入的错误代码的错误信息。它包含可以设置为errno的每个错误代码的信息。标题string.h不应该与strings.h混淆,strings.h是一个不包含strerror的BSD linux头文件(3)。
编辑:好的,我搞砸了。你正在寻找关于fgets而不是fputs的答案。
要检查fgets上的错误,请执行以下操作
if (fgets(buffer, BUF_SIZE, myFile) == NULL)
{
// your file isn't readable. Check permissions
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