Определение пользовательских манипуляторов. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Определение пользовательских манипуляторов.



Порядок создания пользовательского манипулятора с параметрами, например для вывода, следующий:

1. Определить класс (my_manip) с полями: параметры манипулятора, указатель на функцию типа

ostream& (*f)(ostream&,<параметры манипулятора>);

2. Определить конструктор этого класса (my_manip) с инициализацией полей.

3. Определить, в этом классе дружественную функцию – operator<<. Эта функция в качестве правого аргумента принимает объект класса my_manip, левого аргумента (операнда) поток ostream и возвращает поток ostream как результат выполнения функции *f. Например,

typedef far ostream&(far *PTF)(ostream&,int,int,char);

class my_man{

int w;int n;char fill;

PTF f;

public:

//конструктор

my_man(PTF F,int W,int N,char FILL):f(F),w(W),n(N),fill(FILL){}

friend ostream& operator<<(ostream&,my_man);

};

ostream& operator<<(ostream& out,my_man my)

{return my.f(out,my.w,my.n,my.fill);}

 

4. Определить функцию типа *f (fmanip), принимающую поток и параметры манипулятора и возвращающую поток. Эта функция собственно и выполняет форматирование. Например,

ostream& fmanip(ostream& s,int w,int n,char fill)

{s.width(w);

s.flags(ios::fixed);

s.precision(n);

s.fill(fill);

return s;}

5. Определить собственно манипулятор (wp) как функцию, принимающую параметры манипулятора и возвращающую объект my_manip, поле f которого содержит указатель на функцию fmanip. Например,

my_man wp(int w,int n,char fill)

{return my_man(fmanip,w,n,fill);}

Для создания пользовательских манипуляторов с параметрами можно использовать макросы, которые содержатся в файле <iomanip.h>:

OMANIP(int)

IMANIP(int)

IOMANIP(int)

Состояние потока.

Каждый поток имеет связанное с ним состояние. Состояния потока описываются в классе ios в виде перечисления enum.

public:

enum io_state{

goodbit, //нет ошибки 0Х00

eofbit, //конец файла 0Х01

failbit, //последняя операция не выполнилась 0Х02

badbit, //попытка использования недопустимой операции 0Х04

hardfail //фатальная ошибка 0Х08

};

Флаги, определяющие результат последней операции с объектом ios, содержатся в переменной state. Получить значение этой переменной можно с помощью функции int rdstate().

Кроме того, проверить состояние потока можно следующими функциями:

int bad();        1, если badbit или hardfail

int eof();          1, если eofbit

int fail();         1, если failbit, badbit или hardfail

int good();      1, если goodbit

 

 

Если операция >> используется для новых типов данных, то при её перегрузке необходимо предусмотреть соответствующие проверки.

Файловый ввод-вывод.

Потоки для работы с файлами создаются как объекты следующих классов:

ofstream – запись в файл;

ifstream – чтение из файла;

fstream – чтение/запись.

Для создания потоков имеются следующие конструкторы:

0  fstream();

создает поток, не присоединяя его ни к какому файлу.

0  fstream(const char* name,int mode,int p=filebuf::openprot);

создает поток, присоединяет его к файлу с именем name, предварительно открыв файл, устанавливает для него режим mode и уровень защиты p. Если файл не существует, то он создается. Для mode=ios::out, если файл существует, то его размер будет усечен до нуля.

Флаги режима определены в классе ios и имеют следующие значения:

in - для чтения

out - для записи

ate - индекс потока помещен в конец файла. Чтение больше не допустимо, выводные данные записываются в конец файла;

app - поток открыт для добавления данных в конец. Независимо от seekp() данные будут записываться в конец;

trunc - усечение существующего потока до нуля;

nocreate -команда открытия потока будет завершена неудачно, если файл не существует;

noreplace -команда открытия потока будет завершена неудачно, если файл существует;

binary-поток открывается для двоичного обмена.

Если при создании потока он не присоединен к файлу, то присоединить существующий поток к файлу можно функцией

void open(const char* name,int mode,int p=filebuf::openprot);

Функция

void fstreambase::close();

сбрасывает буфер потока, отсоединяет поток от файла и закрывает файл. Эту функцию необходимо явно вызвать при изменении режима работы с потоком. Автоматически она вызывается только при завершении программы.

 

Таким образом, создать поток и связать его с файлом можно тремя способами:

1. Создается объект filebuf

filebuf fbuf;

