我的最终目标是区分我在键盘上按下Esc(ASCII码
我认为有两种选择:
- 等待一段任意时间以查看是否有输入(似乎很hacky)。 - 检查STDIN以查看它是否为空。
我正在尝试后者。为此,我正在尝试使用
问题
- 我想如果我在按下Esc之后没有输入任何内容,那么它会返回-1,因为它没有看到任何剩余的stdin可读内容。 - 我想如果我输入→,那么我将得到一个
但是以上两种情况都没有发生,所以我担心我可能不理解
问题
为什么
最小、完整和可验证的示例
我在MacOS High Sierra和Ubuntu 16上运行此代码,结果相同。
27
)和我按下键盘上的→键(它转换为一系列的27 91 67
)。我正在使用termios
将我的终端置于非规范模式。我认为有两种选择:
- 等待一段任意时间以查看是否有输入(似乎很hacky)。 - 检查STDIN以查看它是否为空。
我正在尝试后者。为此,我正在尝试使用
select
来查看stdin
是否为空。问题
select
似乎总是返回0(超时过期)。这有两个原因:- 我想如果我在按下Esc之后没有输入任何内容,那么它会返回-1,因为它没有看到任何剩余的stdin可读内容。 - 我想如果我输入→,那么我将得到一个
1
返回值,因为它看到27
右边有一个91
和一个67
可读取。但是以上两种情况都没有发生,所以我担心我可能不理解
select
或标准输入/输出。问题
为什么
select
除了0之外没有返回任何东西?是否可以检查stdin
是否为空?其他库如何处理这种情况?最小、完整和可验证的示例
我在MacOS High Sierra和Ubuntu 16上运行此代码,结果相同。
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
int main() {
// put terminal into non-canonical mode
struct termios old;
struct termios new;
int fd = 0; // stdin
tcgetattr(fd, &old);
memcpy(&new, &old, sizeof(old));
new.c_lflag &= ~(ICANON | ECHO);
tcsetattr(fd, TCSANOW, &new);
// loop: get keypress and display (exit via 'x')
char key;
printf("Enter a key to see the ASCII value; press x to exit.\n");
while (1) {
key = getchar();
// check if ESC
if (key == 27) {
fd_set set;
struct timeval timeout;
FD_ZERO(&set);
FD_SET(STDIN_FILENO, &set);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int selret = select(1, &set, NULL, NULL, &timeout);
printf("selret=%i\n", selret);
if (selret == 1) {
// input available
printf("possible sequence\n");
} else if (selret == -1) {
// error
printf("err=%s\n", strerror(errno));
} else {
// just esc key
printf("esc key standalone\n");
}
}
printf("%i\n", (int)key);
if (key == 'x') { break; }
}
// set terminal back to canonical
tcsetattr(fd, TCSANOW, &old);
return 0;
}
输出
gns-mac1:sandbox gns$ ./seltest
Enter a key to see the ASCII value; press x to exit.
selret=0
esc key standalone
27
selret=0
esc key standalone
27
91
67
120
atexit()
的使用,如果程序可能从除main()
循环之外的其他地方调用exit()
,例如错误报告和退出函数,这可能非常重要。 - Jonathan Leffler