getchar и буферизация кода клавиши Enter

Не понимаю логику поведения этого кода. Кто-нибудь, пожалуйста, подскажите.

#include <cstdio>

int main(void)
{
    printf("a");
    getchar();
    printf("b");
    getchar();
    printf("c\n");

return 0;
}

Если просто нажимать Enter: a b c

Если после вывода на экран первого символа, набрать еще символ (или несколько), скажем 'd':

ad
bc

Как тут работает буферизация?


Ответы (1 шт):

Автор решения: Fat-Zer

Если кратко, то getchar() работает примерно следующим образом:

  • Если в буфере есть непрочитанный символ, то она сразу удаляет его из буфера и возвращает.
  • В противном случае:
    • Программа приостанавливается, пока не придут новые данные
    • Когда они придут, они заносятся в буфер (их может быть ); за один раз так может быть прочитано он 1 символа до размера буфера (обычно 4—8КиБ).
    • После этого первый символ из этих данных извлекается из буфера и возвращается пользователю.

При этом данные не читаются непосредственно с клавиатуры непосредственно программой: между ними стоят слои другого ПО, например, драйвер клавиатуры, ОС, Драйвер терминала, Эмулятор терминала и т.п.

Так вот, одна из таких программ накапливает пользовательские нажатия клавиш, в частности, она обрабатывает, нажатия на Backspace и занимается выводом определённых символов на экран. А когда пользователь нажмёт Enter, то эта программа отправит накопленный ввод уже прикладной программе.


Если после вывода на экран первого символа, набрать еще символ (или несколько), скажем 'd':

ad
bc

Как тут работает буферизация?

printf("a");   // Выводим 'a'

getchar();     // Буфер пуст ⇒ ожидаем ввод
               // Ввод пользователя отображается на экране во время ввода
               // Пользователь ввёл 2 символа: {'d','\n'}
               // Заносим их в буфер, извлекаем 'd', в буфере остаётся {`\n`}

printf("b");   // Выводим 'b'

getchar();     // Буфере не пуст ⇒ извлекаем символ '\n' и возвращаем его
               // т.к. в буфере были данные и запрашивать данные от пользователя 
               // было не надо, то и паузы, соответственно, нет

printf("c\n"); // Выводим 'с' и '\n'
→ Ссылка