Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C语言中重新打印输入到终端_C_Asynchronous_Terminal_Chat - Fatal编程技术网

在C语言中重新打印输入到终端

在C语言中重新打印输入到终端,c,asynchronous,terminal,chat,C,Asynchronous,Terminal,Chat,我正在编写一个终端聊天,如果来自另一个用户的新消息异步到达,我想重新打印用户键入的内容 如果新消息到达,我会将“\x1B[2K”打印到标准输出(用于擦除当前行的ANSI转义码)以清除当前行,然后打印“\r”以将光标移动到最左侧位置,然后用新行打印收到的消息 现在我想重新打印用户键入的字符-我发现有一个特殊的字符VREPRINT()可以使用,如果按CTRL-R键,它实际上可以工作…但是如果使用放置在结构termios的c_cc[VREPRINT]中的字符将字符打印到stdout,它不工作-甚至可以

我正在编写一个终端聊天,如果来自另一个用户的新消息异步到达,我想重新打印用户键入的内容

如果新消息到达,我会将“\x1B[2K”打印到标准输出(用于擦除当前行的ANSI转义码)以清除当前行,然后打印“\r”以将光标移动到最左侧位置,然后用新行打印收到的消息

现在我想重新打印用户键入的字符-我发现有一个特殊的字符VREPRINT()可以使用,如果按CTRL-R键,它实际上可以工作…但是如果使用放置在结构termios的c_cc[VREPRINT]中的字符将字符打印到stdout,它不工作-甚至可以这样做吗

我不想使用任何其他库,如readline或ncurses,因为这显然是过火了……如果可能的话,我只想让我的解决方案使用ICANON终端模式工作


提前感谢!

虽然可以写入您正在读取的同一tty设备,但这并不意味着显示的字符将作为输入字符处理

您可以使用两个单独的shell会话(使用
screen
tmux
,或者,如果您在MacOSX上,则使用
iTERM.app
会话)自己测试这一点

在会话1中,获取当前tty名称:

tty
让我们假设会话1的tty名称是
/dev/ttys000

然后输入以下内容,不带返回或换行符——只需将其挂起即可:

echo abc def-
在会话2中(使用会话1中的tty名称),输入以下命令:

echo foo >/dev/ttys000
字符串
foo
应该出现在会话1的挂起行上,如下所示:

echo abc def-foo
现在,返回会话1,点击“回车”(或回车),使输入缓冲区完成并发送到shell,shell将第一个单词解析为
echo
命令,随后的参数作为要打印的文本

您应该会看到字符串“
abc def-
”的回声,但不会看到
foo

该测试表明,字符串
foo
从未被放入输入缓冲区,即使它被发送到用于输入(和输出)的同一tty

您可以尝试查看是否识别和处理了特殊的控制字符;但不会识别和处理。这些字符仅输出到终端,而未被处理

为了处理特殊字符,必须通过连接到输入设备的插座接收这些字符


要完成您试图完成的任务,您必须使用非规范(
stty-icanon
)并处理代码中的每个字符,以便收集挂起的输入并能够生成异步输出


或者,使用
护士
一点也不难,如果你正在编写一个基于终端的聊天程序,我建议至少创建两个面板:一个用于所有输出的“聊天”面板和一个用于用户输入的“输入”面板。这允许其他用户输出,以及“输入”中完成的命令面板,异步接收并写入“聊天”面板,而不会干扰用户在“输入”面板中正在执行的当前命令。

因此,C中没有可用于重新打印终端输入缓冲区的接口?我发现如果我使用struct termios并设置“PENDIN”c_lflag,它的行为几乎与我所希望的一样。如果我按任意键,它会重新打印输入缓冲区!根据手册页,如果收到特殊字符“VREPRINT”,将设置此位字段(“PENDIN”)。因此我认为并希望有某种方法可以在不使用非规范模式的情况下重新打印输入缓冲区。