Вопрос по c, multithreading, keypress – Реализация события KeyPress в C
У меня есть бесконечный цикл, подобный следующему, и в этом цикле я хочу постоянно проверять клавиатуру, чтобы увидеть, была ли нажата клавиша ESC (ESC) или нет. Если она нажата, то петля должна быть разорвана. Как я могу сделать это в C? (Я использую gcc, и делаю доступ к pthreads также в случае, если это должно быть сделано через потоки)
while(1){
//do something
//check for the ESC key
}
while((ch = getchar()) != ESC_ASCCI_CODE)
Maroun
Если основная работа у васЭто может быть сделано в этом основном цикле, вы можете использовать STDIN в неблокирующем режиме. У вас все еще есть проблема с терминалом, который обычно выполняет буферизацию строки. Вы также должны перевести терминал в режим raw.
Как насчет использования Ctrl-C (прерывание)?
Неблокирующая означает, чтоread()
Системный вызов всегда возвращается немедленно, даже если в файле нет новых байтов. В Linux / Unix STDIN можно разблокировать следующим образом:
#include
#include
fcntl(0, F_SETFL, O_NONBLOCK); /* 0 is the stdin file decriptor */
Это сильно зависит от системы. В системах Unix / Linux обработчик терминала по умолчанию собирает строки и уведомляет программу только тогда, когда доступна полная строка (послеВойти ударил.) Если вы вместо этого хотите немедленное нажатие клавиш, вам нужно перевести терминал в неканонический режим:
#include
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 и т. д.), установка 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? */
}
}
После Вас'После этого вы, вероятно, захотите снова установить терминал в канонический режим, чтобы другие программы (например, ваша оболочка) не запутались:
tcgetattr(0, &info);
info.c_lflag |= ICANON;
tcsetattr(0, TCSANOW, &info);
Есть также и другие вещи, которые вы можете сделать с помощью tcsetattr - см. Подробности на странице руководства. Одной вещи, которая может быть достаточной для ваших целей, является установка альтернативного символа EOL.