Как можно реализовать аналог функции kbhit() в linux?

Пользователь

от lori_jast , в категории: Другие , год назад

Как можно реализовать аналог функции kbhit() в linux?

Facebook Vk Ok Twitter LinkedIn Telegram Whatsapp

2 ответа

Пользователь

от gage , год назад

@lori_jast 

В Linux можно реализовать аналог функции kbhit() с помощью использования системных вызовов для неканонического ввода. Вот пример кода на языке C, который позволяет проверять наличие непрочитанных символов во входном потоке ввода:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>

int kbhit() {
    struct termios oldt, newt;
    int ch;
    int oldf;

    tcgetattr(STDIN_FILENO, &oldt); // сохранить старые настройки терминала
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO); // изменить настройки для неканонического ввода без отображения символов
    tcsetattr(STDIN_FILENO, TCSANOW, &newt); // применить новые настройки

    oldf = fcntl(STDIN_FILENO, F_GETFL, 0); // получить старые флаги файлового дескриптора
    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); // добавить флаг неблокирующего чтения

    ch = getchar(); // попытаться прочитать символ из входного потока

    tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // вернуть старые настройки терминала
    fcntl(STDIN_FILENO, F_SETFL, oldf); // вернуть старые флаги файлового дескриптора

    if (ch != EOF) {
        ungetc(ch, stdin); // вернуть символ обратно во входной поток
        return 1;
    }

    return 0;
}

int main() {
    while (1) {
        if (kbhit()) {
            printf("Key pressed!
");
            break;
        }

        // simulate some other work
        usleep(100000); // sleep for 100 milliseconds
    }

    return 0;
}


В этом примере функция kbhit() изменяет настройки терминала на неканонический режим без отображения символов и устанавливает флаг неблокирующего чтения для входного потока стандартного ввода. Затем она пытается прочитать символ из входного потока. Если символ доступен, то он возвращается, иначе функция возвращает 0.


Функция main() в данном примере использует kbhit() для проверки наличия нажатой клавиши в цикле. Если клавиша была нажата, программа выводит сообщение и завершает свою работу. Если клавиша не была нажата, программа продолжает выполнять другую работу (в данном случае указано задержку в 100 миллисекунд).

Пользователь

от forest , 6 месяцев назад

@lori_jast 

Дополнительно отмечу, что данная реализация функции kbhit() использует функции tcgetattr(), tcsetattr() для работы с настройками терминала и fcntl() для управления флагами файлового дескриптора. Такой подход позволяет осуществлять проверку наличия непрочитанных символов во входном потоке ввода без блокировки программы в ожидании ввода данных.


Кроме этого, можно также воспользоваться библиотекой ncurses, которая предоставляет более высокоуровневый инструментарий для работы с терминалом. В ncurses также есть функции, позволяющие организовать неканонический ввод и проверку наличия нажатых клавиш. Этот подход может быть удобен, если требуется более сложная обработка ввода с поддержкой интерактивного пользовательского интерфейса.