Подтвердить что ты не робот

Конец файла (EOF) в C

В настоящее время я читаю книгу программирования C на языке Ritchie и Kernighan. И я довольно смущен об использовании EOF в функции getchar().

Во-первых, я хочу знать, почему значение EOF равно -1 и почему значение getchar()!=EOF равно 0. Прошу прощения за мой вопрос, но я действительно не понимаю. Я действительно пытался, но не могу.

Затем я попытался запустить пример в книге, который может подсчитать количество символов, используя код ниже, но кажется, что я никогда не выхожу из цикла, даже если я нажимаю кнопку ввода, поэтому мне интересно, когда я смогу добраться до EOF

main(){
   long nc;
   nc = 0;
   while (getchar() != EOF)
       ++nc;
   printf("%ld\n", nc);
}

Затем я прочитал ту же проблему в Проблема с EOF в C. Большинство людей советовали, что вместо использования EOF используйте терминатор \n или нулевой терминатор '\ 0', который имеет большой смысл.

Означает ли это, что пример в книге служит другой цели?

4b9b3361

Ответ 1

EOF указывает "конец файла". Новая строка (это то, что происходит при нажатии клавиши ввода) - это не конец файла, это конец строки, поэтому новая строка не завершает этот цикл.

Код не ошибочен [*], он просто не делает то, что вы ожидаете. Он читает до конца ввода, но вы, кажется, хотите читать только до конца строки.

Значение EOF равно -1, потому что оно должно отличаться от любого возвращаемого значения из getchar, которое является фактическим символом. Таким образом, getchar возвращает любое значение символа как unsigned char, преобразованное в int, поэтому оно будет неотрицательным.

Если вы печатаете на терминале и хотите спровоцировать конец файла, используйте CTRL-D (системы с унифицированным стилем) или CTRL-Z (Windows). Затем, после того, как все данные были прочитаны, getchar() вернет EOF, и, следовательно, getchar() != EOF будет ложным, и цикл завершится.

[*] хорошо, он имеет поведение undefined, если ввод больше, чем символы LONG_MAX из-за переполнения целого числа, но мы можем, вероятно, простить это в простом примере.

Ответ 2

EOF равно -1, потому что это определено. Имя предоставляется стандартными заголовками библиотек, которые вы #include. Они делают его равным -1, потому что он должен быть чем-то, что нельзя ошибочно принять за фактический байт, прочитанный getchar(). getchar() сообщает значения фактических байтов с использованием положительного числа (от 0 до 255 включительно), поэтому -1 отлично подходит для этого.

Оператор != означает "не равно". 0 означает false, а все остальное - true. Итак, что происходит, мы вызываем функцию getchar() и сравниваем результат с -1 (EOF). Если результат не был равен EOF, тогда результат будет истинным, потому что вещи, которые не равны, не равны. Если результат был равен EOF, то результат будет ложным, потому что все одинаковые не являются (не равными).

Вызов getchar() возвращает EOF, когда вы достигаете "конца файла". Что касается C, то "стандартный ввод" (данные, которые вы передаете своей программе, введя в окне команд), точно так же, как и файл. Конечно, вы можете всегда вводить больше, поэтому вам нужен явный способ сказать "Я сделан". В системах Windows это control-Z. В системах Unix это control-D.

Пример в книге не "неправильный". Это зависит от того, что вы действительно хотите сделать. Чтение до тех пор, пока EOF не означает, что вы все читаете, пока пользователь не скажет "Я сделан", а затем вы больше не можете читать. Чтение до '\n' означает, что вы читаете строку ввода. Чтение до '\ 0' - плохая идея, если вы ожидаете, что пользователь наберет ввод, потому что это либо трудно, либо невозможно создать этот байт с помощью клавиатуры в командной строке:)

Ответ 3

Это много вопросов.

  • Почему EOF равен -1: обычно -1 в POSIX системные вызовы возвращаются при ошибке, поэтому я предполагаю, что идея "EOF - это некоторая ошибка"

  • любая логическая операция (включая! =) возвращает 1 в случае, если она ИСТИНА, и 0 в случае, если она ЛОЖЬ, поэтому getchar() != EOF есть 0, когда это ЛОЖЬ, то есть getchar() возвращается EOF.

  • чтобы эмулировать EOF при чтении из stdin нажмите Ctrl+D