Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛекцииЛаб(Часть_2_Книги).doc
Скачиваний:
5
Добавлен:
03.05.2019
Размер:
988.16 Кб
Скачать

1.4. Закрытие файла.

Связь потока с файлом уничтожается с помощью операции закрытия. При этом всё содержимое буфера сбрасывается во внешнее устройство. При необходимости информация дописывается до создания полного сектора. Это так называемая очистка буфера. Файл может быть закрыт и автоматически после завершения программы. Но лучше это сделать самому с помощью функции fclose, когда файл больше не нужен. Дело в том, что некоторые события, например, выключение компьютера до завершения программы, могут помешать записи буфера на диск. Кроме этого, существует ограничение на количество одновременно открытых файлов. Не выполнив закрытие файла, например, после его созданиия, мы не всегда сможем открыть его повторно для работы в другом режиме, например, для чтения.

Функция int fclose(FILE *stream) выполняет следующие действия:

выполняет системные операции по закрытию файла, связанного с указанным потоком;

сохраняет в файле данные дискового буфера, если выполняли запись в файл, то есть очищает буфер;

освобождает память, выделенную для буфера;

освобождает оперативную память, зарезервированную функцией fopen под структуру типа FILE. то есть освобождает блок управления файлом;

разрывает связь потока с файлом.

В случае успешного выполнения этих действий функция закрытия файла возвращает 0. В противном случае возвращается ненулевое значение. Поэтому можно записать, например, так: if (fclose(fp)) printf (“\nClosing file: error”);

Если надо закрыть все открытые на данный момент файлы, то необходимо использовать функцию int fcloseall();. Она закрывает все открытые потоки, кроме стандартных stdin, stdout, stdprn и других.

§2. Работа с текстовым файлом

2.1. Посимвольная работа с текстовым файлом

Пример 1. Составим функции для посимвольного создания файла, добавления символов в конец и чтения файла по одному символу .

FILE *cf; char ch;

//Функция для создания текстового файла

void MyCreate()

{ if ((cf=fopen("d:\\ANA\\cpp\\2005_06\\ FileChar\\textf1.dat","w"))==NULL)

{ printf("Error\n"); return ; }

else printf("File is opened for creating\n");

cout<<" 0 – exit\n";

do { ch=getchar(); //Чтение одного символа с экрана

fputc(ch,cf); }

//Один символ из оперативной памяти(ch) перемеcтили в файл(cf).

while (ch!='0');

fclose(cf); }

/* Объявление, открытие и закрытие файла объяснялось в §1. Функция

Int fputc(int ch, file *stream)

записывает один символ в указанный поток в позицию, соответствующую текущему значению указателя положения в файле и после этого даёт ему приращение. В качестве первого фактического параметра естественно использовать символьную переменную. Если используется целое число, то старший байт отбрасывается. Функция возвращает значение записанного символа. Заметим, что в приведенном выше алгоритме символ ‘0’ будет записан в файл. Позже можно использовать его для проверки, весь ли файл прочитан. Если по какой-либо причине этот символ записывать в файл не надо, можно цикл изменить так:

do { ch=getchar(); if ch == '0') break;

fputc(ch,cf); } while (1); */

// Функция для добавления символов в конец созданного текстового файла

void MyAppend()

{if(cf=fopen("d:\\ANA\\cpp\\2005_06\\FileChar\\textf1.dat”,"a")) ==NULL)

{ printf("Error\n"); return ;

}

else printf("File is opened for appending\n");

cout<<"# – exit\n"<<endl;

do { ch=getchar();

fputc(ch,cf);

}

while (ch!='#'); fclose(cf);

}

/* Как видим, эта функция почти ничем не отличается от предыдущей функции создания файла. Только при открытии файла вместо режима “w” указан “a”, так как мы открываем файл для добавления в его конец. */

//Функция для просмотра созданного файла, то есть для вывода на экран.

void MyRead()

{ puts("look file");

if ((cf= fopen("d:\\ANA\\cpp\\2005_06\\ FileChar\\textf1.dat ","r"))==NULL)

{ printf("Error during opening a file\n"); return ;

}

ch=fgetc(cf); /* читаем первый символ вне цикла из файла (cf) и размещаем его в оперативную память в ячейку ch */

while (ch!=EOF) //или while(!feof(cf)) ( + )

{ putchar(ch); //вывод прочитанного символа ch на экран

ch=fgetc(cf); } // читаем очередной символ в цикле

fclose(cf); }

int main()

{ int flag=1;

while (1) { cout << "\n1 -- CREATE"<<endl<<

"2 -- READ"<<endl<<

"3 -- APPEND"<<endl<<

"0 -- EXIT"<<endl;

cin>>flag; switch (flag)

{ case 1: MyCreate(); break;

case 2: MyRead(); break;

case 3: MyAppend(); break;

case 0: return 0;

}

}

}

Функция int fgetc (FILE *stream) возвращает следующий за текущей позицией символ из входного потока и даёт приращение указателю положения в файле. При достижении конца файла и в случае ошибки чтения функция возвращает целое число EOF. Это значение, как видим, можно использовать для организации цикла.

Для двоичных файлов такой способ неприемлим. Дело в том, что может быть прочитано целочисленное значение, равное EOF. В результате fgetc() будет отображать состояние наличия конца файла, хотя физический конец ещё реально не достигнут.

Во втором варианте для проверки, достигнут ли конец как текстового, так и двоичного файла, связанного с указанным потоком, можно использовать функцию int feof(cf). Она возвращает ненулевое значение, если указатель положения в файле находится в его конце, то есть если достигнут конец файла. В имени функции первые буквы словосочетания End Of File (конец файла). В противном случае возвращается нуль. Особенно эта функция полезна при работе с двоичным файлом. В этом случае надо явно вызывать эту функцию, а не просто сравнивать возвращаемую переменную с целочисленным значением, равным EOF, как это разрешено для текстового файла.

Заметим, что может быть не просто чистый просмотр содержимого файла, как это сделано в приведённой функции MyRead(). В простейшем случае для посимвольного анализа прочитанного из файла текста внутри цикла кроме вывода символа необходимо записать один или несколько операторов для анализа символа. Например, для подсчёта количества букв алфавита верхнего или нижнего регистра необходимо в цикле записать

if (isalpha ( ch)) k++; ,

а перед заголовком цикла int k=0;

С помощью прочитанных символов можно сформировать одну или несколько строк. После этого для их анализа рекомендуется использовать рассмотренные ранее строковые функции.

В головной функции вывели простое меню, которое позволяет в цикле вызывать функции для работы с файлом в любом порядке и любое количество раз. Для начального создания файла надо ввести число 1. Затем можем просмотреть созданный файл (введём 2), добавить в конец одну или несколько строк символов (введём 3) и повторно можем ещё раз вывести измененный файл на экран, введя повторно число 2. Чтобы прекратить выполнение программы, надо ввести число 0.