Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП на языке С++.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.8 Mб
Скачать

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

Для создания манипуляторов можно использовать макросы OMANIP(int), IMANIP(int), IOMANIP(int).

Эти макросы содержатся в файле <iomanip.h>

Ниже приведены примеры использования этих макросов.

а) манипулятор с одним параметром

ostream& w(ostream& out,int n)

{out.width(n);

//out<<setw(n);

return out;

}

OMANIP(int) w(int n)

{return OMANIP(int)(w,n);

}

Здесь две функции с именем w, вторая на первый взгляд кажется ненужной. Однако OMANIP(int) – это макрос, позволяющий определить манипулятор, который принимает параметры. Обнаружив в операции << манипулятор, компилятор использует вторую функцию для вызова первой.

б) манипулятор с двумя параметрами.

Проблема здесь в том, что макросы принимают только один параметр, так что для передачи нескольких параметров придется использовать структуру или класс. Например, для двух параметров:

struct Point

{

int n;

int m;

};

Перед использованием в манипуляторе Point нужно вызвать IOMANIPdeclare(Point). IOMANIPdeclare(Type) принимает только идентификатор, так что передача указателей или ссылок требует использования typedef.

#include<iostream.h>

#include<iomanip.h>

struct Point

{int x,y;};

IOMANIPdeclare(Point);

ostream& wp(ostream& out,Point p)

{out.width(p.x);

out.flags(ios::fixed);

out.precision(p.y);

return out;

}

OMANIP(Point) wp(int x,int y)

{Point p;

p.x=x;

p.y=y;

return OMANIP(Point)(wp,p);

}

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

Каждый поток имеет связанное с ним состояние. Состояния потока описываются в классе 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(); возвращает, если eofbit

int fail(); возвращает, если failbit, badbit или hardfail

int good();возвращает, если goodbit

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

Установить состояние потока в заданное значение можно функцией void clear(int s=0);

Эта функция устанавливает флаги ios::state в значение, заданное параметром s, не изменив при этом бита hardfail.

Пример 10.1.

#include<iostream.h>

#include<stdlib.h>

void main()

{int flags;

int k;

cin>>k;

flags=cin.rdstate();

if(flags) //если ошибка

if(flags& ios:badbit)

{cout<<”Ошибка\n”;

cin.clear(0);}

else{cerr<<”Эту ошибку нельзя исправить\n”;

abort();}

cout<<”Ввод без ошибок\n”;

cout<<k<<endl;

}

Пример 10.2.

#include<iostream.h>

#include<stdlib.h>

void main()

{int k;

cin>>k;

if(!cin)

if(cin.bad())

{cout<<”Oшибка\n”;

cin.clear(0);}

else

{cerr<<”Неисправимая ошибка\n”;

abort();}

cout<<”Ввод без ошибок\n”;

cout<<k<<endl;

}

Здесь используется перегруженная int operator!();

Результат операции – значение функции ios::fail().

Есть еще operator void*(), который возвращает 0, когда fail() возвращает 1, в противном случае возвращает указатель this на объект ios.