Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Организация файла последовательного доступа




В С++ файлу не предписывается никакая структура. Для последовательного поиска данных в файле программа обычно начинает считывать данные с начала файла до тех пор, пока не будут считаны требуемые данные. При поиске новых данных этот процесс вновь повторяется.

Данные, содержащиеся в файле последовательного доступа, не могут быть модифицированы без риска разрушения других данных в этом файле. Например, если в файле содержится информация

Коля 12 Александр 52

то при модификации имени Коля на имя Николай может получиться следующее:

НиколайАлександр 52

Аналогично в последовательности целых чисел 12 –1 132 32554 7 для хранения каждого из них отводится sizeof(int) байт. А при форматированном выводе их в файл они занимают различное число байт. Следовательно, такая модель ввода−вывода неприменима для модификации информации на месте. Эта проблема может быть решена перезаписью (с одновременной модификацией) в новый файл информации из старого. Это сопряжено с проблемой обработки всей информации при модификации только одной записи.

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

#include <fstream>

using namespace std;

#include "stdlib.h"

#include "math.h"

void error(char *s1,char *s2="") // вывод сообщения об ошибке

{ cerr<<s1<<" "<<s2<<endl; // при открытии потока для файла

exit(1);

}

int main(int argc,char **argv)

{ char *buf=new char[20];

int i;

ifstream f1; // входной поток

ofstream f2,f3; // выходные потоки

f1.open(argv[1],ios::in); // открытие исходного файла

if(!f1) // проверка состояния потока

error("ошибка открытия файла",argv[1]);

f2.open(argv[2],ios::out); // открытие 1 выходного файла

if(!f2) error("ошибка открытия файла",argv[2]);

f3.open(argv[3],ios::out); // открытие 2 выходного файла

if(!f3) error("ошибка открытия файла",argv[3]);

f1.seekg(0); // установить текущий указатель в начало потока

while(f1.getline(buf,20,' ')) // считывание в буфер до 20 символов

{ if(int n=f1.gcount()) // число реально считанных символов

buf[n-1]='\0';

// проверка на только цифровую строку

for(i=0;*(buf+i)&&(*(buf+i)>='0' && *(buf+i)<='9');i++);

if(!*(buf+i)) f2 <<::atoi(buf)<<' '; // преобразование в число и запись

// в файл f2

else f3<<buf<<' '; // просто выгрузка буфера в файл f3

}

delete [] buf;

f1.close(); // закрытие файлов

f2.close();

f3.close();

}

В программе для ввода имен файлов использована командная строка, первый параметр – имя файла источника (входного), а два других – имена файлов приемников (выходных). Для работы с файлами использованы функции – open, close, seekg, getline и gcount. Более подробное описание функций приведено ниже.

Ниже приведена программа, выполняющая ввод символов в файл с их одновременным упорядочиванием (при вводе) по алфавиту. Использование функций seekg, tellg позволяет позиционировать текущую позицию в файле, то есть осуществлять прямой доступ в файл. Обмен информацией с файлом осуществляется посредством функций get и put.

#include <fstream>

using namespace std;

#include "stdlib.h"

void error(char *s1,char *s2="")

{ cerr<<s1<<" "<<s2<<endl;

exit(1);

}

int main()

{ char c,cc;

int n;

fstream f; // выходной поток

streampos p,pp;

f.open("aaaa",ios::in|ios::out); // открытие выходного файла

if(!f) error("ошибка открытия файла","aaaa");

f.seekp(0); // установить текущий указатель в начало потока

while(1)

{ cin>>c; // ввод очередного символа

if (c=='q' || f.bad()) break;

f.seekg(0,ios::beg); // перемещение указателя в начало файла

while(1)

{ if(((cc=f.get())>=c) || (f.eof()))

{ if(f.eof()) // в файле нет символа, большего с

{ f.clear(0);

p=f.tellg(); // позиция ЕOF в файле

}

else

{ p=f.tellg()-1; // позиция первого символа большего с

f.seekg(-1,ios::end); // указатель на последний элемент в файле

pp=f.tellg(); // позиция последнего элемента в файле

while(p<=pp) // сдвиг в файле на один символ

{ cc=f.get();

f.put(cc);

if (--pp>0) f.seekg(pp); // проверка на невыход за начало файла

}

}

f.seekp(p); // позиционирование указателя в позицию p

f.put(c); // запись символа с в файл

break;

}

}

}

f.close();

return 0;

}

Каждому объекту класса istream соответствует указатель get (указывающий на очередной вводимый из потока байт) и указатель put (соответственно на позицию для вывода байта в поток). Классы istream и ostream содержат по две перегруженные компоненты-функции для перемещения указателя в требуемую позицию в потоке (связанном с ним файле). Такими функциями являются seekg (переместить указатель для извлечения из потока) и seekp (переместить указатель для помещения в поток).

istream& seekg(streampos pos);

istream& seekg(streamoff off, ios::seek_dir dir);

Сказанное выше справедливо и для функций seekp. Первая функция перемещает указатель в позицию рos относительно начала потока. Вторая перемещает соответствующий указатель на off (целое число) байт в трех возможных направлениях: ios::beg (от начала потока), ios::cur (от текущей позиции) и ios::end (от конца потока). Кроме рассмотренных функций в этих классах имеются еще функции tellg и tellp, возвращающие текущее положение указателей get и put соответственно





Поделиться с друзьями:


Дата добавления: 2015-09-20; Мы поможем в написании ваших работ!; просмотров: 1013 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Сложнее всего начать действовать, все остальное зависит только от упорства. © Амелия Эрхарт
==> читать все изречения...

2221 - | 2091 -


© 2015-2025 lektsii.org - Контакты - Последнее добавление

Ген: 0.011 с.