Цель лекции: изучить алгоритмы и приемы чтения-записи, перестановок, поиска и сортировок элементов файла и научиться решать задачи с использованием алгоритмов чтения-записи, перестановок, поиска и сортировок элементов файлов на языке C++.
В программах зачастую необходимо обрабатывать данные больших объемов, причем сами данные и/или результаты обработки требуется сохранять относительно долгое время. Проблему выделения дополнительных ресурсов для хранения обрабатываемых данных можно решить за счет динамической памяти, однако, ее ресурс ограничен. Организовать длительное хранение информации только средствами оперативной памяти практически невозможно ввиду энергозависимости устройства. Поэтому работу с объемными данными и организацию долговременного хранения данных в языках программирования осуществляют с помощью файлов, расположенных на внешних носителях.
stdio.h. Эти функции описаны в стандарте
В C++ часто используются библиотеки классов для ввода-вывода, в том числе и для обмена данными с использованием файлов. При этом функции из
С точки зрения концепции языка С++ файлы представляют собой последовательности байтов (в С и С++ нет понятия <структурированный> или <'\n' – шестнадцатеричный код 0A ), '\r' – шестнадцатеричный код 0D ), символ конца файла (шестнадцатеричный код 1A ) и другие. Операционные системы MS '\r\n' как один символ.
Это обеспечивает читабельность содержащейся информации, так как придает определенную структуру файлу в виде строк. В системе Unix строки разделяются одним символом, который интерпретируется как new line. Таким образом, внутреннее представление текста всегда соответствует системе Unix, а внешнее – реально используемой операционной системе.
Поток в С++ можно рассматривать как отдельный класс (тип данных), который представляют объекты со схожей организацией последовательной передачи данных от источника к приемнику. Потоки ввода/вывода, такие как cin и cout, являются примерами объектов класса <поток>. Список функций для работы с файловыми потоками хранится в fstream.h.
В С++ предусмотрены различные режимы обмена данными в файловых потоках. Разница в организации обмена информацией заключается в наличии/отсутствии
Пример 1. Программа печатает собственный код на экран и другой файл. Файл с программным кодом сохранен как Task_1..
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <fstream>
int _tmain(int argc, _TCHAR* argv[]){
char character;
ifstream in_stream;
ofstream out_stream;
in_stream.open("Task_1.cpp");
out_stream.open("Copy.txt");
in_stream.get(character);
while (!in_stream.eof()) {
cout << character;
out_stream.put(character);
in_stream.get(character);
}
out_stream.close();
in_stream.close();
system("pause");
return 0;
}
Последовательное
Если рассматривать файл как последовательность байтов, то элементом файла будет выступать последовательность нулей и единиц размером в один байт.
Функция fseek перемещает указатель, соответствующий потоку , на новое место расположения, отстоящее от начала на указанное число байтов. Следующая операция в потоке выполняется над новым месторасположением. Если поток открыт для обновления, то следующей операцией будет либо чтение, либо запись. Функция fseek используется для перемещения указателя в любое место файла. Указатель может быть также размещен за концом файла. Однако попытка расположить указатель до начала файла приведет к ошибке. Для потоков, открытых в режиме fseek является ограниченным, т.к. комбинации
Более сложными являются задачи редактирования файлов на программном уровне. К типовым операциям над файлами можно отнести:
Операцию замены можно выполнить с помощью первых двух операций: исключить один фрагмент текста и вставить другой. Но поскольку эта операция широко распространена, она часто рассматривается как отдельная операция.
Собственно редактирование можно было бы выполнять аналогично, но в системе предусмотрены меры, которые способствуют сохранению информации в аварийных ситуациях, то есть система всегда готова закрыть файл, выполнив для этого минимально необходимое количество операций. Даже при зависании машины файл, в целом, не должен быть испорчен. Системная защита реализована следующим образом. В конце текстовых файлов должен быть записан
По этой причине невозможно непосредственно реализовать такую операцию, как запись в середину файла вместо одного символа другого. Из-за указанной особенности реализации операций записи в файл непосредственно прямым способом эту задачу не решить, поскольку после записи символа в требуемом месте после него будет записан символ конца файла, что приведет к тому, что весь остаток файла от места перезаписи до конца файла больше считываться не будет.
Таким образом, для выполнения операций исключения, вставки и замены фрагментов текста в файлах можно использовать только два способа (а также их комбинацию).
Первый способ не вызывает трудностей при небольших размерах файла. Если же файл целиком нельзя разместить в памяти программы, то алгоритм усложняется, поскольку файл приходится считывать по частям и осуществлять перенос информации из одной части в другую.
При втором способе размер файла не играет существенной роли, но ограничение по использованию определяется наличием свободного места на диске. Кроме того, после выполнения обработки необходимо исключать вспомогательный файл. Поэтому этот способ оправдан, когда в результате операции редактирования формируется новый файл, который будет сохранять все результаты изменений. Ниже приведены примеры программ вставки символа в файл, иллюстрирующие оба из указанных способов. В первом примере для вставки символа используется
Пример 2. Замещение символа в файле на введенный символ. В качестве дополнительной области используется
#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;
}
Пример 3. Вставка фрагмента в файл. В качестве дополнительной области используется другой файл.
#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;
}
Чтобы вставить строку в середину файла, используя вспомогательный файл, необходимо проделать следующий алгоритм.
Пример 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;
}
Класс поток – это тип данных, представленный объектами со схожей организацией последовательной передачи данных от источника к приемнику.
Рабочая память – это дополнительная область памяти, предназначенная для временного хранения изменений при редактировании файла.
Редактирование файла на программном уровне – это изменения, производимые с элементами файла в процессе работы программ.
Стандарт ANSI –
Элемент файла – это последовательность нулей и единиц размером в один байт.
Цель работы: изучить алгоритмы и приемы чтения-записи, перестановок, поиска и сортировок элементов файла и научиться решать задачи с использованием алгоритмов чтения-записи, перестановок, поиска и сортировок элементов файлов на языке C++.
При выполнении лабораторной работы для каждого задания требуется написать программу на языке С++, которая получает на входе строковые величины, являющиеся корректными именами входных и выходных файлов (при этом в программе следует предусмотреть проверку существования и корректности открытия используемых файлов). Ввод данных осуществляется из входных файлов с учетом требований к входным данным, содержащихся в постановке задачи. Ограничениями на входные данные является максимальный размер строковых данных и допустимый диапазон числовых типов в языке С++. При некорректном открытии файла программа должна завершить работу с выдачей на экран соответствующего сообщения. Считанные из файла данные обрабатываются в соответствии с условием задачи с помощью алгоритмов перестановок, поиска или сортировок, после чего осуществляется вывод в выходной файл.
Теоретические сведения.
Ознакомьтесь с материалом лекции 22.
Задания к лабораторной работе.
Выполните приведенные ниже задания.
Указания к выполнению работы.
Каждое задание необходимо решить в соответствии с изученными методами и алгоритмами обработки файлов в языке С++. В программном коде к каждой задаче следует выполнять
Следует реализовать каждое задание в соответствии с приведенными этапами:
Требования к отчету.
Отчет по лабораторной работе должен соответствовать следующей структуре.
Контрольные вопросы
fseek является ограниченным?Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.