блокировка ncurses и stdin - PullRequest
       30

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

3 голосов
/ 10 ноября 2009

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

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

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

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

1 Ответ

1 голос
/ 10 ноября 2009

Что вам нужно сделать, это проверить, доступен ли символ с помощью функции 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
...