我对使用fgets()阅读C语言中的文件有疑问。我见过有人使用循环来完成这一任务,但我跳过了循环部分,改为这样做。
使用循环和我的方法有什么区别?
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file = NULL;
char string[30];
file = fopen("test.txt", "r"); //test.txt contains "Hello world!"
if (file == NULL) {
puts("ERROR");
return 1;
}
fgets(string, 30, file);
puts(string);
fclose(file);
return 0;
}
输出:Hello world!
2条答案
按热度按时间waxmsbnn1#
使用循环和我的方法有什么区别?
OP的方式有很多问题。
错误的缓冲区大小
fgets(string, 30, file);
夸大了缓冲区大小10,从而由于潜在的缓冲区溢出而允许 * 未定义的行为 *(UB)。未检查输入结果
fgets(string, 30, file);
不会检查fgets()
的传回值。在检查返回值之前,不知道
string
的内容是否正确更新。额外
'\n'
puts(string);
会附加额外的'\n'
。不一定读取整个文件
单一读取可能无法读取整个内容。请使用循环。
备选方案:读取,直到
fgets()
返回NULL
。mzsu5hc02#
来自手册页:
fgets()函数将从流中读取字节到s指向的数组中,直到读取n-1个字节,或读取a并将其传输到s,或遇到文件结束条件。在将最后一个字节读入数组后,应立即写入空字节。
因此,fgets在遇到换行符、EOF条件、输入错误或读取了n - 1个字符时就会停止阅读,所以您的方法只读取文件中的一行,如果您只需要读取一行,这是非常好的。
要逐行读取整个文件,可以循环调用fgets,直到达到EOF条件。另一种方法是使用fread将整个文件读入缓冲区,然后解析它。或者通过循环调用getc逐字符读取它。
编辑:在你的代码中,fgets试图读取(n - 1)29个字节的内存,而你只为缓冲区分配了10个字节。这会导致未定义的行为。未分配的内存不应该被读取。请使用sizeof(string)代替。
“Hello World!”无法放入您为其分配了10个字节的缓冲区。
返回值:
如果流位于文件结尾,则设置流的文件结尾指示符,并且fgets()返回一个空指针。如果发生读取错误,则设置流的错误指示符,fgets()返回一个空指针,并且设置errno来指示错误。
您没有检查fgets的返回值。