当输入超出预期长度时,为什么OS X上的fgets输出BELL(^ G,ascii:07)字符?

Chr*_*one 5 c macos xcode

测试用例程序:

#include <stdio.h>
#define SIZE 1024
int main(int args,char *argv[]){
  char buf[SIZE];
  fgets(buf, SIZE, stdin);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

用法示例(即输入1024个x字符):

bash-3.2$ gcc read.c -o read
bash-3.2$ ./read
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
^G
Run Code Online (Sandbox Code Playgroud)

在OS X上,这会使终端发出蜂鸣声并等待.我可以再次击中RET并再次发出哔哔声.如果我在管道或Emacs的shell中运行它,我会看到^G正在输出的字符.

在我的Ubuntu VM上进行相同的精确调用,程序按预期完成(即读取1023个字节buf并将其终止).

这正在打断我正在尝试编写的程序(使用另一种语言,但使用下面的C库),它接受JSON行作为命令接口的一部分.所以问题是:如何在OS X中禁用此行为?是否有API调用将其关闭?环境变量可能?它太棒了.

Mic*_*tch 1

您可以通过将其添加到您的~/.bash_profile文件中来防止此行为:

\n\n
stty -imaxbel\n
Run Code Online (Sandbox Code Playgroud)\n\n

此命令记录在 Apple手册页中stty

\n\n
\n

imaxbel (-imaxbel)\n 系统对输入队列中的 MAX_INPUT(当前为 255)个字符施加限制。如果设置了 imaxbel 并且已达到输入队列限制,则后续输入将导致系统将 ASCII BEL 字符发送到输出队列(终端会向您发出蜂鸣声)。否则,如果未设置 imaxbel 并且输入队列已满,则下一个输入字符将导致整个输入和输出队列被丢弃。

\n
\n\n

您还可以选择stty -imaxbel在当前 shell 中手动发出。无需将其添加到启动文件(例如~/.bash_profile),该设置将在您下次登录时恢复为默认值。

\n\n

如果您需要禁用行缓冲并将每个字符在键入时传递给程序,那么一种方法是使用stty cbreak. 它改变的主要内容之一是禁用icanon控制是否处于缓冲行模式的模式。这篇文章cbreak以通俗易懂的方式进行了合理的讨论icanon

\n\n
\n

ICANON - 也许 c_lflag 中最重要的位是 ICANON 位。启用它会启用“规范”模式 \xe2\x80\x93 也称为“行编辑”模式。设置 ICANON 后,终端一次缓冲一行,并启用行编辑。如果没有 ICANON,输入将立即可供程序使用(这也称为“cbreak”模式)。

\n
\n\n

您也许可以通过以下命令获得您正在寻找的结果:

\n\n
stty cbreak -imaxbel\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将进入逐字符模式并确保BEL被禁用。

\n