我只是意外地注意到这一点,使用以下代码。在以下代码中,
char teststring[20];
cin.getline(teststring, 20);
提示停止用户输入,当我按下向上箭头时,我用肌肉记忆检查bash历史记录,它打印出Ansi Escape代码(从here获得详细信息){{ 1}}当我按下一个退格键并按下回车键时,字符^[[A
被删除,它打印出一个不可读的垃圾,而不是A
,但当我手动输入相同的键或复制时 - 再次禁止(为了确保它不是ASCII中的类似符号)没有最后一个字母,它打印^[[
。
输入的字符是一样的原因是什么?
答案 0 :(得分:2)
Unix终端是一个非常复杂的野兽。 Posix包含pretty thorough description个功能;以下只是一个快速摘要。
通常,终端输入设备在"规范"模式。在该模式中,终端驱动程序维护行缓冲区,在必要时通过读取用户输入填充该行缓冲区。如果缓冲区已清空并且程序请求了更多数据,则驱动程序将在向程序提供更多数据之前读取整行输入。因此,如果缓冲区为空,即使getc
读取单个字符,也会导致在getc
返回之前将整个读入终端驱动程序的缓冲区。
当驱动程序读取输入字符时,它会检查某些特殊字符;其他任何东西都被添加到行缓冲区并回显给终端设备。 (对终端设备的输入和输出是独立的;如果驱动程序或程序没有回显输入,屏幕上什么都不会出现,这通常会让人感到困惑。程序会响起,以便能够接受密码,例如。)
所有特殊字符均可配置。有很多;这里有一些比较常见的:
EOF
)字符本身被丢弃,但输入终止并且挂起的读取返回。如果输入缓冲区为空 - 即,在行的开头按下Ctrl-D,则会将零长度缓冲区返回到挂起的读取,这将被解释为文件结束标记。ERASE
)除非输入缓冲区为空,否则从输入缓冲区中删除最后一个字符并从屏幕上删除它。INTR
)将SIGINT
发送给流程。SUSP
)将SIGTSTP
发送给流程。KILL
)删除整个输入缓冲区。STOP
)停止输出。START
)如果已使用STOP
字符停止输出,则恢复输出。当Linux终端驱动程序回显字符时,它通常会将控制字符(ascii代码小于0x20的字符)作为插入符号( ^ ),后跟代码高度为0x40的字符,这通常是一封信。 ESC
字符的代码为0x1B,因此它通常会作为插入符号回显,后跟字符0x5B,这是一个空方括号。因此,您通常希望ESC
以^[
回显。
键盘上的许多键实际上发送了多个字符,几乎所有这些序列都以 ESC [>开头。例如,uparrow发送代码 ESC [ A ,所以如果你正在运行一个无法处理的天真程序光标移动字符,当你按下向上箭头键时,你会看到^[[A
回显。
您看到的字符是用于显示与任何Unicode字形不对应的字符的方式之一。该框包含四个十六进制数字,对应于Unicode代码点,在本例中为U + 001B,即ESC
个字符。我不知道为什么会发生这种情况,但很可能是由于各种组件之间的竞争条件导致了终端回声。