c++ - 为什么按功能键或箭头键时 getch 返回三个值?
问题描述
我有一个函数 getch(),它的工作方式与 Unix(Mac OSX?) getchar() 或 Windows _getch() 非常相似,只是它不等待用户在返回值之前按 enter。我想使用它,因为它避免了使用 system() 来获取实时输入。(我必须做类似 system("stty raw") 的事情来用上述函数做等效的事情,无论出于何种原因,stty raw 真的搞砸了我的终端的缩进。)这是代码:
#include <termios.h>
char getch() {
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() {
//std::thread InputThread(GetInput);
int c = 0;
while(c != 127) { // Delete key is 127
c = getch();
std::cout << "Input: " << c << "\n" << endl;
}
std::cout << "Broke!" << endl;
std::this_thread::sleep_for(std::chrono::seconds(3));
Quit();
//InputThread.detach();
return 0;
}
它可以按您的预期工作。您输入一个密钥,它会打印回给您。如果按删除,程序退出。然而,奇怪的是,如果你按下向上箭头,你会得到如下所示的输出:
Input: 27
Input: 91
Input: 65
功能键和其他箭头键的输出看起来相似。(我会注意到,如果我使用 getchar(),也会发生这种行为)
std::cout 只被调用一次。那么为什么要打印三遍呢?我希望我的程序检测到用户按下 F1,然后退出。但是,如果我的程序以这种方式运行,我不知道该怎么做。
任何帮助深表感谢。如果合适的话,我的平台是 Mac OSX。
解决方案
您正在读取输入一个字符,一次一个字节;但是,按单个键可能不一定会生成一个字符。向上光标键在按下时会生成三个字符,这是ANSI/VT100 系列终端仿真器中ESC [ A
向上光标键的常见映射。
在使用非英语键盘映射时,即使是字母本身也会生成多个字符。例如,在西里尔字母键盘上按下西里尔字母“а”会读取两个字符:208、176。
请注意,“ESC”键本身读取单个 ESC 字符。阅读后ESC
没有任何迹象表明这是一个独立的“Esc”按键,还是代表特殊键的许多可能的多字符序列中的第一个。
终端库,如curses通常采用在从终端读取 ESC 后开始短暂超时的方法。如果没有其他字符到达,他们假定 ESC 是自己按下的。如果立即读取更多字符,它们将尝试查找读取的字符序列表示的特殊键。
自己阅读终端时,由您来完成所有这些工作。没有其他东西可以为您完成这项工作。
推荐阅读
- sql - 为子字符串条件指定多个字符
- mysql - 需要重新安装包 mysql-server-5.7,但我找不到它的存档
- node.js - 如何使用 gcloud 凭据对 Dialogflow API 进行身份验证
- graph - 证明没有边的图之间的编辑距离是一个度量
- facebook - 分享到 Facebook 快拍
- symfony - 在 Symfony / Twig 中选择实体中是否存在一行
- java - 如何将选项卡配置为使用 CSVFormat 分隔?
- php - 如何从字符串变量中创建函数?
- reactjs - 使用 React-router-dom 和 react-table 重定向。
- python-3.x - 有选择地使用 Python 抓取维基百科表格