我正在为控制台文本输入库编写一个测试应用程序。库的这一部分的想法是将任何输入视为常规文本输入,甚至是 Ctrl+[字母] 组合。在大多数情况下,它的效果相当好。但由于某种原因,每次我尝试 Ctrl+C 时,常规输入都会停止工作 - 我可以通过 getchar 继续逐字符读取输入并读取,但使用常规 stdin 时,我似乎只能再次按 Ctrl+C ,当我尝试像平常一样打字时,什么也没有发生。我只需按回车键就成功使用了
std::cin
。
我在 Ubuntu 上测试了它,既在 Windows 终端中作为 WSL,又在完整的 Ubuntu VM 上进行了测试。
这是我的代码的相关部分:
termios tOld, tNew;
tcgetattr(STDIN_FILENO, &tOld);
tNew = tOld;
tNew.c_lflag &= ~(ICANON | ISIG | IEXTEN | IXON | ECHO);
tNew.c_iflag &= ~(IXON | IXOFF);
tcsetattr(STDIN_FILENO, TCSANOW, &tNew);
// further processing (reading via read and getchar and 'parsing' the input)
tcsetattr(STDIN_FILENO, TCSANOW, &tOld);
我想知道我做错了什么。
导致此错误的另一个可能原因是我用于处理 ESC 按键的代码:
std::function<bool(unsigned)> fnWaitForNextKey =
[](unsigned iMillis) -> bool
{
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = iMillis * 1000;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
return select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
};
在终端的c_lflag和c_iflag中,可能可以尝试使用非规范输入,并关闭大部分处理以给终端提供未修改的通道。
tNew.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
tNew.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);