Объект filebuf связывается с устройством (файлом)

fbuf.open(“имя”,ios::in);

Создается поток и связывается с filebuf

istream stream(&fbuf);

2. Создается объект fstream (ifstream, ofstream)

fstream stream;

Открывается файл, который связывается через filebuf с потоком

stream.open(“имя”,ios::in);

3. Создается объект fstream, одновременно открывается файл, который связывается с потоком

fstream stream(“имя”,ios::in);

Порядок выполнения работы.

1. Определить пользовательский тип данных (класс). Определить и реализовать в нем конструкторы, деструктор, операции присваивания, ввода и вывода для стандартных потоков.

2. Написать программу № 1 для создания объектов пользовательского класса (ввод исходной информации с клавиатуры с использованием перегруженной операции “>>) и сохранения их в потоке (файле). Предусмотреть в программе вывод сообщения о количестве сохраненных объектов и о длине полученного файла в байтах.

3. Выполнить тестирование программы.

4. Реализовать для вывода в поток свой манипулятор с параметрами.

5. Написать программу № 2 для чтения объектов из потока, сохранения их в массиве и просмотра массива. Для просмотра объектов использовать перегруженную для cout операцию << и свой манипулятор. Предусмотреть в программе вывод сообщения о количестве прочитанных объектов и байтов.

6. Выполнить программу для чтения из файла сохраненных предыдущей программой объектов и их просмотра.

7. Написать программу № 3 для добавления объектов в поток.

8. Выполнить программу, добавив в поток несколько объектов и просмотреть полученный файл.

9. Написать программу № 4 для удаления объектов из файла.

10. Выполнить программу, удалив из потока несколько объектов и просмотреть полученный файл.

 

 

11. Написать программу № 5 для корректировки (т.е. замены) записей в файле.

12. Выполнить программу и просмотреть полученный файл.

Методические указания.

1 В качестве пользовательского типа данных взять класс из лабораторной работы № 1. Поля класса типа char* заменить на char[целое].

2 В совокупности программы должны использовать все классы потоков: istream, ostream, fstream, ifstream, ofstream.

3 Также в программах следует показать все три способа создания потока и открытия файла (см. выше).

4 Необходимо продемонстрировать чтение из файла и запись в файл как с помощью функций read/ write, так и с помощью перегруженных операций >> и <<.

5 Пользовательский манипулятор создается с не менее чем с двумя параметрами.

6 Определение пользовательского класса сохранить в h-файле.

7 Определение компонентных функций пользовательского класса сохранить в cpp-файле.

8 Реализацию манипулятора сохранить в h-файле.

В качестве параметров манипулятора можно использовать:

а) ширину поля вывода;

б) точность вывода вещественных чисел;

в) символ-заполнитель;

г) способ выравнивания (к левой или правой границе)

и т.д.

9. В поток записать не менее 5 объектов.

10. После записи объектов в файл и перед чтением их из файла определить количество записанных объектов и вывести эту информацию.

Определить количество записанных в файл объектов можно следующим образом:

а) стать на конец файла - функции seekp(),seekg();

б) определить размер файла в байтах - функции tellp(),tellg();

в) определить количество записанных объектов - размер файла поделить на размер объекта.

11. Необходимо тестировать ошибки при работе с файлом. Для этого следует использовать перегруженные операции operator!(),operator void*() и функции bad(),good().

 

12 Поскольку в файле может храниться любое, заранее не известное, количество объектов, для их сохранения в программе № 2 при чтении из файла использовать динамический массив.

13. Следует определить функцию find(), которая принимает значение ключевого поля объекта и возвращает смещение этого объекта от начала файла. Вызывать эту функцию перед удалением/изменением объекта в файле.

14 Для изменения и удаления объекта написать функции del() и repl(), которым передается ссылка на поток, смещение от начала файла изменяемой или удаляемой записи (результат вызова функции find), новое значение изменяемой записи.

Содержание отчета.

1. Титульный лист.

2. Постановка задачи.

3. Определение пользовательского класса.

4. Реализация манипулятора.

5. Реализация функций find(), del() и repl().

6. Пояснения к программам. Для каждой программы указывается, какие потоковые классы в ней используются, как создаются объекты потоковых классов, как открываются файлы, каким образом выполняется ввод и вывод данных.

 



Поделиться:


Последнее изменение этой страницы: 2021-11-27; просмотров: 74; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.141.199.243 (0.013 с.)