Setvbuf не может сделать stdin небуферизованным

Моя основная цель состояла в том, чтобы вернуть getchar, как только он получит символ, а не ждет клавишу ENTER. Я попробовал это

int main()
{
    setvbuf(stdin,NULL,_IONBF,0);
    getchar();

    return 0;
}

Сравнивая это с прототипом setvbuf

setvbuf ( FILE * stream, char * buffer, int mode, size_t size );

он должен установить stdin в небуферизованный режим.

Но все же getchar() продолжает ждать ENTER

Я видел похожие сообщения вроде этого

Печать при чтении символов в C

которые предлагают альтернативные методы, чтобы сделать stdin небуферизованным. Но мне любопытно узнать, почему метод setvbuf не работает

Ответ 1

Драйвер терминала ничего не возвращает, пока вы не нажмете return, даже если операция read() примет то, что уже существует.

Чтобы получить посимвольный ввод от терминала, вы должны вывести его из канонического режима в режим raw или cbreak, и для этого требуются разные операции. Взгляните на руководство POSIX на 'Общий интерфейс терминала для управления терминалом. Или рассмотрите возможность использования библиотеки curses.

См. также: Канонический и неканонический ввод терминалов

Ответ 2

Если вы пытаетесь сделать это под Linux или другой Unix-подобной системой, это терминал, который буферизует ввод и пропускает только целую строку. Вы можете использовать ncurses, чтобы обойти это:

#include <ncurses.h>

int main()
{
    initscr();
    getch();
    endwin();

    return 0;
}

Скомпилировать с помощью:

gcc -o main main.c -lncurses