我有一个像下面这样的无限循环,在这个循环中,我想连续检查键盘,看看是否按下了退出键(ESC).如果按下,则应该打破循环.我怎么能用C做到这一点?(我正在使用gcc,并且在必须通过线程完成的情况下也可以访问pthread)
while(1){ //do something //check for the ESC key }
Chris Dodd.. 6
这严重依赖于系统.在Unix/Linux系统中,默认终端处理程序收集行,仅在完整行可用时(在Enter命中之后)通知程序.如果您想立即按键,则需要将终端置于非规范模式:
#includestruct termios info; tcgetattr(0, &info); /* get current terminal attirbutes; 0 is the file descriptor for stdin */ info.c_lflag &= ~ICANON; /* disable canonical mode */ info.c_cc[VMIN] = 1; /* wait until at least one keystroke available */ info.c_cc[VTIME] = 0; /* no timeout */ tcsetattr(0, TCSANOW, &info); /* set immediately */
完成后,您可以使用从stdin读取的任何调用,它们将返回键而无需等待行尾.您还可以设置c_cc[VMIN] = 0
为在从stdin读取时根本不等待键击.
但是,如果您正在使用stdio FILE相关调用(getchar等)读取stdin,则设置VMIN = 0会使您认为只要没有可用键就已达到EOF,因此您必须clearerr
在此之后调用试着读更多的人物.您可以使用如下循环:
int ch; while((ch = getchar()) != 27 /* ascii ESC */) { if (ch < 0) { if (ferror(stdin)) { /* there was an error... */ } clearerr(stdin); /* do other stuff */ } else { /* some key OTHER than ESC was hit, do something about it? */ } }
完成后,您可能希望确保将终端设置回规范模式,以免其他程序(例如您的shell)混淆:
tcgetattr(0, &info); info.c_lflag |= ICANON; tcsetattr(0, TCSANOW, &info);
您还可以使用tcsetattr执行其他操作 - 有关详细信息,请参阅手册页.可能满足您的目的的一件事是设置另一个EOL角色.
这严重依赖于系统.在Unix/Linux系统中,默认终端处理程序收集行,仅在完整行可用时(在Enter命中之后)通知程序.如果您想立即按键,则需要将终端置于非规范模式:
#include <termios.h> struct termios info; tcgetattr(0, &info); /* get current terminal attirbutes; 0 is the file descriptor for stdin */ info.c_lflag &= ~ICANON; /* disable canonical mode */ info.c_cc[VMIN] = 1; /* wait until at least one keystroke available */ info.c_cc[VTIME] = 0; /* no timeout */ tcsetattr(0, TCSANOW, &info); /* set immediately */
完成后,您可以使用从stdin读取的任何调用,它们将返回键而无需等待行尾.您还可以设置c_cc[VMIN] = 0
为在从stdin读取时根本不等待键击.
但是,如果您正在使用stdio FILE相关调用(getchar等)读取stdin,则设置VMIN = 0会使您认为只要没有可用键就已达到EOF,因此您必须clearerr
在此之后调用试着读更多的人物.您可以使用如下循环:
int ch; while((ch = getchar()) != 27 /* ascii ESC */) { if (ch < 0) { if (ferror(stdin)) { /* there was an error... */ } clearerr(stdin); /* do other stuff */ } else { /* some key OTHER than ESC was hit, do something about it? */ } }
完成后,您可能希望确保将终端设置回规范模式,以免其他程序(例如您的shell)混淆:
tcgetattr(0, &info); info.c_lflag |= ICANON; tcsetattr(0, TCSANOW, &info);
您还可以使用tcsetattr执行其他操作 - 有关详细信息,请参阅手册页.可能满足您的目的的一件事是设置另一个EOL角色.