我对使用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!
使用循环和我的方式有什么区别?
OP的方法有很多问题。
缓冲区大小错误
fgets(string, 30, file);
夸大了缓冲区大小10,允许未定义的行为(UB),由于潜在的缓冲区溢出。
输入结果未检查
fgets(string, 30, file);
不检查fgets()
的返回值
在检查返回值之前,不知道string
的内容是否更新正确
Extra'n'
puts(string);
附加一个额外的'n'
。
不能读取整个文件
一次读取可能不会读取整个内容。使用循环。
备选:读取直到fgets()
返回NULL
。
while (fgets(string, sizeof string, file)) {
fputs(string, stdout);
}
从手册页:
fgets()函数将从流中读取字节到s所指向的数组中,直到读取n-1个字节,或者a被读取并传输到s中,或者遇到文件结束条件。在最后一个字节被读入数组后立即写入一个空字节。
根据这一点,fgets在遇到换行符、EOF条件、输入错误或读取n - 1个字符时停止读取。因此,您的方法只从文件中读取一行。如果你只需要读一行,那就太好了。
为了逐行读取整个文件,在循环中调用fgets,直到达到EOF条件。另一种方法是使用read将整个文件读入缓冲区,然后对其进行解析。或者在循环中调用getc逐个字符读取。
编辑:在你的代码中,fgets试图读取(n - 1) 29个字节的内存,而你只分配了10个字节的缓冲区。这会导致未定义的行为。不应该读取未分配的内存。使用sizeof (string)代替。"Hello World !">
返回值:
成功完成后,fgets()返回s。如果流位于文件结束处,则设置流的文件结束指示器,fgets()返回空指针。如果发生读错误,应该设置流的错误指示器,fgets()将返回空指针,并设置errno来指示错误。
您没有检查fgets的返回值。