我有一个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;
}
它可以按您期望的那样工作。您键入一个密钥,它会被打印回给您。如果按Delete键,程序将退出。但是,奇怪的是,如果按下例如向上箭头,您将获得如下所示的输出:
Input: 27
Input: 91
Input: 65
功能键的输出和其他箭头键看起来相似。 (我会注意,如果我使用getchar(),也会发生这种情况)
std :: cout仅被调用一次。那么为什么要打印三遍呢?我希望我的程序检测到按下F1的用户,然后退出。但是,如果我的程序以这种方式运行,我看不到该怎么做。
非常感谢您的帮助。如果适用的话,我的平台是Mac OSX。
答案 0 :(得分:1)
您正在读取输入一个字符,一次读取一个字节;但是按一个键不一定会产生一个字符。按下光标向上键ESC [ A
会生成三个字符,这是光标向上键in the ANSI/VT100 series of terminal emulators的常见映射。
使用非英语键盘映射时,甚至字母本身也会生成多个字符。例如,在西里尔字母键盘上按下西里尔字母“а”,将读取两个字符:208、176。
请注意,“ ESC”键本身读取单个ESC字符。读完ESC
之后,没有任何迹象表明这是独立的“ Esc”按键,还是代表特殊键的许多可能的多字符序列中的第一个。
终端库(如 curses )通常采用从终端读取ESC后开始短暂超时的方法。如果没有其他字符到达,则它们会认为ESC被自身按下了。如果立即读取更多字符,它们将尝试查找读取的字符序列代表的特殊键。
亲自阅读终端时,由您自己完成所有这些工作。没有别的事情可以为您做。