C语言 使用fgets()阅读文件

wpx232ag  于 2022-12-11  发布在  其他
关注(0)|答案(2)|浏览(149)

我对使用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!

waxmsbnn

waxmsbnn1#

使用循环和我的方法有什么区别?
OP的方式有很多问题。

错误的缓冲区大小

fgets(string, 30, file);夸大了缓冲区大小10,从而由于潜在的缓冲区溢出而允许 * 未定义的行为 *(UB)。

未检查输入结果

fgets(string, 30, file);不会检查fgets()的传回值。
在检查返回值之前,不知道string的内容是否正确更新。

额外'\n'

puts(string);会附加额外的'\n'

不一定读取整个文件

单一读取可能无法读取整个内容。请使用循环。
备选方案:读取,直到fgets()返回NULL

while (fgets(string, sizeof string, file)) {
  fputs(string, stdout);
}
mzsu5hc0

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的返回值。

相关问题