
- •Учебное пособие
- •Введение
- •Объектно-ориентированный подход
- •Объектно-ориентированное программирование Абстрактные типы данных
- •Базовые принципы объектно-ориентированного программирования
- •Простейший ввод и вывод
- •Объект cout
- •Манипуляторы hex и oct
- •Другие манипуляторы
- •Объект cin
- •Операторы для динамического выделения и освобождения памяти (new и delete)
- •Базовые конструкции объектно-ориентированных программ Объекты
- •Понятие класса
- •Конструктор копирования
- •Конструктор explicit
- •Указатели на компоненты класса
- •Встроенные функции (спецификатор inline)
- •Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •Вложенные классы
- •Static-члены (данные) класса
- •Указатель this
- •Компоненты-функции static и const
- •Proxi-классы
- •Параметры ссылки
- •Независимые ссылки
- •Практические приемы ограничения числа объектов класса
- •Наследование (производные классы)
- •Конструкторы и деструкторы при наследовании
- •Виртуальные функции
- •Абстрактные классы
- •Виртуальные деструкторы
- •Множественное наследование
- •Виртуальное наследование
- •Перегрузка функций
- •Перегрузка операторов
- •Перегрузка бинарного оператора
- •Перегрузка унарного оператора
- •Дружественная функция operator
- •Перегрузка оператора []
- •Перегрузка оператора ()
- •Перегрузка операторов new и delete
- •Преобразование типа
- •Явные преобразования типов
- •Преобразования типов, определенных в программе
- •Шаблоны Параметризированные классы
- •Передача в шаблон класса дополнительных параметров
- •Шаблоны функций
- •Совместное использование шаблонов и наследования
- •Шаблоны класса и friend
- •Некоторые примеры использования шаблона класса Реализация smart-указателя
- •Классы поддерживающие транзакции
- •Задание значений параметров класса по умолчанию
- •Пространства имен
- •Ключевое слово using как директива
- •Ключевое слово using как объявление
- •Псевдоним пространства имен
- •Организация ввода-вывода
- •Состояние потока
- •Строковые потоки
- •Организация работы с файлами
- •Организация файла последовательного доступа
- •Создание файла произвольного доступа
- •Основные функции классов ios, istream, ostream
- •Основы обработки исключительных ситуаций
- •Перенаправление исключительных ситуаций
- •Исключительная ситуация, генерируемая оператором new
- •Генерация исключений в конструкторах
- •Задание собственной функции завершения
- •Спецификации исключительных ситуаций
- •Задание собственного неожиданного обработчика
- •Иерархия исключений стандартной библиотеки
- •Стандартная библиотека шаблонов (stl) Общее понятие о контейнере
- •Общее понятие об итераторе
- •Категории итераторов
- •Основные итераторы
- •Вспомогательные итераторы
- •Операции с итераторами
- •Контейнерные классы Контейнеры последовательностей
- •Контейнер последовательностей vector
- •Контейнер последовательностей list
- •Контейнер последовательностей deque
- •Ассоциативные контейнеры
- •Ассоциативный контейнер multiset
- •Ассоциативный контейнер set
- •Ассоциативный контейнер multimap
- •Ассоциативный контейнер map
- •Адаптеры контейнеров
- •Адаптеры stack
- •Адаптеры queue
- •Адаптеры priority_queue
- •Пассивные и активные итераторы
- •Алгоритмы
- •Алгоритмы сортировки sort, partial_sort, sort_heap
- •Алгоритмы поиска find, find_if, find_end, binary_search
- •Алгоритмы fill, fill_n, generate и generate_n
- •Алгоритмы equal, mismatch и lexicographical_compare
- •Математические алгоритмы
- •Алгоритмы работы с множествами
- •Алгоритмы swap, iter_swap и swap_ranges
- •Алгоритмы copy, copy_backward, merge, unique и reverse
- •Примеры реализации контейнерных классов Связанные списки
- •Реализация односвязного списка
- •Реализация двусвязного списка
- •Реализация двоичного дерева
- •Литература
- •Вопросы по курсу ооп
- •220013, Минск, п.Бровки, 6.
Организация файла последовательного доступа
В С++ файлу не предписывается никакая структура. Для последовательного поиска данных в файле программа обычно начинает считывать данные с начала файла до тех пор, пока не будут считаны требуемые данные. При поиске новых данных этот процесс вновь повторяется.
Данные, содержащиеся в файле последовательного доступа, не могут быть модифицированы без риска разрушения других данных в этом файле. Например, если в файле содержится информация:
Коля 12 Александр 52
то при модификации имени Коля на имя Николай может получиться следующее:
НиколайАлександр 52
Аналогично в последовательности целых чисел 12 –1 132 32554 7 для хранения каждого из них отводится sizeof(int) байт. А при форматированном выводе их в файл они занимают различное число байт. Следовательно, такая модель ввода-вывода неприменима для модификации информации на месте. Эта проблема может быть решена перезаписью (с одновременной модификацией) в новый файл информации из старого. Это сопряжено с проблемой обработки всей информации при модификации только одной записи.
Следующая программа выполняет перезапись информации из одного файла в два других, при этом в первый файл из исходного переписываются только числа, а во второй - вся остальная информация.
#include "fstream.h"
#include "stdlib.h"
#include "math.h"
void error(char *s1,char *s2="") // вывод сообщения об ошибке
{ cerr<<s1<<" "<<s2<<endl; // при открытии потока для файла
exit(1);
}
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.h"
#include "stdlib.h"
void error(char *s1,char *s2="")
{ cerr<<s1<<" "<<s2<<endl;
exit(1);
}
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 1;
}
Каждому объекту класса istream соответствует указатель get (указывающий на очередной вводимый из потока байт) и указатель put (соответственно на позицию для вывода байта в поток). Классы istream и ostream содержат по 2 перегруженные компоненты-функции для перемещения указателя в требуемую позицию в потоке (связанном с ним файле). Такими функциями являются 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 соответственно
streampos tellg();