Файловый ввод-вывод 537
функция fopen()
Далее в программе с помощью функции fopen() открывается файл. Эта функция объявлена в заголовочном файле stdio.h. Ее первым аргументом является имя файла, который необходимо открыть; точнее, это адрес строки, содержащей имя файла. Второй аргумент — строка, идентифицирующая режим, в котором файл должен быть открыт. В библиотеке С предоставляется несколько возможностей, показанных в табл. 13.1.
Таблица 13.1. Строки режима для fopen()

Для таких систем, как Unix и Linux, которые имеют только один файловый тип, режимы с буквой b эквивалентны соответствующим режимам без буквы b.
Новые режимы записи C11 с буквой х обладают парой новых характеристик но сравнению со старыми режимами записи. Во-первых, если вы пытаетесь открыть существующий файл в одном из традиционных режимов записи, то fopen() усекает файл до нулевой длины, в результате чего предыдущее содержимое файла утрачивается. Но режимы с буквой х обеспечивают в таком случае отказ функции fopen() от дальнейшей работы, не причиняя вреда файлу. Во-вторых, при условии, что это позволяет среда, возможность монопольного доступа в режимах с х предотвращает доступ к файлу со стороны других программ или потоков до тех пор, пока текущий процесс не закроет этот файл.
Внимание!
Если вы используете любой режим "w" без буквы х для существующего файла, содержимое файла усекается так, что программа может начать работу с чистого листа. Однако попытка открыть существующий файл с применением одного из режимов С11, содержащий букву х, завершится отказом.
538 Глава 13
После успешного открытия файла функция fopen() возвращает указатель файла, который затем другие функции ввода-вывода могут использовать для указания этого файла. Указатель файла (в примере это fp) имеет тип указателя на FILE; здесь FILE - производный тип, определенный в stdio.h. Указатель fp не ссылается на действительный файл. Вместо этого он указывает на объект данных, содержащий инфор мацию о файле, включая сведения о буфере, который применяется для файлового ввода-вывода. Гак как функции ввода-вывода из стандартной библиотеки используют буфер, им необходимо знать, где этот буфер находится. Им также должно быть известно, насколько заполнен буфер и с каким файлом осуществляется работа. Это позволяет функциям по мере необходимости заполнять или опустошать буфер. Вся эта информация содержится в объекте данных, указываемом fp. (Такой объект данных является примером структуры С, которые обсуждаются в главе 14.)
Функция fopen() возвращает нулевой указатель (также определенный в stdio.h), если ей не удается открыть файл. Когда указатель fp равен NULL, программа прекращает выполнение. Функция fopen() может отказать из-за переполнения диска, от сутствия файла в искомом каталоге, недопустимого имени, ограничений доступа или аппаратной проблемы. Это лишь небольшая часть причин отказа, так что ищите неполадку; даже минимальные меры по отлавливанию ошибок могут иметь большое значение.
ФУНКЦИИ getc() и putc()
Функции getc() и putc() работают очень похоже на getchar() и putchar(). Отличие заключается в том, что этим новым функциям потребуется указать, с каким файлом работать. Таким образом, приведенный ниже многократно использованный нами оператор означает “получить символ из стандартного ввода”:
ch = getchar();
Тем не менее, следующий оператор означает “получить символ из файла, идентифицируемого fp”:
ch = getc(fp);
Аналогично, показанный далее оператор означает “поместить символ ch в файл, идентифицируемый указателем fpout на FILE”:
putc(ch, fpout);
В списке аргументов putc() сначала задается символ, а затем указатель файла.
В листинге 13.1 во втором аргументе putc() применяется stdout. Он определен в stdio.h как указатель файла, ассоциированный со стандартным выводом, поэтому putc (ch, stdout) эквивалентно putchar (ch). На самом деле вторая функция обычно определена как первая. Аналогично, getchar() определена как функция getc(), использующая стандартный ввод.
Возможно, вас интересует, почему в этом примере применяется putc(), а не putchar(). Одна причина связана с необходимостью ознакомления с функцией putc(). Другая причина заключается в том, что вы легко можете преобразовать программу так, чтобы она могла генерировать файловый за счет использования аргумента, отличного от stdout.
конец файла
Программа, читающая данные из файла, должна останавливаться, когда она достигает конца файла. Как можно сообщить программе о том, что встретился конец файла?
Читать дальше