Блокировка 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