Самый простой механизм ввода заключается в чтении по од-ному символу за раз из "стандартного ввода", обычно с терми-нала пользователя, с помощью функции GETCHAR. ФункцияGETCHAR() при каждом к ней обращении возвращает следующий вводимый символ. В большинстве сред, которые поддерживаютязык "с", терминал может быть заменен некоторым файлом с по-мощью обозначения < : если некоторая программа PROG исполь-зует функцию GETCHAR то командная строка PROG<INFILE приведет к тому, что PROG будет читать из файла INFILE, а нес терминала. Переключение ввода делается таким образом, чтосама программа PROG не замечает изменения; в частности стро-ка"<INFILE" не включается в командную строку аргументов вARGV. Переключение ввода оказывается незаметным и в том слу-чае, когда вывод поступает из другой программы посредствомпоточного (PIPE) механизма; командная строка OTHERPROG \! PROG прогоняет две программы, OTHERPROG и PROG, и организует так,что стандартным вводом для PROG служит стандартный выводOTHERPROG. Функция GETCHAR возвращает значение EOF, когда она попа-дает на конец файла, какой бы ввод она при этом не считыва-ла. Стандартная библиотека полагает символическую константуEOF равной -1 (посредством #DEFINE в файле STDIO.H), но про-верки следует писать в терминах EOF, а не -1, чтобы избежатьзависимости от конкретного значения. Вывод можно осуществлять с помощью функции PUTCHAR(C),помещающей символ 'с' в "стандартный ввод", который по умол-чанию является терминалом. Вывод можно направить в некоторыйфайл с помощью обозначения > : если PROG использует PUTCHAR,то командная строка PROG>OUTFILE приведет к записи стандартного вывода в файл OUTFILE, а нена терминал. На системе UNIX можно также использовать поточ-ный механизм. Строка PROG \! ANOTHERPROG помещает стандартный вывод PROG в стандартный вводANOTHERPROG. И опять PROG не будет осведомлена об изменениинаправления. Вывод, осуществляемый функцией PRINTF, также поступает встандартный вывод, и обращения к PUTCHAR и PRINTF могут пе-ремежаться. Поразительное количество программ читает только из одно-го входного потока и пишет только в один выходной поток; длятаких программ ввод и вывод с помощью функций GETCHAR,PUTCHAR и PRINTF может оказаться вполне адекватным и для на-чала определенно достаточным. Это особенно справедливо тог- да, когда имеется возможность указания файлов для ввода ивывода и поточный механизм для связи вывода одной программыс вводом другой. Рассмотрим, например, программу LOWER, ко-торая преобразует прописные буквы из своего ввода в строч-ные: #INCLUDE <STDIO.H> MAIN() /* CONVERT INPUT TO LOWER CASE */\( INT C; WHILE ((C = GETCHAR()) != EOF) PUTCHAR(ISUPPER(C) ? TOLOWER(C) : C);\) "Функции" ISUPPER и TOLOWER на самом деле являются макроса-ми, определенными в STDIO.H . Макрос ISUPPER проверяет, яв-ляется ли его аргумент буквой из верхнего регистра, и возв-ращает ненулевое значение, если это так, и нуль в противномслучае. Макрос TOLOWER преобразует букву из верхнего регист-ра в ту же букву нижнего регистра. Независимо от того, какэти функции реализованы на конкретной машине, их внешнее по-ведение совершенно одинаково, так что использующие их прог-раммы избавлены от знания символьного набора. Если требуется преобразовать несколько файлов, то можнособрать эти файлы с помощью программы, подобной утилите CATсистемы UNIX, CAT FILE1 FILE2 ... \! LOWER>OUTPUT и избежать тем самым вопроса о том, как обратиться к этимфайлам из программы. (Программа CAT приводится позже в этойглаве). Кроме того отметим, что в стандартной библиотеке вво-да/вывода "функции" GETCHAR и PUTCHAR на самом деле могутбыть макросами. Это позволяет избежать накладных расходов наобращение к функции для обработки каждого символа. В главе 8мы продемонстрируем, как это делается.