【问题标题】:Does fgets() always terminate the char buffer with \0?fgets() 是否总是用 \0 终止字符缓冲区?
【发布时间】:2009-11-02 09:27:38
【问题描述】:

即使已经到达 EOF,fgets() 是否总是以 \0 终止字符缓冲区?看起来确实如此(在 ANSI K&R 书中介绍的实现中确实如此),但我想我会要求确定。

我猜这个问题适用于其他类似的函数,例如gets()。

编辑:我知道 \0 在“正常”情况下附加,我的问题针对 EOF 或错误条件。例如:

FILE *fp;
char b[128];
/* ... */
if (feof(fp)) {
    /* is \0 appended after EACH of these calls? */
    fgets(b, 128, fp);
    fgets(b, 128, fp);
    fgets(b, 128, fp);
}

【问题讨论】:

  • 总是检查fgets()的返回值:if (fgets(...) == NULL) /* indeterminate array */;
  • 您可能是对的,但是,我看到还有其他答案指出始终附加\0,即使fgets() 返回NULL

标签: c fgets


【解决方案1】:

永远不要使用gets,因为你永远不能保证它不会溢出你给它的任何缓冲区,所以虽然它在技术上总是终止读取字符串,但这实际上并没有帮助。

【讨论】:

    【解决方案2】:

    永远不要使用gets!!

    7.19.7.2 fgets 函数 概要 1 #include char *fgets(char * restrict s, int n, 文件 * 限制流); 描述 2 fgets函数读取最多比字符数少一个 由 n 指定的从流指向的流到指向的数组中 由 s.换行符后不读取其他字符 (保留)或文件结束后。写入空字符 在最后一个字符读入数组后立即。 退货 3 如果成功,fgets 函数返回 s。如果遇到文件结尾 并且没有字符被读入数组,数组的内容 保持不变并返回一个空指针。如果发生读取错误 在操作过程中,数组内容是不确定的并且为空 返回指针。

    所以,是的,当fgets() 不返回 NULL 时,目标数组总是有一个空字符。

    如果fgets() 返回 NULL,则目标数组可能已更改并且可能没有空字符。从fgets() 获取 NULL 后永远不要依赖数组。


    编辑添加示例

    $ 猫 fgets_error.c #include 无效 print_buf(char *buf, size_t len) { 诠释 k; printf("%02X", buf[0]); for (k=1; k

    看到了吗? buf 中没有 NUL :)

    【讨论】:

    • @pmg re“从不使用gets!!”,你有文件读取的替代方法吗?
    • @atlex2:是的,替代方案是fgets()
    • getline 是更好的选择,如果您可以限制自己使用最近的类似 POSIX 的系统,例如 Linux 和 OSX(或者在缺少它的平台上拥有自己的版本)。
    【解决方案3】:

    人 fgets:

    fgets() 从流中最多读入一个小于 size 的字符并将它们存储到 s 指向的缓冲区中。在 EOF 或换行符后停止读取。如果读取了换行符,则将其存储到缓冲区中。 “\0”存储在缓冲区中最后一个字符之后。

    【讨论】:

      【解决方案4】:

      如果您确实以二进制模式“rb”打开文件,并且如果您想使用 fgets 逐行读取文本,您可以使用以下代码来保护您的软件丢失文本,如果错误包含的文本'\0' 字节。 但最后就像提到的其他人一样,如果流包含'\0',通常你不应该使用fgets


      size_t filepos=ftell(stream);
      fgets(buffer, buffersize, stream);
      len=strlen(buffer);
      /* now check for > len+1 since no problem if the 
         last byte is 0 */
      if(ftell(stream)-filepos > len+1) 
      {
          if(!len) filepos++;
          if(!fseek(stream, filepos, SEEK_SET) && len)
          {
              fread(buffer, 1, len, stream);
              buffer[len]='\0';
          }
      }
      

      【讨论】:

        【解决方案5】:

        是的。来自CPlusPlus.com

        从流中读取字符并将它们作为 C 字符串存储到 str 中,直到读取 (num-1) 个字符或到达换行符或文件结尾,以先到者为准。

        换行符使 fgets 停止读取,但它被认为是有效字符,因此它包含在复制到 str 的字符串中。

        在读取的字符之后会自动在 str 中附加一个空字符,以表示 C 字符串的结束。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-13
          • 1970-01-01
          • 2012-09-21
          • 1970-01-01
          • 1970-01-01
          • 2015-07-08
          相关资源
          最近更新 更多