我正在尝试用C语言编写一个程序(在Linux上)循环,直到用户按下一个键,但不应该要求按键继续每个循环.
有一个简单的方法吗?我想我可以做到这一点,select()
但这似乎很多工作.
或者,有没有办法在程序关闭之前捕获ctrl- ckeypress进行清理而不是非阻塞io?
如前所述,您可以使用sigaction
陷阱ctrl-c或select
陷阱任何标准输入.
但请注意,对于后一种方法,您还需要设置TTY,使其一次一个字符而不是一次一行模式.后者是默认值 - 如果您键入一行文本,则在按Enter键之前不会将其发送到正在运行的程序的stdin.
您需要使用该tcsetattr()
功能关闭ICANON模式,也可能还禁用ECHO.从内存中,您还必须在程序退出时将终端设置回ICANON模式!
为了完整性,这里有一些代码我刚刚敲了(nb:没有错误检查!),它设置了一个Unix TTY并模拟了DOS
函数,kbhit()
并且getch()
:
#include#include #include #include #include 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); } 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 */ }
select()
为方便起见有点太低级了.我建议您使用该ncurses
库将终端设置为cbreak模式和延迟模式,然后调用getch()
,ERR
如果没有字符准备就会返回:
WINDOW *w = initscr(); cbreak(); nodelay(w, TRUE);
那时你可以getch
不受阻塞地打电话.
在UNIX系统上,您可以使用sigaction
call为SIGINT
信号注册信号处理程序,该信号处理程序代表Control + C键序列.信号处理程序可以设置一个标志,该标志将在循环中检查,使其适当地中断.
你可能想要 kbhit();
//Example will loop until a key is pressed #include#include using namespace std; int main() { while(1) { if(kbhit()) { break; } } }
这可能不适用于所有环境.一种可移植的方法是创建一个监视线程并设置一些标志getch();