Шрифт:
Интервал:
Закладка:
if((in=fopen("test", "r"))!= NULL)
Заполнение диска, использование запрещенного имени или некоторые другие причины могут препятствовать открытию файла. Поэтому побеспокойтесь, чтобы их не было - маленькая ошибка может увести вас очень далеко.
Закрыть файл проще.
Закрытие файла: fclose( )
Наш пример показывает, как закрывать файл:
fclose(in);
Просто используйте функцию fclose( ). Заметим, что аргументом ее является in, указатель на файл, а не test, имя файла.
Для программы, более серьезной, чем эта, следовало бы посмотреть, успешно ли закрыт файл. Функция fclose( ) возвращает значение 0, если файл закрыт успешно, и -1 в противном случае.
Текстовые файлы с буферизацией
Функции fopen() и fclose() работают с текстовыми файлами с "буферизацией". Под буферизацией мы понимаем, что вводимые и выводимые данные запоминаются во временной области памяти, называемой буфером. Если буфер заполнился, содержимое его передается в блок, и процесс буферизации начинается снова. Одна из основных задач fclose( ) заключается в том, чтобы "освободить" любые частично заполненные буфера, если файл закрыт.
Текстовым считается файл, в котором информация запоминается в виде символов в коде ASCII (или аналогичном). Он отличается от двоичного файла, который обычно используется для запоминания кодов машинного языка. Функции ввода-вывода, о которых мы собираемся рассказать, предназначены только для работы с текстовыми файлами.
Ввод-вывод файла: getc( ) и putc( )
Две функции getc( ) и putc( ) работают аналогично функциям getchar( ) и putchar( ). Разница заключается в том, что вы должны сообщить новичкам, какой файл следует использовать. Таким образом, наш "старый дружище"
ch = getchar( );
предназначен для получения символа от стандартного ввода, а
ch = getc(in);
- для получения символа от файла, на который указывает in. Аналогично функция
putc(ch, out);
предназначена для записи символа ch в файл, на который ссылается указатель out типа FILE. В списке аргументов функции putc( ) этот символ стоит первым, а затем указатель файла. В нашем примере мы использовали
putc(ch, stdout);
где stdout является указателем на стандартный вывод. Таким образом, этот оператор эквивалентен
putchar(ch);
Действительно, оператор putchar(ch) определен директивой #define так же как функция putc(ch, stdout) определена в файле stdio.h. Этот ужасный файл к тому же определяет в директиве #define указатели stdout и stdin на стандартный вывод и стандартный ввод системы.
Это выглядит довольно просто? Хорошо, добавим пару полезных новшеств.
ПРОСТАЯ ПРОГРАММА СЖАТИЯ ФАЙЛА
В нашем примере имя файла, который следовало открыть, было записано в программе. Мы нс обязаны считаться с этим ограничением. Используя аргументы командной строки, можно сообщить нашей программе имя файла, который хотим считать. B нашем следующем примере (рис. 15.1) так и происходит. С помощью примитивного приема сжимается содержимое - остается только каждый третий символ. Наконец, сжатая версия размещается в новый файл, имя которого состоит из старого имени с добавкой .red (сокращение слова reduced). Обычно весьма важны первый и последний элементы (аргумент командной строки и добавка к имени файла). Само же сжатие имеет более ограниченное применение, но, как вы увидите, им можно пользоваться.
/* сожмите ваши файлы в 2-3 раза! */
#include <stdio.h>
main(argc, argv)
int argc;
char *argv[ ];
{
FILE *in, *out; /* описывает два указателя типа FILE */
int ch;
static char name[20]; /* память для имени выходного файла */
int count = 0;
if(argc < 2) /* проверяет, есть ли входной файл */
printf(" Извините, мне нужно имя файла в качестве аргумента.n" );
else
{ if((in = fopen(argv[1], "r")) != NULL)
{
strcpy(name, argv[1]; /* копирует имя файла в массив */
strcat(name, ".red"); /* добавляет .red к имени */
out = fopen(name, "w"); /* открывает файл для записи */
while((ch = getc(in)) ! = EOF)
if( count ++ %3 ==0)
putc(ch, out); /* печатает каждый третий символ */
fclose(in);
fclosе(out); }
else
printf(" Я не смогла открыть файл" %s" .n", argv[1]);
} }
РИС. 15.1. Программа сжатия файла.
Мы поместили программу в файл, названный reduce и применили эту программу к файлу, названному eddy, который содержал одну единственную строку
Даже Эдди нас опередил с детским хором.
Была выполнена команда
reduce eddy
и на выходе получен файл, названный eddy.red, который содержит
Дед спел тихо
Какая удача! Наш случайно выбранный файл сделал осмысленное сокращение.
Вот некоторые замечания по программе.
Вспомните, что argc содержит определенное количество аргументов, в число которых входит имя программного файла. Вспомните также, что с согласия операционной системы argv[0] представляет имя программы, т. е. в нашем случае reduce. Вспомните еще, что argv[l] представляет первый аргумент, в нашем случае eddy. Так как сам argv[l] является указателем на строку, он не должен заключаться в двойные кавычки в операторе вызова функции.
Мы используем argc, чтобы посмотреть, есть ли аргумент. Любые избыточные аргументы игнорируются. Помещая в программу еще один цикл, вы могли бы использовать дополнительные аргументы - имена файлов и пропускать в цикле каждый из этих файлов по очереди.
С целью создания нового имени выходного файла мы используем функцию strcpy( ) для копирования имени eddy в массив nаmе. Затем применяем функцию strcat( ) для объединения этого имени с .red.
Программа требует, чтобы два файла были открыты одновременно, поэтому мы описали два указателя типа 'FILE '. Заметим, что каждый файл должен открываться и закрываться независимо от другого. Существует ограничение на количество файлов, которые вы можете держать открытыми одновременно. Оно зависит от типа системы, но чаще всего находится в пределах от 10 до 20. Можно использовать один и тот же указатель для различных файлов при условии, что они нс открываются в одно и то же время.
Мы не ограничиваемся использованием только функций getc( ) и putc( ) для файлов ввода-вывода. Далее мы рассмотрим некоторые другие возможности.
ВВОД-ВЫВОД ФАЙЛА: fprintf( ), fscanf( ), fgets( ) И fputs( )
Все функции ввода-вывода, которые мы использовали в предыдущих главах, имеют аналоги для ввода-вывода файла. Основное отличие состоит в том, что вам нужно использовать указатель типа FILE, чтобы сообщить новым функциям, с каким файлом им следует работать. Подобно getc( ) и putc( ) эти функции используются после функции fopen( ), открывающей файл, и перед fclose( ), закрывающей его.
Функции fprintf( ) и fscanf( )
Эти функции ввода-вывода работают почти как printf( ) и scanf( ), но им нужен дополнительный аргумент для ссылки на сам файл. Он является первым в списке аргументов. Вот пример, иллюстрирующий обращение к этим функциям:
/* образец использования fprintf( ) и fscanf( ) */
#include <stdio.h>
main( )
{
FILE *fi;
int age;
fi = fopen("sam", "r"); /* считывание */
fscanf(fi, "%d", &age); /* fi указывает на sam */
fclose(fi);
fi = fopen("data", "a"); /* дополнение "/
fprintf(fi, "sam is %d. n", age); /* fi указывает на data */
fclose(fi);
}
Заметим, что можно было использовать fi для двух различных файлов, потому что мы закрыли первый файл, прежде чем открыть второй.
В отличие от getc( ) и putc( ) эти две функции получают указатель типа FILE в качестве первого аргумента. Две другие, описанные ниже, получают его в качестве последнего аргумента.
Функция fgets( )
Эта функция имеет три аргумента, в то время как gets( ) имеет один. Вот пример ее использования:
/* считывает файл строка за строкой */
- C++ - Страустрап Бьярн - Программирование
- Искусство программирования на языке сценариев командной оболочки - Мендель Купер - Программирование
- Delphi. Учимся на примерах - Сергей Парижский - Программирование