Основные алгоритмы работы с файлами
Для записи данных в файл нужно выполнить:
1. Описать переменную типа ofstream.
2. Открыть файл для записи с помощью функции open.
3. Вывести информацию в файл с помощью cout.
4. Обязательно закрыть файл.
Для чтения данных из текстового файла нужно выполнить:
1. Описать переменную типа ifstream.
2. Открыть файл для чтения с помощью функции open.
3. Считать информацию из файла с помощью cin при считывании каждой порции данных необходимо проверять, что чтение возможно.
4. Закрыть файл.
Порядок работы с потоками
Описание потоковой переменной
Для того чтобы начать работать с текстовым файлом, необходимо описать переменную типа ofstream.Например, с помощью оператора
ofstream F;будет создана переменная F для записи информации в файл.
Открытие файла
В общем случае оператор открытия файла будет иметь вид:
F.open("file", mode);где F– переменная, описанная в нашем случае как ofstream;
file– полное имя файла на диске;
mode– режим работы с открываемым файлом.
Существуют следующие режимы для открытия файла (см. табл.6).
Таблица 6. Режимы работы с потоком при его открытии
Режимы работы с файлом при открытии | |
Режим | Описание |
ios::in | открыть файл в режиме чтения данных, этот режим является режимом по умолчанию для потоков ifstream |
ios::out | открыть файл в режиме записи данных, этот режим является режимом по умолчанию для потоков ofstream |
ios::app | открыть файл в режиме записи данных в конец файла |
ios::ate | передвинуться в конец уже открытого файла |
ios::trunc | очистить файл, это же происходит в режиме ios::out |
ios::nocreate | не выполнять операцию открытия файла, если он не существует |
ios::noreplace | не открывать существующий файл |
ios::binary | открыть двоичный файл |
Параметр mode может отсутствовать, в этом случае файл открывается в режиме по умолчанию для данного потока:
ios::in– для потоков ifstream,
ios::out– для потоков ofstream.
После удачного открытия файла (в любом режиме) в переменной F будет храниться 1 (true), в противном случае 0 (false). Это позволит проверять корректность операции открытия файла.
Если открытие файла завершилось неудачей, объект, соответствующий потоку, будет возвращать значение 0:
if (!ofs){ cout << "Файл не открыт\n"; }Проверить успешность открытия файла можно также с помощью функции is_open(). Функция возвращает 1, если поток удалось связать с открытым файлом. Например,
if (!ofs.is_open()) cout << "Файл не открыт\n";Открыть файл в режиме записи можно одним из следующих способов:
Первый способ
ofstream F;F.open("abc.txt", ios::out);
Второй способ, режим ios::out является режимом по умолчанию для потока ofstream
ofstream F;F.open("abc.txt");Третий способ объединяет описание переменной типа поток и открытие файла в одном операторе.
ofstream F("abc.txt", ios::out);После открытия файла в режиме записи, будет создан пустой файл, в который можно будет записывать информацию. Если необходимо открыть существующий файл (при этом сохранить его содержимое), то в качестве режима следует использовать значение ios::app.
Обработка
После открытия файла в режиме записи, в него можно писать точно так же, как и на экран, только вместо стандартного устройства вывода cout необходимо указать имя открытого для записи файла.
Например, для записи в поток F переменной a, оператор вывода будет иметь вид:
F << a;Для последовательного вывода в поток G переменных b, c и d оператор вывода станет таким:
G << b << c << d;Чтение из файла выполняется корректно до достижения конца файла. Для проверки, достигнут ли конец файла, можно использовать функцию
ios::eof(),которая имеет прототип int eof();.
Данная функция возвращает 0, если конец файла не достигнут, и значение 1 при достижении конца файла.
Закрыттие файла
Открытые на диске файлы после окончания работы с ними рекомендуется закрыть. Оператор закрытия файла будет иметь вид:
F.close;где F– переменная для записи информации в файл.
Пример 1. Работа с файлом в потоковом режиме.
#include "stdafx.h"#include <iostream>using namespace std;#include <fstream>int _tmain(int argc, _TCHAR* argv[]){ int n = 50; char str[20]; // Открываем файл для вывода ofstream ofs("Test.txt"); // Проверка корректности открытия файла if (!ofs) cout << "Файл не открыт.\n"; else { ofs << "Hello!\n" << n; // Закрываем файл ofs.close(); } // Открываем тот же файл для ввода ifstream file("Test.txt"); // Проверка корректности открытия файла if (!file) cout << "Файл не открыт.\n"; else { file >> str >> n; cout << str << "\n" << n; // Закрываем файл file.close(); } system("pause"); return 0;}
При использовании библиотеки классов С++ операции открытия, создания и закрытия, выполняются при создании объектов выходного (входного ) файлового потока.
Пример 2.
#include <iostream.h>
#include <fstream.h> // ofstream
#include <stdlib.h> // содержит функцию exit
int main()
{ char sim;
// создаётся файл, старый стирается
ofstream myfile("d:\oop\myfile.txt",ios::out);
if(!myfile)
{
cerr<<" ошибка открытия myfile.txt"<<endl;
exit(1);
}
for(int i=1;i<10;i++){
cout<<"введите символ"<<endl;
cin>>sim;
myfile.put(sim); }
myfile<<endl;
return 0;
}
Пример 3.
#include <iostream.h>
//#include <fstream.h> // ofstream
#include <fstream.h>
#include <stdlib.h> // содержит функцию exit
int main()
{ char sim;
ifstream myfile("d:\oop\myfile.txt",ios::in);
if(!myfile)
{
cerr<<" ошибка открытия myfile.txt"<<endl;
exit(1);
}
int nsim=0, kolstr=0;
while (myfile.get(sim)){
if (sim==char("\n"))
kolstr++;
else
nsim++;
cout.put(sim); }
cout<<endl<<endl<<"kolstr="<<kolstr<<" "<<"nsim="<<nsim<<endl;
cin>>nsim;
return 0;
}
Пример 4.
#include <iostream.h>
#include <fstream.h> // ofstream
#include <stdlib.h> // содержит функцию exit
int main()
{ char sim;
ofstream myfile("d:\oop\myfile.txt",ios::in); // открывается
// файл для чтения
if(!myfile)
{
cerr<<" ошибка открытия myfile.txt"<<endl;
exit(1);
}
for(int i=1;i<10;i++){........................}
cout<<"введите символ"<<endl;
cin>>sim;
myfile.put(sim); }
myfile<<endl;
return 0;
}
Пример 5.
#include <iostream.h>
#include <fstream.h> // ofstream
#include <stdlib.h> // содержит функцию exit
#define size 40
int main()
{ char sim,*filename;
cout<<"введите имя файла и путь d:\oop\myfile.txt \n";
filename=new char(size);
cin.getline(filename,size);
ofstream myfile(filename,ios::out);
if(!myfile)
{
cerr<<" ошибка открытия myfile.txt"<<endl;
cin>>sim;
exit(1);
}
for(int i=1;i<10;i++){. . . . . . . . . . }
cout<<"введите символ"<<endl;
cin>>sim;
myfile.put(sim); }
myfile<<endl;
delete[]filename;
return 0;
}
Задачи редактирования файла
Более сложными являются задачи редактирования файлов на программном уровне. К типовым операциям над файлами можно отнести:
1. Исключение из файла фрагмента текста.
2. Вставка в файл фрагмента текста.
3. Замена фрагмента текста файла на другой фрагмент.
4. Упорядочивание элементов файла по определенному ключу.
Операцию замены можно выполнить с помощью первых двух операций: исключить один фрагмент текста и вставить другой. Но поскольку эта операция широко распространена, она часто рассматривается как отдельная операция.
Собственно редактирование можно было бы выполнять аналогично, но в системе предусмотрены меры, которые способствуют сохранению информации в аварийных ситуациях, то есть система всегда готова закрыть файл, выполнив для этого минимально необходимое количество операций. Даже при зависании машины файл, в целом, не должен быть испорчен. Системная защита реализована следующим образом. В конце текстовых файлов должен быть записан управляющий символ конца файла, который в действительности помещается на последнюю позицию при выполнении любой операции записи в файл. Так как работа с файлом осуществляется через буфер, то символ конца файла записывается в этот буфер после каждой операции записи, а не при физическом сохранении содержимого буфера на диск.
По этой причине невозможно непосредственно реализовать такую операцию, как запись в середину файла вместо одного символа другого. Из-за указанной особенности реализации операций записи в файл непосредственно прямым способом эту задачу не решить, поскольку после записи символа в требуемом месте после него будет записан символ конца файла, что приведет к тому, что весь остаток файла от места перезаписи до конца файла больше считываться не будет.
Таким образом, для выполнения операций исключения, вставки и замены фрагментов текста в файлах можно использовать только два способа (а также их комбинацию).
1. Рабочую память выделять в памяти программы и считывать в нее файл для обработки (с целью экономного расходования памяти желательно пользоваться массивами указателей).
2. В качестве рабочей памяти использовать вспомогательный файл.
Первый способ не вызывает трудностей при небольших размерах файла. Если же файл целиком нельзя разместить в памяти программы, то алгоритм усложняется, поскольку файл приходится считывать по частям и осуществлять перенос информации из одной части в другую.
При втором способе размер файла не играет существенной роли, но ограничение по использованию определяется наличием свободного места на диске. Кроме того, после выполнения обработки необходимо исключать вспомогательный файл. Поэтому этот способ оправдан, когда в результате операции редактирования формируется новый файл, который будет сохранять все результаты изменений. Ниже приведены примеры программ вставки символа в файл, иллюстрирующие оба из указанных способов. В первом примере для вставки символа используется память программы. Файл считывается в символьный массив (буфер), символ вставляется в этот массив (для этого предварительно часть массива от точки вставки до конца копируется со сдвигом на один символ вправо, освобождая место для символа), после этого массив переписывается обратно в исходный файл.
Пример 1. Замещение символа в файле на введенный символ. В качестве дополнительной области используется память программы.
#include "stdafx.h"#include <iostream>using namespace std;#include <conio.h> #include <ctype.h> #include <io.h> #define SIZE 40 int _tmain(int argc, _TCHAR* argv[]){ char *buffer,str[SIZE],*pt,*qt,c; long n; int i,k,len; FILE *f; f = fopen("copy.txt","r+"); //Режим "r" без '+' создает защиту от записи printf("\n Введите символ и позицию вставки\n"); c = getchar(); scanf("%d",&k); n = filelength (fileno(f)); //число символов в файле len = (int)n-1 ; //поправка на символ конца файла buffer = (char*)malloc(len); fread(buffer, len,1,f); fseek(f,0L,SEEK_SET); /*После команды fread текущая позиция в файле изменилась, поэтому возврат ее в исходное положение*/ //Установить указатель на текущий символ на конец буфера pt = buffer; while(*pt++); qt = pt + 1; // Второй указатель на 1 позицию вправо for (i = 0; i < len - k + 1; i++) // Копирование до точки вставки *qt-- = *pt--; buffer[k - 1] = c; // Вставка символа, поскольку место свободно fwrite(buffer, len,1,f); fseek(f,0L,SEEK_SET); // После команды fwrite позиция в файле изменилась fscanf(f,"%s",str); printf("\n Cтрока после вставки равна %s",str); system("pause"); return 0;}Пример 2. Вставка фрагмента в файл. В качестве дополнительной области используется другой файл.
#include "stdafx.h"#include <iostream>using namespace std;#include <io.h> #include <stdlib.h> #include <conio.h> #include <ctype.h> #define SIZE 2000 int _tmain(int argc, _TCHAR* argv[]){ FILE *f1, *f2; char str[SIZE],c; int i,n; f1 = fopen("copy1.txt","w"); f2 = fopen("copy.txt","r"); printf("\nВведите позицию и фрагмент для вставки \n"); scanf("%d%s",&n,str); if (n > 0 && n < (int)filelength (fileno(f2)) ) { //Обработка i = 1; // Переписать исходный файл в конечный до точки вставки while(i < n && feof(f2) == 0) { c = getc(f2); putc(c,f1); i++; } fputs(str,f1); // Переписать вставляемый фрагмент // Переписать исходный файл в конечный до конца while(feof(f2) == 0) { c = getc(f2); if (c!=-1) putc(c,f1); } } // Конец оператора if else printf("\nОшибка ввода параметра смещения (%d)",n); system("pause"); return 0;}Чтобы вставить строку в середину файла, используя вспомогательный файл, необходимо проделать следующий алгоритм.
1. Открыть входной файл в режиме чтения и вспомогательный файл в режиме записи (этот файл будет создан автоматически).
2. Прочесть из входного файла текст до места вставки.
3. Записать прочитанный фрагмент во вспомогательный файл.
4. Записать во вспомогательный файл вставляемый фрагмент.
5. Прочесть из входного файла остаточный фрагмент и записать его во вспомогательный файл.
6. Закрыть оба файла.
Пример 4. Для редактирования файла используется временный файл.
#include "stdafx.h"#include <iostream>using namespace std;#define BSIZE 200 int _tmain(int argc, _TCHAR* argv[]){ char arg[20]="task.txt"; char buf[BSIZE]; int ch; FILE *in, *tmp; in=fopen(arg,"rb"); if(in==NULL) printf("Не открывается файл %s\n", arg); else { tmp = tmpfile(); buf[0]='\t'; while(fgets(buf+1,BSIZE-1,in) != NULL) fputs(buf,tmp); fclose(in); in = fopen(arg,"wb"); fseek(tmp,0l,SEEK_SET); while ((ch=fgetc(tmp)) != EOF) fputc(ch,in); fclose(in); fclose(tmp); } system("pause"); return 0;}Задание.
Для выданного преподавателем варианта задачи написать и отладить программу на языке С++, которая содержит форматированную обработку файла .
Для всех приведенных ниже заданий, предусматривающих обработку файла с заданной структурой, написать программу для его создания, записи, чтения и обработки данных.
5. Требования к отчету по лабораторной работе:
Отчет должен содержать:
1) распечатку или текст программы с комментариями;
2) результаты работы программы.
6. Варианты заданий:
1. В файле хранится информация о зарегистрированных пересдачах задолженностей студен тов: ФИО, предмет, количество пересдач. Сформировать файл по заданному признаку (например количеству пересдач) и выдать его на экран дисплея.
2. Создать типизированный файл, в котором хранится информация о предметах, изъятых на таможне за отчётный период: дата изъятия, наименование предмета, количество единиц, стоимость. Определить количество единиц заданного типа предмета.
3. В файле хранится информация о финансовой деятельности предприятий за истекший год: наименование предприятия, месяц, доход предприятия за этот месяц, начисления на зарплату, прибыль предприятия. Сформировать файл, содержащий список предприятий, у которых положительное отклонение от среднемесячного дохода превышает 50%.
4. Сформировать файл, в котором хранятся результаты сессии группы. Написать программу корректировки оценок, у студентов, пересдавших сессию.
5. В файле хранится информация о пропусках занятий студентами: ФИО, предмет, пол, время занятия. Поступила очередная информация о пропусках. Написать программу и алгоритм решения следующей задачи: проверить наличие в исходном файле повторных пропусков занятий.
6. В файле хранится информация о владельцах гаражного кооператива: ФИО, марка автомобиля, номер машины. Написать программу внесения в файл информации о новых членах кооператива, если данные о них отсутствуют в исходном файле.
7. В файле хранится информация по задолженностям студентов: ФИО, группа, курс, предмет. Написать программу удаления из файла информации о студентах аннулировавших задолженности.
8. В файле хранится информация о студентах получивших разрешение на пересдачу экзамена: ФИО, группа, предмет, курс. Сформировать файл, содержащий информацию о студентах получивших разрешение на пересдачу после заданной даты.
9. В типизированном файле хранится информация о владельцах автотранспорта: ФИО, марка автомобиля, номер машины. Написать программу формирования файла, содержащего информацию о владельцах автомобилей, в номере которых встречаются заданные цифры.
10. В типизированном файле хранится информация о деятельности некоторых подразделений: наименование подразделения, количество сотрудников, прибыль, полученная за текущий квартал. Определить лучшее подразделение с учётом числа сотрудников.
11. В типизированном файле хранится информация о движении поездов по станции «Старый Оскол»: номер поезда, маршрут движения, время прибытия, время отправления. Необходимо распечатать все поезда, которые отправляются в заданном диапазоне времени.
12. В файле хранится информация о финансовой деятельности предприятий за истекший год: наименование предприятия, месяц, доход предприятия за этот месяц, начисления на зарплату, прибыль предприятия. Отсортировать этот файл в порядке убывания дохода и вывести на экран информацию о трёх наиболее доходных предприятиях.
13. В типизированном файле хранится информация о движении поездов по станции «Старый Оскол»: номер поезда, маршрут движения, время прибытия, время отправления. На его базе сформировать новый файл, содержащий информацию о поездах, движущихся в заданный конечный пункт.
14. Сформировать типизированный файл, в котором хранится информация об ассортименте продовольственных товаров в коммерческих магазинах: код (наименование) магазина, наименование товара, количество этого товара, цена за килограмм. Подобрать магазин или магазины для оптовой закупки заданного товара в заданном количестве так, чтобы минимизировать затраты на его приобретение.
15. Создать типизированный файл, в котором хранится информация о предметах, изъятых на таможне за отчётный период: дата изъятия, наименование предмета, код группы, к которой относится предмет (оружие, продовольственные товары, т.д.), количество единиц, стоимость единицы. Определить группу предметов, по которой чаще всего происходило изъятие.
16. Сформировать типизированный файл, в котором хранится информация о сотрудниках подразделения: ФИО, место рождения, год рождения. На его основе сформировать файл сотрудников, родившихся в данном городе и распечатать его.
17. Создать типизированный файл, в котором хранится информация об абонентах АТС: ФИО, место жительства, номер телефона. Необходимо упорядочить список абонентов в файле по алфавиту.
18. В типизированном файле хранится информация о лицензиях, выданных на приобретение газового оружия: ФИО, дата выдачи лицензии, тип оружия, его стоимость. Необходимо вывести на экран все записи с заданной стоимостью.
19. Сформировать типизированный файл, в котором хранится информация об академических задолженностях по факультетам за три года: год, факультет, количество задолженностей. Написать программу определения факультета с максимальным и минимальным количеством задолженностей.
20. Сформировать типизированный файл, в котором хранится информация об ассортименте продовольственных товаров в коммерческих магазинах: код (наименование) магазина, наименование товара, количество этого товара. Подобрать магазин, в котором хранится заданный товар в нужном количестве.
21. Создать типизированный файл, в котором хранится информация об абонентах АТС: ФИО, место жительства, номер телефона. Необходимо написать программу, которая по фамилии выдаёт номер абонента.
22. Сформировать типизированный файл, в котором хранится информация о заболеваниях сотрудников: ФИО, год рождения, заболевание, продолжительность болезни. На его основе сформировать файл сотрудников, которые перенесли одно и тоже заболевание.
23. Создать типизированный файл, в котором хранится информация об абонентах библиотеки: ФИО, кафедра, количество книг взятых абонентом. Необходимо написать программу, определения кафедры, за которой числится максимальное количество книг.
24. Сформировать типизированный файл, в котором хранятся результаты сессии группы: факультет, группа, семестр, ФИО студента, средняя оценка. Написать программу начисления стипендии по результатам сессии (стипендия = средняя оценка х 50 руб).
25. В файле хранится информация об изобретательской деятельности кафедр за три года: наименование кафедр, количество заявок, количество положительных решений. Написать программу определения кафедры получившей максимальное количество положительных решений.
26. В файле хранится информация о студентах института: факультет, группа, ФИО, домашний адрес, месяц и год рождения. Написать программу определения месяца, в котором родилось максимальное количество студентов в вашей группе.
27. В файле хранится информация о результатах сессии: фамилия и инициалы студента, номер группы, успеваемость (массив из пяти элементов). Сформировать список студентов, имеющих хотя бы одну «двойку».
28. В файле хранится информация о результатах сессии: фамилия и инициалы студента, номер группы, успеваемость (массив из пяти элементов). Сформировать список студентов, имеющих только оценки «4» и «5».
29. В файле хранится информация о результатах сессии: фамилия и инициалы студента, номер группы, успеваемость (массив из пяти элементов). Сформировать список студентов, имеющих средний балл, больший 4.0.
30. В файле хранится информация о сотрудниках предприятия: подразделение, ФИО сотрудника, месяц, заработная плата за этот месяц. Рассчитать совокупный фонд заработной платы сотрудников введенного подразделения за 1-ый квартал отчетного года.
7. Контрольные вопросы.
1) Что включает в себя понятие файла? Как оно связано со стандартными потоками ввода/вывода?
2) Перечислите стандартные потоки ввода/вывода, открываемые пи запуске программы.
3) Как связаны между собой понятия логического и физического файлов?
4) Как работает функция fopen()?
5) Что такое режим доступа? Перечислить возможные режимы доступа при работе с файлами.
6) Почему при работе с файлом не рекомендуется использовать оператор цикла с пост-условием?
7) Каков механизм действий, связанных с закрытием файлов? Почему необходимо закрывать файлы по окончании работы с ними?
8) Как открыть бинарный файл?
9) Какие функции осуществляют чтение и запись при работе с бинарными файлами?
10) Что такое последовательный и произвольный доступ к компонентам файла?
11) В чем заключается опасность использования функции fseek()?
12) Какие способы обработки файлов Вы знаете?
13) Чем отличается потоковый режим обработки файлов от форматированного?
14) Что такое «буферизация»? Когда она применяется?
15) Что такое «флэширование»? какие способы флэширования Вы знаете?
Список рекомендуемой литературы.
Основная:
1. Канцедал С. А. Алгоритмизация и программирование [Текст] : учебное пособие / С.А. Канцедал. - М. : ИНФРА-М, 2008 ; М. : Форум, 2008. - 352 с. : ил. - ISBN 978-5-8199-0355-1 : 157.41
2. Колдаев В. Д. Основы алгоритмизации и программирования [Text] : учебное пособие / В.Д.Колдаев ; Под. ред. проф. Л.Г.Гагариной. - М. : ИД ФОРУМ : ИНФРА-М, 2009. - 416 с. : ил. - ISBN 978-5-16-002690-9 : 116.05
3. Павловская Т. А. С/С++ Программирование на языке высокого уровня [Text] / Т.А.Павловская. - СПб. : Питер, 2009. - 461 с. : ил. - ISBN 978-5-94723-568-5 : 176.99
5. Павловская, Т. А. С/С++ Структурное программирование [Text] : практикум / Т.А.Павловская, Ю.А.Щупак. - СПб. : Питер, 2007
6. Пантелеев А. В. Методы оптимизации в примерах и задачах [Text] : учебное пособие / А.В. Пантелеев, Т.А. Летова. - 3-е изд., стер. - М. : Высшая школа, 2008. - 544 с. : ил. - ISBN 978-5-06-004137-8 : 633.93
7. Культин, Н. С/С++ в задачах и примерах [Text] / Н. Культин. - 2-е изд., перераб. и доп. - СПб. : БХВ - Петербург, 2011. - 368 с. : ил. эл. опт. диск (CD-ROM). - ISBN 978-5-94157-406-3 : 233.26
8. Козырь О.Ф. Программирование и основы алгоритмизации. Методические указания к выполнению лабораторных работ.(очная и заочная формы обучения) - Старый Оскол: Изд-во СОФ МИСиС, 2012.
9. Бритик В.И., Козырь О.Ф. Программирование и основы алгоритмизации. Основы программирования. Основы программирования и алгоритмизации. Методические указания к выполнению домашних и курсовых работ (очная, очно-заочная и заочная формы обучения) - Старый Оскол: Изд-во СОФ МИСиС, 2008 – 60 с.
10. Козырь О.Ф. Программирование и основы алгоритмизации. Методическое пособие (очная и заочная формы обучения) - Старый Оскол: Изд-во СОФ МИСиС, 2008.
Дополнительная:
1. Агальцов В. П. Математические методы в программировании [Текст] : учебник / В.П.Агальцов. - 2-е изд, перераб. и доп. - М. : ИД "ФОРУМ", 2010. - 240 с. : ил. - ISBN978-5-8199-0410-7 : 175.01
2. Чиртик, А. А. Программирование на C++. Трюки и эффекты [Text] / А.А.Чиртик. - CПб : Питер, 2010. - 352 с. : ил + 1 эл. опт. диск (CD-ROM). - ISBN 978-5-49807-102-2 : 319.99
3. Крячков А. В. Программирование на С и С++. Практикум [Text] : учебное пособие для вузов / А.В. Крячков, И.В. Сухинина, В.К. Томшин ; под ред. В.К. Томшина. - 2-е изд., испр. - М. : Горячая линия-Телеком, 2000. - 344 с. : ил. - ISBN 5-93517-014-0 : 58.50 , 69.30