【问题标题】:Proper length passed to fgets传递给 fgets 的正确长度
【发布时间】:2021-05-19 16:46:23
【问题描述】:

如果我有以下缓冲区:

char buffy[40]; // includes \0 at the end

fgets 函数应该有STLEN 40 还是 39?为什么?

char buffy[40];
while (fgets(buffy, 40, fp) != EOF)
    // ...

【问题讨论】:

  • This fgets documentation 可能会有所帮助。
  • buffy 业力杀手
  • (fgets(buffy, 40, fp) != EOF 不是正确的测试。针对NULL 进行测试。

标签: arrays c char c-strings fgets


【解决方案1】:

fgets 读入的字符数最多比它的第二个参数的值少一个。因此,在这种情况下,正确的值应该是 40。它将最多读取 39 个字符,并且数组的最后一个元素将用于存储 '\0'。这确保不会发生缓冲区溢出。作为成语

fgets(buf, sizeof buf, fp)

可以在(且仅当)数组 buf 的声明可见时使用。

请注意,将其称为fgets(buf, 39, fp) 并没有错,但这将导致它最多读入38 个字符,并且'\0' 将存储在buf[38] 中(如果已读取38 个字符)。数组的最后一个元素 (buf[39]) 根本不会被使用。

【讨论】:

    【解决方案2】:

    每 C11 7.21.7.2 The fgets function:

    概要

        #include <stdio.h>
        char *fgets(char * restrict s, int n,
             FILE * restrict stream);
    

    说明

    fgets 函数从 stream 指向的流中读取最多比n 指定的字符数少一个到s 指向的数组中。在换行符(保留)之后或文件结尾之后不会读取其他字符。在读入数组的最后一个字符之后立即写入一个空字符。

    所以

    char buffy[40];
    while (fgets(buffy, 40, fp) != NULL)
    

    是正确的,但是

    char buffy[40];
    while (fgets(buffy, sizeof(buffy), fp) != NULL)
    

    会更好。

    【讨论】:

      【解决方案3】:

      如果你会写例子

      fgets(buffy, 39, fp)
      

      那么函数fgets 将一无所知,实际上数组包含40 字符。:)

      所以数组的40-th元素不会被使用,会是多余的。

      当您使用 40 字符声明数组时

      char buffy[40]; 
      

      然后在fgets 的调用中使用所有这些,例如

      fgets(buffy, sizeof( buffy ), fp)
      

      该函数将从字符串中读取不超过 39 个字符,并在数组后面附加零字符 '\0'

      如果你需要从输入的字符串中去掉换行符'\n',那么你可以这样写

      buffy[ strcspn( buffy, "\n" ) ] = '\0'; 
      

      【讨论】:

        【解决方案4】:

        fgets docs中所述:

        参数:
        ...
        n - 这是要读取的最大字符数(包括最后的空字符)。通常,使用作为 str 传递的数组的长度。

        因此,如果您的数组长度为 40,则应使用 40。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-06
          • 1970-01-01
          相关资源
          最近更新 更多