c++ - getchar() 避免转义序列
问题描述
我正在编写 Linux 控制台应用程序(某种菜单),所以我需要从用户那里获得输入。这是我到目前为止使用的代码:
int getch(void)
{
int ch;
struct termios oldt;
struct termios newt;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= static_cast<unsigned int>(~(ICANON | ECHO));
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
#define KEY_UP 65
#define KEY_DOWN 66
#define KEY_ESC 27
while(true)
{
ch = getch();
switch(ch)
{
case KEY_UP:
break;
case KEY_DOWN:
break;
case ESC:
break;
}
}
一切都很好,直到我需要使用 ESC。突然发现 getch() 有时会在循环中返回几个整数。例如:
KEY_UP: 27 91 65
KEY_DOWN: 27 91 66
BKSPACE: 127
ESC: 27
好的,在我的情况下,在循环中进行 3 次迭代后,我将获得正确的值(例如 65 表示 KEY_UP),但是当我真正单击 Esc 按钮时,如何获得 ESC 呢?如何配置 getch() 以仅返回实际值并避免 esc 序列?
Ubuntu 18.04 gcc 7.4.0 libstdc++.so.6
解决方案
您可以获得真正的 ESC 键来实现一个功能,如果缓冲区中有更多待读取的数据,则kbhit
基本上返回 true,这里是一个包装器,返回您的or (27) 的结果:kbhit
kbget
getch
KEY_ESCAPE
static int kbhit(void)
{
int c = 0;
tcgetattr(0, &oterm);
memcpy(&term, &oterm, sizeof(term));
term.c_lflag &= ~(ICANON | ECHO);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(0, TCSANOW, &term);
c = getchar();
tcsetattr(0, TCSANOW, &oterm);
if (c != -1) ungetc(c, stdin);
return ((c != -1) ? 1 : 0);
}
static int kbesc(void)
{
int c;
if (!kbhit()) return KEY_ESCAPE;
c = getch();
if (c == '[') {
switch (getch()) {
case 'A':
c = KEY_UP;
break;
case 'B':
c = KEY_DOWN;
break;
case 'C':
c = KEY_LEFT;
break;
case 'D':
c = KEY_RIGHT;
break;
default:
c = 0;
break;
}
} else {
c = 0;
}
if (c == 0) while (kbhit()) getch();
return c;
}
static int kbget(void)
{
int c;
c = getch();
return (c == KEY_ESCAPE) ? kbesc() : c;
}
推荐阅读
- selenium - 未定义 DesiredCapabilities 类型的 firefox() 方法
- python - 无法将 RDD 转换为数据帧
- json - Jackson Kotlin - 反序列化 JsonNode
- azure-iot-edge - Com 端口映射 - Azure IOT Edge - Windows IOT 2019
- amazon-web-services - 使用 AWS CLI 命令添加带有条件的 SQS 权限
- ios - 当我使用 MvxSimpleTableViewSource 时,xamarin ios Tableview 没有重新加载
- python - 根据多个其他列的值选择和更改第三个值
- sql - 是否有另一种方法可以在 SQL 中使用 Union 来处理这种情况?
- adblock - 如何在ublock中阻止父母而不阻止孩子
- html - 使用rem的chrome和firefox之间的字体大小差异