问题描述
我一直在努力解决一个非常简单的问题,该问题用 C 编写了一个小程序.
只要输入的大小不超过1024字节,就可以通过fgets()
获取输入(命令,参数,要执行的标志).键入1024个字符后,不再接受任何字符-提示停止.我认为问题的原因不在fgets()
参数/配置中,因为否则它将至少使输入达到定义的大小,而不是阻塞.
我如何使fgets()
接受只要_SC_LINE_MAX
(2048
)个字节/字符的行?
终端驱动程序限制输入线的长度
正如我在评论中指出的那样,问题几乎可以肯定是您的终端驱动程序不允许您输入长度超过1024字节的行.它不会分配更多的存储空间.这适用于规范"模式;有关更多信息,请参见规范与非规范终端输入.那个.
有一个简单的测试程序(现在在问题中).在Mac OS X 10.11.4上运行它时,我可以输入1023个字符加上换行符,或者输入1024个字符,但不能输入换行符,直到删除一个为止.
为记录起见,输入字符串为:
12345678901234567890123456789X123456789Y123456789Z123456789A123456789B123456789C123456789D123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123456789r123456789s123456789t123456789s123456789t123456789u123456789v123456789w123456789x123456789y123456789z123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123456789r123456789s123456789t123456789u123456789v123456789w123456789x123456789y123456789z123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123456789r123456789s123456789t123456789u123456789v123456789w123456789x123456789y123456789z123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123
如果使用换行符复制并粘贴该行,则可能会输入OK.如果再添加其他字符,则可能会收到终端提示音.
还有另一个问题( fgets()
限制为1024个字节-我可以使用什么代替?)几乎可以肯定会遇到相同的问题-并且实际上没有得到太多有用的帮助.
如果您使用GNU之类的库 readline
库,它可以将终端置于非规范模式,然后可以处理更长的行,因为终端驱动程序在将数据发送到程序之前不会等到输入换行符.在类似Linux的系统上,重建具有更大终端输入线长度限制的内核在名义上是一个选项,但对于临时程序员而言并不是一项任务.
LINE_MAX
和相关宏的含义
还要注意,_SC_LINE_MAX
是 sysconf()
代码确定LINE_MAX
的方法,该值必须至少为{POSIX2_LINE_MAX}
的值(最小2048),该文档记录为:
请注意,终端不是文本文件.此限制表明,grep
之类的实用程序一定不能对2048字节长的行进行错误处理,但是它可能会被更长的行弄糊涂(例如,因为它读取一行2048字节的数据块,并且开始行"在长行的第二个或后续大块的开头匹配).
POSIX注释的原理:
引用的{MAX_CANON}
描述为:
在其他地方(<limits.h>
),_POSIX_MAX_CANON
的最小可接受值为255.
I have been struggling with a pretty simple issue writing a little program in C.
Getting input (commands, arguments, flags to be executed) via fgets()
works fine as long as the size of the input does not exceed 1024 bytes. After 1024 characters are typed, no more characters are accepted -- the prompt just stops. I assume reason for the problem doesn't lay in the fgets()
parameters/configuration because otherwise it would at least take the input up to defined size instead of blocking.
How can I make fgets()
accept lines as long as _SC_LINE_MAX
(2048
) bytes/chars?
Terminal drivers limit the length of input lines
As I noted in the comments, the trouble is almost certainly that your terminal driver won't allow you to enter lines that are longer than 1024 bytes; it won't allocate more storage. That applies in 'canonical' mode; see Canonical vs non-canonical terminal input for more information about that.
There's a simple test program (now in the question). When I run it on Mac OS X 10.11.4, I can enter 1023 characters plus newline, or 1024 characters but no newline until I delete one.
For the record, the input string was:
12345678901234567890123456789X123456789Y123456789Z123456789A123456789B123456789C123456789D123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123456789r123456789s123456789t123456789s123456789t123456789u123456789v123456789w123456789x123456789y123456789z123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123456789r123456789s123456789t123456789u123456789v123456789w123456789x123456789y123456789z123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123456789r123456789s123456789t123456789u123456789v123456789w123456789x123456789y123456789z123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789k123456789l123456789m123456789n123456789o123456789p123456789q123
If you copy and paste that with the newline, it will probably be entered OK. If you add any more characters, you will probably get the terminal beeping at you.
There's another question (fgets()
is limited to 1024 bytes — what can I use instead?) that almost certainly ran into the same problem — and really wasn't given much in the way of useful help.
If you use a library such as the GNU readline
library, it can put the terminal into non-canonical mode and then can handle longer lines because the terminal driver doesn't wait until the newline is entered before sending the data to the program. Rebuilding the kernel with a bigger limit on the terminal input line length is nominally an option on Linux-like systems, but not a task for the casual programmer.
Meaning of LINE_MAX
and related macros
Also note that _SC_LINE_MAX
is the sysconf()
code for determining LINE_MAX
, which must be at least the value of {POSIX2_LINE_MAX}
(minimum 2048), which is documented as being:
Note that a terminal is not a text file. This limit says that utilities such as grep
must not mishandle lines that are 2048 bytes long, but it might get confused by longer lines (for example, because it reads 2048-byte chunks of a line, and does 'beginning of line' matches at the start of the second or subsequent chunks of a long line).
The rationale for POSIX notes:
And the {MAX_CANON}
referenced is described as:
And elsewhere (<limits.h>
), the minimum acceptable value for _POSIX_MAX_CANON
is 255.
这篇关于fgets提示限制为1024字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!