fgets,其中读取的字符数大于存储大小

fgets where the number of char read is bigger than the size of the storage

我正在看一个代码来学习东西,我看到了这样的东西:

void funRead(){
     char str[80];
     FILE *fi;
     fi = fopen("file","r");
     while(!feof(fi)){
        fgets(str, 200, fi);
        // do things
     }
     fclose(fi);
}

而且有效! (这是一个相当大的代码)我不明白为什么它可以工作所以我试图重现它(只是这一部分,几乎只是上面的代码)并且我的程序崩溃了(我在 Eclipse).它只在我写

时有效
fgets(str, 80, fi);

或另一个<80的号码,否则将无法使用。

我是不是漏掉了什么?

EDIT :我正在谈论的程序部分的屏幕截图 https://gyazo.com/c8847ccc36bbbe7a406a3260db8dd358 第 4 和第 26 行

在您的代码中,您定义了一个大小为 80 个字符的字符数组

char str[80];


fgets(str, 200, fi);

上面的语句意味着它正在从字符数组“str”中的文件“fi”中读取200个字符" 大小 80。 您不能在大小为 80 的数组中复制 200 个字符。

要么扩大字符数组,要么一次从文件中读取 80 个或更少的字符。

编辑:程序崩溃的原因是因为它正在访问非法内存位置。这并不意味着如果你索引一个大于数组大小的位置它就会崩溃,它只是意味着如果不允许访问该内存位置它可能会崩溃。 这就是原因,您提到的代码可能有效(纯属偶然),尽管 200 部分是错误的。如果它 运行 然后 运行 它多次它可能至少会崩溃一次。

fgets(str, 200, fi);确实是错误的,因为它是告诉fgets往上读 到 199 个字符,而实际上 str 最多可以存储 79 个字符(不是 包括 '[=17=]' 终止字节),这就是为什么 "works"1fgets(str, 80, fi);.

一般来说,像这样使用 sizeof 是个好主意2:

char str[80];
fgets(str, sizeof str, fi);

使用 sizeof 您将获得正确的尺寸,即使您稍后决定更改 str.

的大小

really wrong 的一件事是:

while(!feof(fi))
{
    ...
}

代码应该做的是:

while(fgets(str, sizeof str, fi))
{
    // do things
}

这是读取整个文件的正确方法。


注释

1我把作品放在引号里是因为代码检查何时停止的方式 读数不正确。然而 fgets(str, 80, fi) 是正确的调用。

2请注意,只有当 str 是 大批。如果它是一个指针并且你为它分配了内存,那么你不能使用 sizeof,例如:

size_t len = 80;
char *str = malloc(len);
if(str == NULL)
{
    // error handling
}

fgets(str, len, fi); // <-- do not use sizeof here, but the variable