Почему putchar не возвращает новую строку при вводе с помощью getchar?

Компиляция с помощью 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 читает от конца к началу потока, при вводе четырех символов он читается как следует от начала до конца: если я наберу четыре символов возвращает первые три символа из буфера.

Это в UNIX-подобной ОС или в Windows? Я спрашиваю, потому что в Windows (и MS-DOS) новая строка — это CR + LF, что может объяснить описанное вами поведение.

Ruud Helderman 28.07.2019 20:28

Я компилирую в Clang и запускаю его в Linux, я только что обновил вопрос, чтобы отразить эту информацию. Благодарю вас!

NewStack 28.07.2019 21:07

Добавьте больше печати, чтобы вы могли видеть, с чем имеете дело. Например, замените каждый putchar() соответствующим вариантом printf("[%c] = %d\n", a, a);. Это покажет вам, что происходит, намного лучше, чем просто использование putchar() will.

Jonathan Leffler 28.07.2019 22:38

Привет, Джонатан, это дало мне больше информации, но все еще не проясняет для меня основную проблему. Когда я применяю этот код, я вижу, что поток буфера — это первый символ, перевод строки, а затем второй символ. Для меня это не ответ, почему окончательный поток, напечатанный с помощью put char, будет содержать только последний введенный символ. Это мне не ясно - если буфер: первая буква, перевод строки, вторая буква и putchar ждет заполнения буфера, а затем печатает полный буфер, я должен получить "X [LINE FEED] Y" с код в исходном сообщении, но я получаю только "Y"?

NewStack 28.07.2019 23:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
248
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

stdin обычно буферизуется строкой. Первому getchar() ничего не дается, пока не будет введено '\n'.

Также '\n' является одним из введенных символов.

Но тогда почему мне предлагается ввести только вторую букву, а не третью? Судя по вашему ответу, мне кажется, поведение будет таким: Введите букву, Новая строка (помещает первую букву в буфер), Введите вторую букву, Новая строка (помещает вторую букву в буфер), Введите третью букву, Новая строка ( помещает третью букву в буфер). Но так себя не ведет, после ввода первой буквы ждет секунду, потом после ввода второй возвращает вторую и завершает программу. Он никогда не запрашивает третью, и все, что должно быть в буфере в этот момент, это «X [НОВАЯ СТРОКА] Y [НОВАЯ СТРОКА]»

NewStack 28.07.2019 20:25

@NewStack «Введите букву, Новая строка (помещает первую букву в буфер) Введите вторую букву, Новая строка ..." --> новая линия — вторая буква. «Введите букву, новая строка (помещает первую букву в буфер)» помещает 2 буквы в stdin.

chux - Reinstate Monica 28.07.2019 21:43

@NewStack Вместо putchar(a); используйте printf("%d <%c>\n", a, a);, чтобы увидеть больше информации.

chux - Reinstate Monica 28.07.2019 21:47

Я использовал этот код в комментарии к своему исходному сообщению, но предоставленная им информация по-прежнему не отвечает на вопрос, почему я не получаю «Первое письмо [новая строка] Второе письмо» от putchar() после заполнения буфера. Это имело бы смысл. Я получаю только "Второе письмо". Итак, почему я получаю только второе письмо, почему я не получаю «Первое письмо [новая строка] Второе письмо» после заполнения буфера.

NewStack 28.07.2019 23:45

@NewStack Думайте об этом как о двух буферах: stdin и буфере клавиатура. Буфер клавиатура передает свою строку данных в stdin обычно при вводе '\n'. С вводом "X\nY\nZ\n", a = getchar(); ждет, пока stdin что-то получит. Это первое что-то "X\n", а 'X' возвращается, оставляя '\n' на потом. b = getchar(); затем возвращается '\n'. Позже c = getchar(); чего-то ждет. Это что-то есть "Y\n", а 'Y' возвращается, оставляя '\n' на потом.

chux - Reinstate Monica 29.07.2019 00:15

Спасибо, Чукс, я слежу за тобой, но вопрос в том, что случилось с X?

NewStack 29.07.2019 00:34

Насколько я понимаю, в приведенном выше коде putchar должен ждать заполнения буфера, прежде чем выводить что-либо на экран. Верно ли это понимание? Потому что, если нет, это может быть то, где я пропускаю информацию. Поведение следующее: 1) я набираю символ и нажимаю Enter, 2) он возвращает этот символ и ждет другого 3) я ввожу второй символ и нажимаю Enter 4) он возвращает второй символ. Я думал, что перед генерацией вывода буфер должен быть заполнен 3 символами, если это неверно, это может меня сбить с толку.

NewStack 29.07.2019 00:39

@NewStack A) «Правильно ли это понимание?» Нет. putchar() не ждет. Он отпечатки своего персонажа, помещая его в stdio, а затем возвращается. Это не значит, что вы еще ничего не видите. stdio имеет собственный буфер выход, который может не отображаться на вашем экране, пока он не получит '\n' - или промывать. Используйте fflush(stdout); после каждого вывода. B) понять, что «я ввожу символ и нажимаю Enter» и «я ввожу второй символ и нажимаю Enter» помещают 4 символа в stdin. Потребуется 4 getchar(), чтобы получить их все.

chux - Reinstate Monica 29.07.2019 00:46

Другие вопросы по теме