selftrips
@selftrips

Как в С можно сделать реагирование на клавишу клавиатуры без ожидания обязательного ввода (без использования стандартных библиотек)?

То есть некая реализация интерактива.
Программа продолжает "крутиться", но если был нажат определенный символ обрабатывает его.
Например, если нажат Q/q выходит из цикла заканчивает работу.
Проблема не в обработке? проблема в получении ввода с клавы без ожидания программы на этом месте.
System Version: macOS 11.4
  • Вопрос задан
  • 164 просмотра
Пригласить эксперта
Ответы на вопрос 4
VoidVolker
@VoidVolker
Dark side eye. А у нас печеньки! А у вас?
Использовать хук пользовательского ввода системного API. В каждой ОС - свои механизмы. Например для винды: https://learn.microsoft.com/en-us/windows/win32/wi...
Ответ написан
AshBlade
@AshBlade
Просто хочу быть счастливым
Можно запустить фоновый поток: он читает ввод и при получении Q/q выставляет флаг окончания.
Псеводкод:

int should_stop = 0;

void keyboard_processor() {
     while (should_stop != 1) {
           char input = get_input();
           if (input == 'q' || input == 'Q') {
                  should_stop = 1;
                  break;
           }
     }
}
int main() {
    start_thread(keyboard_processor);
    while (should_stop != 1) {
          do_work();
    }
}
Ответ написан
@pvvv
стандартная библиотека чем не угодила?
там есть kbhit(), который проверяет наличие ввода, после которого getchar ничего ожидать не будет.

if (kbhit()) key = getchar();
Ответ написан
@stasenso
Честно стырил со stack overflow, работает для POSIX-совместимых систем. Функцию надо вешать на отдельный поток в бесконечный цикл.

#include <termios.h>
char getch()
{
wchar_t buf = 0;
struct termios old = {0};
if (tcgetattr(0, &old) < 0)
perror("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if (tcsetattr(0, TCSANOW, &old) < 0)
perror("tcsetattr ICANON");
if (read(0, &buf, 1) < 0)
perror ("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if (tcsetattr(0, TCSADRAIN, &old) < 0)
perror ("tcsetattr ~ICANON");
return (buf);
}

Совсем без зависимостей никак, увы.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы