Блокировка ncurses и stdin

У меня есть STDIN в select() установить, и я хочу взять строку из stdin всякий раз, когда пользователь набирает ее и нажимает Enter.

Но select вызывает стандартный ввод как готовый к чтению до нажатия Enter, а в редких случаях - до того, как что-либо будет напечатано. Это вешает мою программу на getstr() пока я не нажму Enter.

Я пробовал настройку nocbreak() и это действительно идеально, за исключением того, что ничего не отражается на экране, поэтому я не вижу, что я печатаю. И настройка echo() не меняет это.

Я также пытался использовать timeout(0), но результаты этого были еще безумнее и не сработали.

1 ответ

Что вам нужно сделать, так это проверить, доступен ли символ с помощью функции getch(). Если вы используете его в режиме без задержки, метод не будет блокироваться. Затем вам нужно съесть символы, пока не встретите '\n', добавляя каждый символ к результирующей строке по мере продвижения.

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

Здесь приведен небольшой пример, который вы можете использовать. Он имеет цикл выбора и использует библиотеку чтения строки GNU:

#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <stdbool.h>

int quit = false;

void rl_cb(char* line)
{
    if (NULL==line) {
        quit = true;
        return;
    }

    if(strlen(line) > 0) add_history(line);

    printf("You typed:\n%s\n", line);
    free(line);
}

int main()
{
    struct timeval to;
    const char *prompt = "# ";

    rl_callback_handler_install(prompt, (rl_vcpfunc_t*) &rl_cb);

    to.tv_sec = 0;
    to.tv_usec = 10000;

    while(1){
        if (quit) break;
        select(1, NULL, NULL, NULL, &to);
        rl_callback_read_char();
    };
    rl_callback_handler_remove();

    return 0;
}

Компилировать с:

gcc -Wall rl.c -lreadline
Другие вопросы по тегам