Функции getchar()
и putchar()
являются частью пакета stdio
, который выполняет буферизованный ввод / вывод.
Это означает, что, несмотря на количество символов, которое вы на самом деле запрашиваете (один только в вашем случае), механизм буферизации заставляет символы ждать в буфере, пока весь буфер (или одна строка, в случае, если stdin
не получен из tty устройство) заполнено.
То, что здесь происходит, заключается в том, что при первом getchar()
запрашивается полное заполнение буфера, и оно только частично заполняется введенной вами строкой ввода. После этого все вызовы getchar()
получают отдельные символы из буфера, пока он снова не станет пустым, и в этот момент запрашивается другой полный буфер.
Это сделано для того, чтобы обработка одного символа была эффективным способом обработки. Это также происходит на выходе. Функция putchar()
заполняет только буфер до тех пор, пока он не будет полностью заполнен (или, если ваш выходной канал подключен к tty-устройству, пока вы не запросите вывод символа \n
), и когда это произойдет, будет выведен полный буфер к файлу / устройству.
Кроме того, драйвер терминала во всех разновидностях Unix работает в линейном режиме, что означает, что пока вы не нажмете клавишу <ENTER>
, вы ничего не отправите в программу. Это позволит вам исправить ошибки, допущенные при вводе, с помощью клавиш стирания (backspace) и / или клавиш kill (Cntrl-U). Это моделируется в консольных приложениях Windows, поэтому вам, вероятно, понадобится устройство вывода в необработанном режиме, прежде чем можно будет вводить символьным способом.
Если вы хотите, чтобы ваша программа считывала по одному символу за раз, вам нужно обойти буферы stdio (через вызов функции setbuf(NULL)
или используя системный вызов read(2)
для чтения одного символа, который может быть сделано с:
char c;
int res = read(0, &c, 1);
if (res < 0) { /* error */
...
} else if (res == 0) { /* EOF in input */
...
} else { /* 1, as you requested only one char */
... /* one character was read. */
}
) и перевести драйвер терминала в необработанный режим (с помощью вызовов tcsetattr()
и tcgetattr()
, см. Справочную страницу termios(4)
для получения подробной информации о том, как это сделать) перед тем, как приступить к чтению. В этом случае вы должны вернуть состояние терминала в линейный режим перед завершением программы, иначе у вас возникнут проблемы.