【问题标题】:fgets prompt limited to 1024 Bytesfgets 提示限制为 1024 字节
【发布时间】:2016-05-02 19:48:12
【问题描述】:

我一直在努力解决一个非常简单的问题,用 C 编写一个小程序。

只要输入的大小不超过 1024 字节,通过fgets() 获取输入(命令、参数、要执行的标志)就可以正常工作。输入 1024 个字符后,不再接受任何字符——提示停止。我认为问题的原因不在于fgets() 参数/配置,否则它至少会将输入变为定义的大小而不是阻塞。

我怎样才能让fgets() 接受与_SC_LINE_MAX (2048) 字节/字符一样长的行?

【问题讨论】:

  • 您使用的是什么操作系统/shell?
  • 这很可能是shell的限制。将输入放入一个文件中,并使用 shell 的 IO 间接机制将文件的内容通过管道传输到程序的标准输入。
  • 如果您输入的是长行,问题在于系统上的终端驱动程序(但它比 Mac OS X 更慷慨)。
  • 请分享您的代码,即使它可能非常简单。然后其他人可以验证您的发现
  • @RSahu:很公平。精确和简洁并不总是齐头并进的。我在 Mac OS X 10.11.4 上进行了测试,限制为 1024(1023 个非换行符加上一个换行符)。这很奇怪:我很确定以前我在 256 个字符时遇到了这个限制——但自从我上次明确测试它以来已经有一段时间了,当我尝试复制某些东西时,这个问题通常会表现出来(一大块JSON,例如)从一个网站到一个文件。

标签: c prompt fgets


【解决方案1】:

终端驱动程序限制输入线的长度

正如我在 cmets 中指出的,问题几乎可以肯定是您的终端驱动程序不允许您输入长度超过 1024 字节的行;它不会分配更多的存储空间。这适用于“规范”模式;有关详细信息,请参阅 Canonical vs non-canonical terminal input

有一个简单的测试程序(现在有问题)。当我在 Mac OS X 10.11.4 上运行它时,我可以输入 1023 个字符加上换行符,或者 1024 个字符但没有换行符,直到我删除一个。

为了记录,输入字符串是:

12345678901234567890123456789X123456789Y123456789Z123456789A123456789B123456789C123456789D123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123456789r123456789s123456789t123456789s123456789t123456789u123456789v123456789w123456789x123456789y123456789z123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123456789r123456789s123456789t123456789u123456789v123456789w123456789x123456789y123456789z123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123456789r123456789s123456789t123456789u123456789v123456789w123456789x123456789y123456789z123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123

如果您使用换行符复制并粘贴它,它可能会输入 OK。如果您添加更多字符,您可能会收到终端提示音。

还有另一个问题 (fgets() is limited to 1024 bytes — what can I use instead?) 几乎肯定遇到了同样的问题,而且确实没有得到太多有用的帮助。

如果您使用诸如 GNU readline 库之类的库,它可以将终端置于非规范模式,然后可以处理更长的行,因为终端驱动程序不会等到输入换行符才发送数据到程序。重新构建对终端输入行长度有更大限制的内核在类 Linux 系统上名义上是一种选择,但对于普通程序员来说不是一项任务。

LINE_MAX及相关宏的含义

还要注意_SC_LINE_MAX 是用于确定LINE_MAXsysconf() 代码,它必须至少是{POSIX2_LINE_MAX} 的值(最小2048),记录为:

除非另有说明,否则当实用程序被描述为处理文本文件时,实用程序(标准输入或其他文件)的输入行的最大长度(以字节为单位)。长度包括尾随<newline> 的空间。

请注意,终端不是文本文件。此限制表明,诸如grep 之类的实用程序不得错误处理 2048 字节长的行,但它可能会被更长的行混淆(例如,因为它读取行的 2048 字节块,并且执行“行开头”匹配长行的第二个或后续块的开头)。

POSIX 注释的基本原理:

{LINE_MAX}

这是一个影响所有实用程序的全局限制,除非另有说明。 POSIX.1-2008 的系统接口卷中的{MAX_CANON} 值可能会进一步限制来自终端的输入行。 {LINE_MAX} 值是很多争论的主题,它是希望拥有无限行数的人和理解许多历史实用程序是用固定缓冲区编写的人之间的折衷方案。实用程序编写者经常选择 UNIX 系统常量 BUFSIZ 来分配这些缓冲区。因此,一些实用程序的 I/O 线限制为 512 字节,而其他实用程序则达到 4096 字节或更大。

需要注意的是{LINE_MAX}只适用于输入行长度; POSIX.1-2008 中没有限制输出行长度的要求。 awksedpaste 等实用程序理论上可以构造比它们收到的任何输入行更长的行,具体取决于使用的选项或应用程序的指令。他们不需要将其输出截断为{LINE_MAX}。处理这个问题是应用程序的责任。如果将其中一个实用程序的输出通过管道传输到另一个标准实用程序,则必须考虑线路长度限制; fold 实用程序等可用于确保只有合理的行长才能到达实用程序或应用程序。

而引用的{MAX_CANON}描述为:

{MAX_CANON}

终端规范输入行中的最大字节数。
可接受的最小值:{_POSIX_MAX_CANON}

在其他地方 (<limits.h>),_POSIX_MAX_CANON 可接受的最小值为 255。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    相关资源
    最近更新 更多