Getchar читает ctrl+z или возвращает EOF?

У меня есть этот код:

#include <stdio.h>

int main(void) {

int d=0;

d = getchar();
printf("%d\n", d);

}

Выход:

^Z
-1

Насколько я понимаю, здесь могут произойти две вещи:

  1. Getchar читает ctrl+z и возвращает его.
  2. Getchar ничего не читает и возвращает EOF.

Есть ли еще варианты? Какой из двух правильный?

^Z, который вы видите, не является входным значением: это эхо от обработчика клавиатуры, как и в случае с другими клавишами, которые вы нажимаете. Вариант 3: getchar() считывает значение Ctrl-Z26 и преобразует его в флаг EOF.

Weather Vane 23.03.2024 16:59

В этом случае значение все равно присваивается d. В вашем предыдущем примере сканирования этого не было.

Weather Vane 23.03.2024 17:05

@WeatherVane Большое спасибо! У меня только один дополнительный вопрос: когда я смотрю на таблицу ASCII, там написано, что 25 — это «конец среды», а 26 — «замена». Может быть, это 25, а не 26?

user394334 23.03.2024 17:22
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
3
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

В этом есть две части:

  1. Что делает getchar().
  2. Что делает консоль/ОС/среда выполнения.

Что делает getchar(), понятно:

Возвращает EOF (-1) в случае любого сбоя. Если сбой вызван концом файла, дополнительно устанавливается индикатор eof (см. feof() на стандартном вводе).

Что в этом случае делает консоль ОС (Windows):

  1. Получите ввод Ctrl-Z (непечатаемый управляющий символ ASCII 26)
  2. Отображает непечатаемое сочетание клавиш Ctrl-Z как ^Z
  3. Перехватывает Ctrl-Z как EOF и вставляет EOF в стандартный ввод (не Chr.26).

Обратите внимание, что сочетание клавиш Ctrl-Z (SUB) характерно для Windows, MS-DOS и до этого CP/M. В CP/M SUB использовался для расширения файлов до размеров, кратных 128 байтам (требование его примитивной файловой системы), поэтому для файлов, размер которых не кратен 128 байтам, он по сути обозначал конец файла. В Unix и Linux используется сочетание клавиш Ctrl-D (EOT — конец передачи), что, возможно, имеет больше смысла, но на самом деле ни то, ни другое не является концом файла, терминология происходит от рассмотрения stdin как потока «файла», что упрощает интерфейсы драйверов устройств и перенаправление.

Итак, система (Windows) рассматривает Ctrl-Z в консоли как инструкцию по вставке EOF во входной поток консоли, а getchar() возвращает EOF и устанавливает флаг EOF входного потока. Повторение ^Z (или любого символа) является специфичным для платформы побочным эффектом. getchar() на самом деле ничего не повторяет.

На самом деле это не конец потока, и ввод может возобновиться после вызова одного из rewind(), fsetpos(), fseek() или clearerr().

Также обратите внимание, что это строго поведение входного потока консоли. Если бы stdin был перенаправлен из файла, EOF был бы указан в истинном конце файла, и этот файл мог бы содержать символы Ctrl-Z (SUB), и они были бы возвращены getchar() как значение 26.

В качестве примечания: когда файл открывается в текстовом режиме в Windows, символ 26 обрабатывается так же, как и раньше, и чтение файла заканчивается на этом этапе.

Weather Vane 23.03.2024 19:16

Большое спасибо! Значит, именно Windows, а не getchar преобразует 26 в -1? Вы говорите: «Итак, система (Windows) рассматривает Ctrl-Z в консоли как инструкцию по вставке EOF в поток ввода консоли», означает ли это, что она вставляет -1 в поток ввода консоли?

user394334 23.03.2024 20:35

@user394334 user394334 Я действительно говорю, что это «как если бы» EOF был вставлен в Steam. Точная базовая реализация может не делать именно этого. Это модель поведения, которая подходит для написания кода с использованием stdio. Если вам нужен больший контроль на более низком уровне, используйте API консоли Windows

Clifford 23.03.2024 20:48

Последний вопрос: Итак, после этого getchar просматривает поток и обнаруживает EOF, который Windows поместила в поток, и возвращает EOF, который теперь равен -1 (то есть getchar устанавливает его как -1?)?

user394334 23.03.2024 20:51

@WeatherVane Я кое-что узнал. Но опять же, непечатаемый символ в середине текстового файла был бы необычным. Возможно, мне придется проверить свое утверждение о том, что это не вызывает EOF при перенаправлении на стандартный ввод.

Clifford 23.03.2024 20:54

Я проверил это, прежде чем оставить свой комментарий.

Weather Vane 23.03.2024 20:56

@user394334 user394334 кто знает? Это имеет значение? А разве это не то же самое, что и ваш предыдущий вопрос? Суть «модели» поведения в том, что она не обязательно должна быть внутренне точной. Ему просто нужно соответствовать любому внешне наблюдаемому поведению.

Clifford 23.03.2024 20:58

@user394334 user394334 не имеет значения, как это произойдет. В случае перенаправления ввода файла Crtl-Z или Ctrl-D отсутствуют (с учетом моего первого комментария).

Weather Vane 23.03.2024 20:58

Клиффорд, я предполагаю, что это сделано для того, чтобы сохранить совместимость с древними текстовыми файлами, существовавшими до NT. Конечно, 0x1A, вероятно, находится не в середине файла, а в конце, и желательно не читать его как символ (в любом случае это не текст).

Weather Vane 23.03.2024 21:07

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