我正在尝试编写一个程序,该程序将在用户按下 F1 键时退出。我正在使用自定义函数 myGetch() 从终端获取用户输入。它只是直接从终端获取用户输入,而无需用户按回车键。
我制作了一个小程序来打印出键码,目的是找到 F1 输出的键码,这样我就可以使用该键码而不是“127”作为“删除”键来退出程序。
#include <termios.h>
char myGetch() {
char buf = 0;
struct termios old = {0};
if (tcgetattr(0, &old) < 0)
perror("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if (tcsetattr(0, TCSANOW, &old) < 0)
perror("tcsetattr ICANON");
if (read(0, &buf, 1) < 0)
perror ("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if (tcsetattr(0, TCSADRAIN, &old) < 0)
perror ("tcsetattr ~ICANON");
return (buf);
}
int main() {
int c = 0;
while(c != 127) { // Delete key is 127
c = myGetch();
std::cout << "Input: " << c << "\n" << endl;
}
std::cout << "User pressed delete!" << endl;
std::this_thread::sleep_for(std::chrono::seconds(3));
Quit();
return 0;
}
它的工作方式如您所料。您输入一个 key ,它会打印回给您。如果按删除,程序退出。然而,奇怪的是,如果你按下向上箭头,你会得到如下所示的输出:
Input: 27
Input: 91
Input: 65
功能键和其他箭头键的输出看起来很相似。
std::cout 只被调用一次。那为什么要打印三次呢?我希望我的程序检测到用户按下 F1,然后退出。但如果我的程序以这种方式运行,我不知道该怎么做。
非常感谢任何帮助。如果相关的话,我的平台是 Mac OSX。
最佳答案
您正在读取一个字符,一次一个字节;但是,按一个键不一定会生成一个字符。光标向上键在按下时生成三个字符,ESC [ A
,这是光标向上键的常见映射 in the ANSI/VT100 series of terminal emulators .
即使是字母本身也会在使用非英语键盘映射时生成多个字符。例如,在西里尔键盘上按西里尔字母“а”会读出两个字符:208、176。
请注意,“ESC”键本身读取单个 ESC 字符。读取 ESC
后,没有任何迹象表明这是一个独立的“Esc”按键,还是代表特殊键的许多可能的多字符序列中的第一个。
终端库,如 curses 通常采用在从终端读取 ESC 后开始短暂超时的方法。如果没有更多的字符到达,他们就认为 ESC 是自己按下的。如果立即读取更多字符,它们将尝试查找读取的字符序列代表的特殊键。
当您自己阅读终端时,所有这些工作都由您来完成。没有其他东西可以为您完成这项工作。
关于c++ - 为什么按功能键或箭头键时 getch 会返回三个值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52213976/