我试图了解何时应使用stdio函数assert
。
例如,如果我在有效的clearerr()
上fread()
或fwrite()
并获得了一个短计数而FILE*
为真,该怎么办?
根据我到目前为止所读的内容,ferror
和fread()
很健壮,并且会阻塞和/或重试(如果在较低级别的函数中可能发生锁和/或中断),因此使用fwrite()
似乎毫无意义,因为clearerr()
或fread
错误将是灾难性的,试图恢复毫无意义。
此外,fwrite
仅告诉我有错误,而不是错误。
ferror()
答案 0 :(得分:8)
clearerr
至少有一个现实的用例:当您想模拟未以独占模式打开的文件上的tail -f
时。这意味着另一个(或许多其他)进程在文件末尾写入数据,并且一个进程甚至在到达文件末尾后重复读取 以便查看是否有新数据到达。在这种情况下,可能看起来像这样:
for (;;) {
if (NULL == fgets(line, sizeof(line), fd)) {
sleep(n);
clearerr(fd); // reset EOF condition
}
else {
fputs(line, fdout);
}
}
答案 1 :(得分:3)
设置FILE
的错误状态的功能(由ferror
报告)即使以后成功调用也无法清除。同样,如果您在读取文件时遇到文件末尾,即使文件以后有更多可用数据,也不会自动清除它。
基本上,这意味着如果您正在使用ferror
检查错误状态,并且有某种方法可以从中恢复,则ferror
会一直指示错误直到您使用clearerr
。
在您的示例中,如果仅使用返回值fread
作为终止读取的条件(即EOF和任何类型的错误都被认为是最终错误),则无需{{1} }:只需进入clearerr
(也许可以使用fclose
来确定是否打印错误消息)。
反之,如果ferror
实际上是一个流,稍后可以在其上成功读取,并且您检测到(或假设)了特定的条件并重试,则应FILE
在重试或您将在以后的尝试中继续看到旧的错误情况。
同样,如注释中所指出,clearerr
也会清除文件末尾状态,因此在使用clearerr
检查文件末尾时也是如此。 (不过请注意,阅读时通常shouldn't use !feof(file)
as the loop condition。)
答案 2 :(得分:2)
clearerr()
从流中清除错误和EOF标志。
说FILE
是这样的:
typedef struct {
int fd;
char *buf;
int error;
int eof;
} FILE;
FILE *file;
这会将file->error
和file->eof
设置为0
。
执行此操作的某些原因包括文件I / O,例如文件提供EOF时,但随后会附加另一个程序(或另一个线程等)。如果在执行此操作后清除错误,则可以使程序充当tail -f
的替代品。
答案 3 :(得分:1)
clearerr()
清除错误和文件结束标志。
学步使用clearerr()
:
// Return -1 on end-of-file
// Return -2 on rare file error
// Else return the unsigned char value
int my_get_quandry() {
// At this point, the file end-of-file flag may be set.
// At this point, the file file error flag may be set.
// They may both be set.
// Attempt to read another
int ch = fgetc();
if (ch != EOF) {
return ch;
}
// Now was the EOF due to a end-of file or error?
// feof() is true if end-of-file just occurred OR if end-of-file was set earlier
// ferror() is true if error just occurred OR if error was set earlier
// If only one feof() or ferror() is true, we know why EOF just occurred,
// Yet if both set, we do not know.
...?
}
使用clearerr()
// Return -1 on end-of-file
// Return -2 on rare file error
// Else return the unsigned char value
int my_get_crystal() {
clearerr(stdin);
// Attempt to read another
int ch = fgetc();
if (ch != EOF) {
return ch;
}
// Now EOF due to at most one reason
if (feof(stdin)) return -1;
if (ferror(stdin)) return -2;
// if code reaches this point, it is due to the odd-ball platform of `char` having the
// same range as `int`. But let us leave that platform for another day.
return ch;
}