C выберите () тайм-аут STDIN один символ (без ENTER) - PullRequest
4 голосов
/ 15 декабря 2011

Я хочу иметь возможность использовать select() для работы с вводом одного символа (без ENTER) из STDIN.

Поэтому, когда пользователь нажимает одну клавишу, select() должен немедленно вернуться,не дожидаясь, пока пользователь нажмет ENTER.

int main(void)
{
    fd_set rfds;
    struct timeval tv;
    int retval;

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

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

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

   if (retval == -1)
        perror("select()");
    else if (retval)
        printf("Data is available now.\n");
    else
        printf("No data within five seconds.\n");

   exit(EXIT_SUCCESS);
}

Это работает, но вы должны нажать клавишу ENTER, чтобы закончить.Я просто хочу, чтобы выбор не ждал, пока пользователь нажмет клавишу, и ENTER.

Спасибо.

Ответы [ 2 ]

3 голосов
/ 15 декабря 2011

Я полагаю, что когда ключ вводится в терминал, он буферизуется до тех пор, пока вы не нажмете клавишу ВВОД, т. Е. Что касается программы, вы ничего не ввели. Возможно, вы захотите взглянуть на этот вопрос .

1 голос
/ 15 декабря 2011

В среде Unix-стиля это может быть достигнуто с помощью функций termios.

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

#include <termios.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    /* Declare the variables you had ... */
    struct termios term;

    tcgetattr(0, &term);
    term.c_iflag &= ~ICANON;
    term.c_cc[VMIN] = 0;
    term.c_cc[VTIME] = 0;
    tcsetattr(0, TCSANOW, &term);

    /* Now the rest of your code ... */
}

Перехват ошибок, которые могут возникнуть при вызовах tcgetattr и tcsetattr, оставлен читателю в качестве упражнения.

...