fgets() 在数组中存储什么

what does fgets() store in the array

所以我在 Kernighan 和 Ritchie 的书中查找了 fgets()。所以它是这样的:

char *fgets(char *s, int n, FILE *stream)

fgets最多读取n-1个字符到数组s中,遇到换行符停止;换行符包含在以“\0”结尾的数组中。 fgets returns s,如果文件结束或发生错误则为 NULL。

所以我的困惑是,如果文件包含以下行

Earth is the third planet from the Sun
The only astronomical object known to harbor life 
About 29% of Earth's surface is land consisting of continents and islands

如果我使用 fgets() 读取文件,那么 's' 会包含什么? 它会包含 "Earth is the third planet from the Sun\n[=12=]" 还是会包含 "Earth is the third planet from the Sun[=13=]\n" 或其他内容?

好的,让我们写一些代码看看数组中存储了什么。

#include <stdio.h>

int main(void) {
    char s[64];
    int size = sizeof(s);
    int i;
    /* initialize array */
    for (i = 0; i < size; i++) s[i] = (char)0xff;

    /* call fgets() */
    fgets(s, size, stdin);

    /* print contents of the array */
    for (i = 0; i < size; i++) {
        printf("%02X ", (unsigned char)s[i]);
        if ((i + 1) % 16 == 0) {
            int j, offset = (i / 16) * 16;
            for (j = 0; j < 16; j++) {
                putchar(0x20 <= s[offset + j] && s[offset + j] < 0x7f ? s[offset + j] : '.');
            }
            putchar('\n');
        }
    }
    return 0;
}

输入(如问题中指定):

Earth is the third planet from the Sun
The only astronomical object known to harbor life 
About 29% of Earth's surface is land consisting of continents and islands

Output:

45 61 72 74 68 20 69 73 20 74 68 65 20 74 68 69 Earth is the thi
72 64 20 70 6C 61 6E 65 74 20 66 72 6F 6D 20 74 rd planet from t
68 65 20 53 75 6E 0A 00 FF FF FF FF FF FF FF FF he Sun..........
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................

它包含"Earth is the third planet from the Sun\n[=14=]"

我们还要检查一下指定的缓冲区长度小于存储所需大小的情况。

fgets(s, size, stdin); 替换为 fgets(s, 32, stdin);,我得到 output:

45 61 72 74 68 20 69 73 20 74 68 65 20 74 68 69 Earth is the thi
72 64 20 70 6C 61 6E 65 74 20 66 72 6F 6D 20 00 rd planet from .
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................

这表明在这种情况下它将存储 n-1 个字符和 1 个终止空字符。

这是 C 标准本身对 fgets 的描述-

§ 7.21.7.2

The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array.

这里有 2 个主要注意点来回答您的问题。

  • The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s

    所以您传递的 n 很重要,它表示要读取的最大字符数,包括空终止符

    因此,如果您将 100 作为 n 传递,它将从文件中读取最多 99 个字符,然后将 '[=14= ]' 最后。

    “至多”是什么意思?好吧,fgets 会在遇到新行时立即停止(或者如果文件刚刚结束,显然)。

    No additional characters are read after a new-line character (which is retained) or after end-of-file

    这意味着 fgets 将从文件中读取 最多并包括 第一个换行符 \n,或者最多 n - 1 个字符- 以先发生者为准

  • A null character is written immediately after the last character read into the array.

    也就是说,在从文件中读取所有字符完成后,根据前面提到的条款,将[=19=]写入缓冲区。

所以为了回答你的问题,在你的示例文件中,如果你这样做了 fgets(s, 1024, file) - 假设 s 是一个指向可以容纳 的字符 array/buffer 的指针至少 1024 个字符并且 file 是一个 FILE* 到你的文件 - 你会得到结果

Earth is the third planet from the Sun\n[=24=]

因为 fgets 在第一个 \n 处停止,因为那发生在超过 n 指示的字符限制之前。然后它将 [=19=] 放在缓冲区的末尾。

请注意 fgets 不仅写入您传递给它的缓冲区,而且 returns 相同的缓冲区 - 不要被这个混淆.它们是指向同一位置的指针。

如您所说,char *fgets(char *str, int n, FILE *stream) 从指定流(stdin、文件..)中读取一行,函数读取行并在到达 文件末尾时停止 或当读取 (n-1) 个字符时.

因此,在您的示例中 s 将包含 Earth is the third planet from the Sun\n[=12=]

另一种情况,当行中的字符数大于(n-1)。令 n = 10,则 s 将包含 Earth is [=14=].