Функция fwrite() возвращает количество успешно записанных элементов. Обычно оно равно nmemb, однако может быть меньше, если произошла ошибка записи.
ФУНКЦИЯ size_t fread()
Прототип функции fread() имеет следующий вид:
size_t fread(void * restrict ptr, size_t size, size_t nmemb,
FILE * restrict fp);
Функция fread() принимает такой же набор аргументов, как и fwrite(). На этот раз ptr представляет собой адрес области памяти, куда помещаются данные, прочитанные из файла, a fp идентифицирует читаемый файл. Эту функцию следует использовать для чтения данных, которые были записаны в файл с помощью fwrite(). Например, вот как восстановить массив из 10 элементов double, сохраненный в пре дыдущем примере:
double earnings[10];
fread(earnings, sizeof (double), 10, fp);
Этот вызов копирует 10 значений размера double в массив earnings.
Функция fread() возвращает количество успешно прочитанных элементов. Обычно оно равно nmemb, однако может быть меньше, если произошла ошибка записи или был достигнут конец файла.
ФУНКЦИИ int feof (FILE *fp) И int ferror (FILE *fp)
Когда стандартные функции ввода возвращают EOF, это обычно означает, что достигнут конец файла. Тем не менее, возврат EOF может также указывать на возникновение ошибки чтения. Функции feof() и ferror() позволяют проводить различие между этими двумя возможностями. Функция feof() возвращает ненулевое значение, если при последнем вызове функции ввода был обнаружен конец файла, и ноль в противном случае. Функция ferror() возвращает ненулевое значение, если произошла ошибка чтения или записи, и ноль в противном случае.
Пример использования fread() И fwrite()
Давайте воспользуемся некоторыми из этих функций в программе, которая добавляет содержимое из списка файлов в конец указанного файла. Одна из задач заключается в передаче внутрь программы информации о файлах. Это можно делать интерактивно или с помощью аргументов командной строки. Мы примем первый подход, который предполагает выполнение перечисленных ниже действий.
554 глава 13
• Запрос имени файла назначения и его открытие.
• Применение цикла для запроса исходных файлов.
• Поочередное открытие каждого исходного файла в режиме чтения и добавление его содержимого в конец файла назначения.
Чтобы проиллюстрировать работу функции setvbuf(), мы применим ее для установки другого размера буфера. Следующий этап детализации связан с открытием файла назначения. Мы будем использовать следующие шаги.
1. Открытие файла назначения в режиме добавления.
2. Если сделать это не удается, то завершение работы.
3. Установка буфера размером 4096 байтов для этого файла.
4. Если сделать это не удается, то завершение работы.
Аналогично, мы можем уточнить часть программы, отвечающую за копирование, для чего выполнить с каждым файлом такие действия.
• Если это файл назначения, то пропустить его и перейти к следующему файлу.
• Если файл не может быть открыт в режиме чтения, то пропустить его и перейти к следующему файлу.
• Добавить содержимое файла в файл назначения.
В завершение программа перейдет в начало файла назначения и отобразит его содержимое. В целях практики для копирования будут применяться функции fread() и fwrite(). Результирующий код приведен в листинге 13.5.
Листинг 13.5. Программа append.с

Файловый ввод-вывод 555

556 Глава 13
Если функции setvbuf() не удается создать буфер, она возвращает ненулевое значение, после чего программа прекращает работу. Похожий код устанавливает буфер размером 4096 байтов для файла, копируемого в текущий момент. За счет использования NULL во втором аргументе setvbuf() мы позволяем этой функции самостоятельно выделить память под буфер.
Для получения имени файла в программе применяется функция s_gets() вместо scanf(), т.к. scanf() пропускает пробельные символы и, следовательно, не сможет обнаружить пустую строку. Кроме того, в программе используется s_gets() вместо простой функции fgets(), потому что fgets() оставляет в строке символ новой строки.
Показанный ниже код предотвращает добавление содержимого файла в конец самого себя:
if (strcmp (file_src, file_app) == 0)
fputs ("Добавить файл в конец самого себя невозможною', stderr);
Аргумент file app представляет имя файла назначения, a file src — имя файла, обрабатываемого в текущий момент.
Функция append() выполняет копирование. Вместо копирования по одному байту за раз она применяет fread() и fwrite() для копирования по 4096 байтов за один раз:
Читать дальше