В некоторых системах EOF может быть определено как значение, не равное -1, но это определение всегда отличается от возвращаемого значения, генерируемого допустимым входным символом. Если вы включили файл stdio.h и применяете символическую константу EOF, то не обязаны беспокоиться о ее числовом определении. Важно понимать, что EOF представляет значение, сигнализирующее об обнаружении конца файла, а не значение, действительно находящееся файле.
А как использовать EOF в программе? Нужно сравнить возвращаемое значение getchar() с EOF. Если они отличаются, конец файла пока еще не достигнут. Другими словами, можно указывать выражение, подобное следующему:
while ((ch = getchar()) != EOF) !
Что, если производится чтение клавиатурного ввода, а не файла? Большинство систем (но не все) поддерживают какой-то способ эмулировать условие конца файла с помощью клавиатуры. С учетом этого базовую программу чтения и эхо-вывода можно переписать, как показано в листинге 8.2.
Листинг 8.2. Программа echo eof .с

Обратите внимание на перечисленные ниже аспекты.
Глава 8
• Вам не придется определять EOF, т.к. об этом уже позаботился заголовочный файл stdio.h.
• Вам не нужно беспокоиться о действительном значении EOF, поскольку оператор #define в файле stdio.h позволяет иметь дело с символическим представлением EOF. Вы не должны писать код, в котором предполагается, что EOF имеет какое-то конкретное значение.
• Тип переменной ch изменен с char на int, потому что переменные типа char могут быть представлены целочисленными значениями без знака в диапазоне от 0 до 255, но EOF может иметь числовое значение -1. Такое значение недопустимо для типа char без знака, но допустимо для типа int. К счастью, функция getchar() сама имеет тип int, поэтому она может читать символ EOF. В реализациях, поддерживающих тин char со знаком, можно обойтись объявлением переменной ch как имеющей тип char, но лучше применить более общую форму.
• Именно из-за того, что функция getchar() имеет тип int, некоторые компиляторы предупреждают о возможной потере данных при присваивании возвращаемого значения этой функции переменной типа char.
• Тот факт, что переменная ch является целочисленной, никак не беспокоит функцию putchar(). Она по-прежнему выводит символьный эквивалент.
• Чтобы использовать эту программу с клавиатурным вводом, необходим какой-то способ набора символа EOF. Понятно, что нельзя просто набрать буквы EOF или ввести -1. (Ввод с клавиатуры -1 приводит к передаче в программу двух символов: дефиса и цифры 1.) Взамен понадобится выяснить, какой символ требует система. Например, в большинстве систем Unix и Linux нажатие комбинации клавиш в начале строки вызывает передачу сигнала конца файла. Многие системы в качестве сигнала конца файла распознают комбинацию в начале строки, а некоторые интерпретируют ее как таковую в любом месте строки.
Ниже показан пример применения буферизированного ввода в программе echo eof.с под управлением Unix:
У него не было даже пальто.
У него не было даже пальто.
В город молодой человек вошел в зеленом в талию костюме.
В город молодой человек вошел в зеленом в талию костюме.
И. Ильф, Е. Петров
И. Ильф, Е. Петров
[Ctrl+D]
Каждый раз, когда вы нажимаете , хранящиеся в буфере символы обрабатываются, и копия строки выводится. Это продолжается вплоть до эмуляции конца файла в стиле Unix. В другой сисгеме пришлось бы нажать комбинацию .
Давайте подумаем о возможностях, доступных для программы echo_eof. с. Она копирует на экран любые переданный ей ввод. Предположим, что вы каким-то образом предоставили ей файл. Тогда программа выведет на экран содержимое этого файла, остановившись по достижении конца файла после обнаружения сигнала EOF. А еще представим, что вместо этого вы нашли способ направить вывод программы в файл. Тогда можно было ввести данные с клавиатуры и использовать echo_eof.с для их сохранения в файле. Далее предположим, что вам удалось сделать то и другое одновременно: направить ввод из одного файла в echo eof.с и переслать вывод в дру-
Символьный ввод-вывод и проверка достоверности ввода 301
гой файл. Тогда программу echo_eof.с можно было бы применять для копирования файлов. Эта небольшая программа обладает потенциалом для просмотра содержимого файлов, создания новых файлов и копирования существующих файлов — весьма неплохо для такой короткой программы! Ключом является управление потоком ввода и вывода, что и будет следующей рассматриваемой темой.
Читать дальше