Компиляция с помощью Clang/GCC и запуск в Linux:
При выполнении следующего кода я столкнулся с непредвиденным для меня поведением: при вводе одного символа («X») мне будет предложено ввести другой символ («Y»), предположительно, потому что буфер не заполнен. Когда я ввожу второй символ ("Y"), putchar отображает только второй символ ("Y" - он не возвращает первый "X" и не содержит новых строк/разрывов строк). Я предполагаю, что это связано с тем, что putchar читает поток от конца к началу и читает буфер как «[NEW LINE] Y [NEW LINE]», а исходный «X» уже находится за пределами буфера, выделенного для трех переменных. . Но это чтение от конца к началу потока, похоже, не согласуется с обычным поведением putchar — если я наберу четыре символа «XYZA» и нажму Enter, он вернет поток от начала до конца, понятно усеченный: «XYZ ".
Мой первый вопрос: верны ли мои предположения выше, мой второй вопрос: если да, то почему putchar не выводит новые строки, которые предположительно находятся в буфере. Если бы я получил "[NEW LINE] Y [NEW LINE]" в качестве вывода, мне было бы ясно, что происходит, но я просто получаю "Y". Это почему? Обрезает ли putchar пробельные элементы или getchar читает новую строку каким-то образом, который не преобразуется в символ escape-последовательности?
Я пробовал несколько комбинаций использования клавиши ввода, но не понимаю, как это работает. Я хотел бы знать, что он делает.
int main() {
int a,b,c;
printf("Type three letters: ");
a = getchar();
putchar(a);
b = getchar();
putchar(b);
c = getchar();
putchar(c);
}
При выполнении вышеуказанного:
Если я ввожу три символа, он возвращает три символа.
Если я наберу два символа (например, «XY»), он вернет два символа, предположительно потому, что третий символ — это новая строка, сгенерированная нажатием клавиши ввода. Это ДЕЙСТВИТЕЛЬНО отображает новую строку после отображения «XY», что делает следующее поведение гораздо более запутанным для меня:
Если я набираю один символ, он запрашивает другой символ, когда я набираю другой символ, он возвращает только второй символ. Почему это? Мне кажется, что он читает буфер с конца в начало и обрезает пробелы, но это маловероятно. Я не понимаю такого поведения.
Несмотря на то, что я получаю только один символ из последнего примера, что мне кажется из-за того, что putchar читает от конца к началу потока, при вводе четырех символов он читается как следует от начала до конца: если я наберу четыре символов возвращает первые три символа из буфера.
Я компилирую в Clang и запускаю его в Linux, я только что обновил вопрос, чтобы отразить эту информацию. Благодарю вас!
Добавьте больше печати, чтобы вы могли видеть, с чем имеете дело. Например, замените каждый putchar()
соответствующим вариантом printf("[%c] = %d\n", a, a);
. Это покажет вам, что происходит, намного лучше, чем просто использование putchar()
will.
Привет, Джонатан, это дало мне больше информации, но все еще не проясняет для меня основную проблему. Когда я применяю этот код, я вижу, что поток буфера — это первый символ, перевод строки, а затем второй символ. Для меня это не ответ, почему окончательный поток, напечатанный с помощью put char, будет содержать только последний введенный символ. Это мне не ясно - если буфер: первая буква, перевод строки, вторая буква и putchar ждет заполнения буфера, а затем печатает полный буфер, я должен получить "X [LINE FEED] Y" с код в исходном сообщении, но я получаю только "Y"?
stdin
обычно буферизуется строкой. Первому getchar()
ничего не дается, пока не будет введено '\n'
.
Также '\n'
является одним из введенных символов.
Но тогда почему мне предлагается ввести только вторую букву, а не третью? Судя по вашему ответу, мне кажется, поведение будет таким: Введите букву, Новая строка (помещает первую букву в буфер), Введите вторую букву, Новая строка (помещает вторую букву в буфер), Введите третью букву, Новая строка ( помещает третью букву в буфер). Но так себя не ведет, после ввода первой буквы ждет секунду, потом после ввода второй возвращает вторую и завершает программу. Он никогда не запрашивает третью, и все, что должно быть в буфере в этот момент, это «X [НОВАЯ СТРОКА] Y [НОВАЯ СТРОКА]»
@NewStack «Введите букву, Новая строка (помещает первую букву в буфер) Введите вторую букву, Новая строка ..." --> новая линия — вторая буква. «Введите букву, новая строка (помещает первую букву в буфер)» помещает 2 буквы в stdin
.
@NewStack Вместо putchar(a);
используйте printf("%d <%c>\n", a, a);
, чтобы увидеть больше информации.
Я использовал этот код в комментарии к своему исходному сообщению, но предоставленная им информация по-прежнему не отвечает на вопрос, почему я не получаю «Первое письмо [новая строка] Второе письмо» от putchar() после заполнения буфера. Это имело бы смысл. Я получаю только "Второе письмо". Итак, почему я получаю только второе письмо, почему я не получаю «Первое письмо [новая строка] Второе письмо» после заполнения буфера.
@NewStack Думайте об этом как о двух буферах: stdin
и буфере клавиатура. Буфер клавиатура передает свою строку данных в stdin
обычно при вводе '\n'
. С вводом "X\nY\nZ\n"
, a = getchar();
ждет, пока stdin
что-то получит. Это первое что-то "X\n"
, а 'X'
возвращается, оставляя '\n'
на потом. b = getchar();
затем возвращается '\n'
. Позже c = getchar();
чего-то ждет. Это что-то есть "Y\n"
, а 'Y'
возвращается, оставляя '\n'
на потом.
Спасибо, Чукс, я слежу за тобой, но вопрос в том, что случилось с X?
Насколько я понимаю, в приведенном выше коде putchar должен ждать заполнения буфера, прежде чем выводить что-либо на экран. Верно ли это понимание? Потому что, если нет, это может быть то, где я пропускаю информацию. Поведение следующее: 1) я набираю символ и нажимаю Enter, 2) он возвращает этот символ и ждет другого 3) я ввожу второй символ и нажимаю Enter 4) он возвращает второй символ. Я думал, что перед генерацией вывода буфер должен быть заполнен 3 символами, если это неверно, это может меня сбить с толку.
@NewStack A) «Правильно ли это понимание?» Нет. putchar()
не ждет. Он отпечатки своего персонажа, помещая его в stdio
, а затем возвращается. Это не значит, что вы еще ничего не видите. stdio
имеет собственный буфер выход, который может не отображаться на вашем экране, пока он не получит '\n'
- или промывать. Используйте fflush(stdout);
после каждого вывода. B) понять, что «я ввожу символ и нажимаю Enter» и «я ввожу второй символ и нажимаю Enter» помещают 4 символа в stdin
. Потребуется 4 getchar()
, чтобы получить их все.
Это в UNIX-подобной ОС или в Windows? Я спрашиваю, потому что в Windows (и MS-DOS) новая строка — это CR + LF, что может объяснить описанное вами поведение.