Как использовать Select() для чтения ввода с клавиатуры в C

Я пытаюсь использовать Select() для чтения ввода с клавиатуры и я застрял в том, что я не знаю, как читать с клавиатуры и использовать дескриптор файла для этого. Мне сказали использовать STDIN и STDIN_FILENO для решения этой проблемы, но я все еще смущен.
Как я могу это сделать?

3 ответов


Ваш вопрос звучит немного смущенно. select() используется для блокировки, пока не будет доступен вход. Но вы делаете фактическое чтение с обычными функциями чтения файлов (например,read,fread,fgetc, etc.).

вот краткий пример. Он блокирует, пока stdin не будет иметь хотя бы один символ, доступный для чтения. Но, конечно, если вы не измените терминал на какой-то необработанный режим, он блокируется до тех пор, пока вы не нажмете enter, когда любые введенные символы будут сброшены в буфер файлов (из некоторых терминальный буфер).

#include <stdio.h>
#include <sys/select.h>

int main(void) {
    fd_set s_rd, s_wr, s_ex;
    FD_ZERO(&s_rd);
    FD_ZERO(&s_wr);
    FD_ZERO(&s_ex);
    FD_SET(fileno(stdin), &s_rd);
    select(fileno(stdin)+1, &s_rd, &s_wr, &s_ex, NULL);
    return 0;
}

Как уже было сказано, с помощью выберите вы можете просто контролировать, например, stdin, чтобы проверить, доступны ли входные данные для чтения или нет. Если он доступен, вы можете использовать, например,fgets безопасно считывать входные данные в какой-то буфер, как показано ниже:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    fd_set rfds;
    struct timeval tv;
    int retval, len;
    char buff[255] = {0};

    /* Watch stdin (fd 0) to see when it has input. */
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);

    /* Wait up to five seconds. */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

    retval = select(1, &rfds, NULL, NULL, &tv);

    if (retval == -1){
        perror("select()");
        exit(EXIT_FAILURE);
    }
    else if (retval){
        /* FD_ISSET(0, &rfds) is true so input is available now. */

        /* Read data from stdin using fgets. */
        fgets(buff, sizeof(buff), stdin);

        /* Remove trailing newline character from the input buffer if needed. */
        len = strlen(buff) - 1;
        if (buff[len] == '\n')
            buff[len] = '';

        printf("'%s' was read from stdin.\n", buff);
    }
    else
        printf("No data within five seconds.\n");            

    exit(EXIT_SUCCESS);
}

возможно, вы хотите, чтобы способ заглянуть ввода клавиатуры на "WINDOWS"? В windows он не может получить результат от select() для STDIN. Вы должны использовать PeekConsoleInput(). И используйте ручку stdin, как следующее.

hStdin = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE, ...

stdin может стать входом трубы. если это так, вы не получаете ввода с клавиатуры.

P. S. Если вы не просите о Windows, очень жаль.