【问题标题】:What does it mean by "fgets will not stop if it encounters a NUL"“如果遇到NUL,fgets不会停止”是什么意思
【发布时间】:2020-08-21 23:08:01
【问题描述】:

所以,我在StackOverflow看到了下面的答案

fgets 在 C99 或当前标准 C11 中实际上并未被弃用。但是该教程的作者是对的,fgets 在遇到 NUL 时不会停止,并且没有机制来报告它对此类字符的读取。

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

“fgets遇到NUL不会停止是什么意思?请用简单的代码sn-p解释一下。

链接:Why is the fgets function deprecated?

【问题讨论】:

  • 给我们看帖子。
  • @anastaciu 已编辑。
  • 那句话有什么不清楚的地方?假设输入包含以下字节:41 41 41 41 00 4a 4b 4c 4d 10 4e 4f 你认为fgets 读取了多少字节?
  • 我猜困惑是NULL 与 C 中的\0 字符不同
  • fgets() 读取一行,直到找到 '\n',因此如果数据包含 NUL 字符,它将终止字符串并打印 NUL 和 \0 之间的所有子字符串“没有任何线索就不会出现。BUT fgets 旨在读取文本,并且 nul 字符会出乎意料。因此,说 fgets 因这个原因被弃用就像说 strcpy是不安全的,因为如果缓冲区包含字符串终止符,它不会复制缓冲区中的数据。

标签: c null fgets


【解决方案1】:

按照惯例,C 中的字符串是“NUL 终止的”。这意味着字符串的结尾由“NUL”字符的存在决定。 NUL 字符是字符 '\0' 或更具体地说是值为 0 的 char。所有 C 字符串文字都是以 NUL 结尾的,并且大多数接受字符串的 C API(在标准库和大多数其他库中编写在 C 中)期望这些字符串以 NUL 终止。

意味着一个 NUL 字符不能用作预期 NUL 终止的 API 中的正常数据值。这些 API 会将 NUL 字符视为字符串数据的有意义部分,而不是字符串的结尾。例如,strlen("foo\0bar") 是 3,而不是 7。

fgets 从文件流中读取字符数据。但该文件可以包含 NUL 字符。该帖子的意思是fgets 将像对待任何其他字符一样对待文件中的 NUL 字符。 fgets 会以 NUL 终止给定的字符串,但如果文件包含 NUL 字符,fgets 将尽职尽责地读取它们。

这就是帖子警告的内容:fgets 不会将 NUL 字符与任何其他字符区别对待,而大多数其他 C API 函数会这样做。因此,如果您将由fgets 生成的字符串传递给一些需要 NUL 终止的 API,如果该文件包含 NUL 字符,您可能会遇到问题。

【讨论】:

    【解决方案2】:

    Fgets 仅用于文本文件。为什么文本文件中会有空值? 因此,对于大多数用途来说,它非常好。在最坏的情况下,您看不到空字符之后的内容,或者您​​将下一行连接到其中,因为您认为它是不完整的行。

    如果你想检测你的 fget()ed 缓冲区包含空值,用 chr 1 预填充它,然后查看空值以查看 chr1 是否已被覆盖。或使用 ftell 查看是否已读取的内容多于缓冲区大小。 请记住,在 Windows 上,由于行尾转换,此计数可能会减少 1,但如果您认为文本确实 /not/ 包含直到 null 的行尾,那么这不是问题,真的。

    【讨论】:

    • 在使用 UTF16 编码的文本文件中发现 空字符(作为单个字节)的常见原因。当然,使用fgets() 读取该文本文件并不是最好的工具。然而,对于用户来说,提供这样的文件很容易。当读取正确的 16/32 位块时,发现 16 位 空字符 仍然是不寻常的。
    猜你喜欢
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 2012-11-02
    相关资源
    最近更新 更多