我正在使用fgets逐行读取文件
char buffer[4096];
while (fgets(buffer, sizeof(buffer), file__1) != NULL) {
fprintf(file__2, "%s", buffer);
}
但是,man page of fgets()在“示例”部分中说明了这一点
while (fgets(line, line_max + 1, fp) != NULL) {
// Verify that a full line has been read ...
// If not, report an error or prepare to treat the
// next time through the loop as a read of a
// continuation of the current line.
...
// Process line ...
...
}
我的问题是,当fgets失败时,我如何“验证已读取整行”?
3条答案
按热度按时间guicsvcw1#
我如何才能“验证已读取整行”?
如果
fgets
返回NULL
,则意味着因此,当
fgets
返回NULL
时,您应该始终假设尚未读取整行。然而,当
fgets
不返回NULL
时,则意味着对fgets
的函数调用成功。但这并不一定意味着已经读取了一整行。有可能fgets
成功地填充了缓冲区,但该行太长,无法放入缓冲区。因此,确定是否读取了整行的最简单方法是检查fgets
返回的字符串是否包含换行符,例如使用函数strchr
。即使没有找到换行符,也不一定意味着没有读取整行。虽然POSIX defines a line to end with a newline character,但有可能您正在阅读的文本文件不遵循此规则。有可能您正在读取的文本文件的最后一行没有换行符,因此您会遇到文件结束之前没有换行符的情况。在这种情况下,即使在到达文件结尾之前没有遇到换行符,也可以将该行视为“一整行”。
在处理用户输入时,也可能会遇到文件结束而没有换行符的情况。例如,在Linux上,用户可以按CTRL+D来使用键盘输入文件结束。(在Microsoft Windows上,您可以使用CTRL+Z来执行相同的操作,但与Linux相比,这只会在行的开头起作用。)
由于上述原因,在找不到换行符的情况下,使用函数
feof
检查流的文件结束指示符可能是合适的,并在设置了流的文件结束指示符时忽略缺少的换行符。仅当如果打印出一条错误消息,提示该行太长,无法放入缓冲区,则不设置文件指示符。为了逐行读取文本文件并确保始终读取整行,我推荐以下代码:
hvvq6cgz2#
这并不是fgets()的失败;如果fgets失败并返回空指针,则控制流不会进入循环。
如果您正在阅读带有fgets的行,并且该行恰好长于参数2中传递给fgets()的大小,则需要处理整行检查。在这种情况下,fgets()返回传递的缓冲区,并且是“成功”。
你可以通过检查字符串中的最后一个字符是否是换行符来检查这个问题,然后你可以中止或者以某种方式处理它。
这样的东西会处理检查:
lmvvr0a83#
如何验证fgets()是否读取一行并处理错误(?)
回想一下C是如何从文本文件中定义 line 的:
文本流是一个有序的字符序列,组成 * 行 *,每行由零个或多个字符加上一个终止换行符组成。最后一行是否需要终止换行符是实现定义的。
很多案子容易处理。所有案子都难处理。
没有处理好的:
sizeof buffer
或更大。fprintf(file__2, "%s", buffer);
无法打印整行 *。'\n'
时,后面的一些代码可能会遇到麻烦,比如*strchr(buffer, '\n') = 0;
,以删除 * 潜在的 * 尾随'\n'
。fgets()
无法阅读使用宽字符的 text 文件。fgets()
和ferror()
已经为true时,fgets()
可能会正常工作并返回非NULL
。最好不要测试ferror()
,除非fgets()
返回NULL
,然后先测试feof()
。INT_MAX
。BUFSIZ
详细信息。额外的代码可以处理其中的一些。不幸的是,
fgets()
不够健壮。