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

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

56 голосов
/ 05 декабря 2010

Я сейчас читаю книгу «Язык программирования С» Ритчи и Кернигана.И я довольно озадачен использованием 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', что имеет большой смысл.

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

Ответы [ 3 ]

79 голосов
/ 05 декабря 2010

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

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

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

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

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

16 голосов
/ 05 декабря 2010

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

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

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

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

7 голосов
/ 05 декабря 2010

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

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

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

  3. для эмуляции EOF при чтении из stdin нажмите Ctrl + D

...