【问题标题】:Why does fgets() store a \0 after the last character in a buffer?为什么 fgets() 在缓冲区的最后一个字符之后存储一个 \0?
【发布时间】:2015-12-23 19:13:33
【问题描述】:

我一直在阅读 Linux 程序员手册,查找各种函数,并试图更深入地了解它们是什么/它们是如何工作的。

看着fgets()我读到“一个'\0'存储在缓冲区中的最后一个字符之后。

我已经通读了What does \0 stand for?,并且对\0 所代表的含义有非常深刻的理解(一个空字符,对吗?)。但我难以理解的是它与fgets() 的相关性,我真的不明白为什么它“需要”以空字符结尾。

【问题讨论】:

  • 因为 fgets() 返回 C 中的字符串(字符数组),并且根据 C 标准,这些字符串需要以 \0 字符结尾。
  • 因为'\0' 是字符串处理函数运行所必需的。它标志着数组的结束。请记住:您告诉fgets 缓冲区的大小,但它读取的字符串可能比这短。
  • 阅读:“我知道空值结束一个字符串。但是为什么我的字符串以空值结束?”
  • @LightnessRacesinOrbit 更像是“我知道字符串以 \0 结尾,但为什么 fgets() 也知道这一点?”
  • @Magisch: "f[ile] get s[tring]" 哈哈

标签: c


【解决方案1】:

正如您已经说过的,您可能知道\0 构成C 中所有字符串的结尾。根据C 标准,所有字符串都需要以\0 终止。

由于fgets() 生成一个字符串,该字符串当然会正确地以空值结尾。

请注意,对于 C 中的所有字符串函数,您使用或生成的任何字符串都必须以 \0 字符结尾。

【讨论】:

  • fgets 没有得到字符串,它制作字符串。
  • 它从文件中获取字符,并将它们变成一个字符串。但我同意你的反对并改写了我的回答。
  • 感谢您的简明解释。这实际上是有道理的,我觉得不明白有点傻>.<.>
【解决方案2】:

因为否则你不知道生成的字符串有多长。

fgets 的参数之一是要读取的最大字符数,但这只是:最大值。如果您要求 512 个字符,但缓冲区中只有 8 个字符,那么您只会得到 8 个字符……并且在第 9 个插槽中为 NULL 来标记 C 字符串的逻辑结尾。

可以说,fgets 本来可以设计为返回读取的字符数,但是对于大多数目的,您只需要自己手动添加 NULL 字节,并且该函数必须找到一种方法来表示除了返回空指针之外的错误。

【讨论】:

    【解决方案3】:

    来自C standards

    fgets 函数读取的次数最多小于 1 由n 指定的字符 来自stream 指向的流 into s 指向的数组。之后没有额外的字符被读取 换行符(保留)或文件结尾之后。 一个空值 在读入最后一个字符后立即写入字符 数组

    这是为了确保在创建的字符串中没有缓冲区溢出(字符/内容不会超出提供的存储空间)。

    【讨论】:

    • 引用您的来源,并使用引用格式来格式化引用。
    【解决方案4】:

    正如我之前的所有人所说,fgets 从文件中读取字节并将它们转换为以空值结尾的标准 C 字符串。 \0 字节的终止反映了这个函数是面向文本的事实。

    如果您不想对从文件中读取的数据使用空终止,则它不是字符串(不是文本),而且行尾字节\n 也没有意义。在这种情况下,您可以使用fread

    所以 C 有两个函数可以从文件中读取:fgets 用于文本,fread 用于非文本(二进制数据)。

    顺便说一句,如果输入文件有一个真正的零值字节,fgets 会做一件不舒服的事情:它将继续读取直到它读取到行尾字节\n,并且输出“字符串”将有两个(或更多)空终止符。这作为文本没有任何意义,因此这是 fgets 面向文本且不适合任意数据的另一个示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-03
      • 2011-05-20
      • 1970-01-01
      • 2016-08-28
      • 1970-01-01
      • 2013-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多