我正在尝试用 C 语言(在 Linux 上)编写一个程序,该程序循环直到用户按下一个键,但不应该需要按键来继续每个循环。 有没有一种简单的方法可以做到这一点?我想我可以用 select() 来做到这一点,但这似乎需要做很多工作。 或者,有没有办法在程序关闭而不是非阻塞 io 之前捕获 ctrl - c 按键来进行清理? 原文由 Zxaos 发布,翻译遵循 CC BY-SA 4.0 许可协议
如前所述,您可以使用 sigaction 捕获 ctrl-c,或 select 捕获任何标准输入。 但是请注意,使用后一种方法,您还需要设置 TTY,使其处于一次字符而不是一次一行模式。后者是默认设置 - 如果您输入一行文本,它不会被发送到正在运行的程序的标准输入,直到您按下回车键。 您需要使用 tcsetattr() 功能来关闭 ICANON 模式,并且可能还禁用 ECHO。从内存中,您还必须在程序退出时将终端设置回 ICANON 模式! 为了完整起见,这是我刚刚敲出的一些代码(nb:没有错误检查!)它设置了一个 Unix TTY 并模拟了 DOS <conio.h> 函数 kbhit() 和 getch() : #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/select.h> #include <termios.h> struct termios orig_termios; void reset_terminal_mode() tcsetattr(0, TCSANOW, &orig_termios); void set_conio_terminal_mode() struct termios new_termios; /* take two copies - one for now, one for later */ tcgetattr(0, &orig_termios); memcpy(&new_termios, &orig_termios, sizeof(new_termios)); /* register cleanup handler, and set the new terminal mode */ atexit(reset_terminal_mode); cfmakeraw(&new_termios); tcsetattr(0, TCSANOW, &new_termios); int kbhit() struct timeval tv = { 0L, 0L }; fd_set fds; FD_ZERO(&fds); FD_SET(0, &fds); return select(1, &fds, NULL, NULL, &tv) > 0; int getch() int r; unsigned char c; if ((r = read(0, &c, sizeof(c))) < 0) { return r; } else { return c; int main(int argc, char *argv[]) set_conio_terminal_mode(); while (!kbhit()) { /* do some work */ (void)getch(); /* consume the character */ 原文由 Alnitak 发布,翻译遵循 CC BY-SA 4.0 许可协议
select() 为了方便起见,有点太低级了。我建议你使用 ncurses 库将终端置于 cbreak 模式和延迟模式,然后调用 getch() ,它将返回 ERR 如果没有字符准备好: WINDOW *w = initscr(); cbreak(); nodelay(w, TRUE);