Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
84
Добавлен:
10.12.2013
Размер:
856.06 Кб
Скачать

2. Стандартные потоки

Для поддержки потоков библиотека C++ содержит иерархию классов, построен­ную на основе двух базовых классов — ios и streambuf. Класс ios содержит общие для ввода и вывода поля и методы, класс streambuf обеспечивает буферизацию потоков и их взаимодействие с физическими устройствами. Между этими классами существует связь: в классе ios есть поле bp, которое является указателем на streambuf.

Стандартному потоку ввода соответствует класс istream, стандартному потоку вывода – класс ostream. Эти классы являются производными от класса ios. Класс iostream является наследником классов istream и ostream, это класс двунаправленных потоков, он обеспечивает общие средства потокового ввода/вывода.

Для работы со стандартными потоками надо использовать библиотеку iostream. При этом в программе автоматически становятся доступными объекты cin и cout.

cin - объект, соответствует стандартному потоку ввода,

cout - объект, соответствует стандартному потоку вывода.

Оба эти потока являются буферизированными.

Форматированный ввод/вывод реализуется через две перегруженные операции:

<< - вывод в поток;

>> - чтение из потока.

Пример:

В классе ostream перегружены следующие операции:

ostream& operator<<(short);

ostream& operator<<(double);

ostream& operator<<(int);

//и т. д.

Пусть в программе встретились операторы:

int x=5;

cout<<x;

Компилятор определит, что левый операнд имеет тип ostream, а правый - int. В заголовочном файле ostream он найдет прототип метода ostream& operator<<(int) и вызовет метод cout.operator<<(x), где х имеет тип int, в результате работы этого метода на экране будет выведено число 5.

В случае вывода на экран значений встроенных типов (int, float, double и др.) класс ostream обеспечивает их преобразование из внутреннего двоичного формата к изображению в виде строки символов. При этом выполняется форматирование, которое установлено по умолчанию специальными полями базового класса ios.

Аналогично происходит работа со стандартным потоком cin.

3. Форматирование при вводе/выводе

Если форматирование по умолчанию не устраивает пользователя, то можно установить собственное форматирование. В потоковых классах форматирование выполняется тремя способами — с помо­щью флагов, манипуляторов и форматирующих методов.

Флаги представляют собой отдельные биты, объединенные в поле x_flags класса ios.

Флаг

Положение

Умолчание

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

skipws

0x0001

+

При извлечении пробельные символы игнорируются

left

0x0002

Выравнивание по левому краю поля

right

0x0004

+

Выравнивание по правому краю поля

internal

0x0008

Знак числа выводится по левому краю, число — по правому. Промежуток заполняется символами x_fi 11 (см. ниже), по умолчанию пробелами

dec

0x0010

+

Десятичная система счисления

oct

0x0020

Восьмеричная система счисления

hex

0x0040

Шестнадцатеричная система счисления

showbase

0x0080

Выводится основание системы счисления (0х для шестнадцатеричных чисел и 0 для восьмеричных)

showpoint

0x0100

При выводе вещественных чисел печатать десятичную точку и дробную часть

uppercase

0x0200

При выводе использовать символы верхнего регистра

showpos

0x0400

Печатать знак при выводе положительных чисел

scientific

0x0800

Печатать вещественные числа в форме мантиссы с порядком

fixed

0x1000

Печатать вещественные числа в форме с фиксированной точкой (точность определяется полем x_precision, см. ниже)

Флаги (left, right и internal), (dec, oct и hex), а также (scientific и fixed) взаимно исключа­ют друг друга, то есть в каждый момент может быть установлен только один флаг из каж­дой группы.

Для управления флагами в классе ios есть методы flags, setf и unsetf:

1ong ios:: f1ags ();– возвращает текущие флаги потока;

1ong ios::f1ags(1ong); – присваивает флагам значение параметра;

long ios:: setf (long, long); – присваивает флагам, биты которых установлены в первом параметре значение соответствующих битов второго параметра;

long ios::setf(1ong) - устанавливает флаги, биты которых установлены в параметре.

Все функции возвращают прежние флаги потока.

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

int x_width – минимальная ширина поля вывода;

int x_precision – количество цифр в дробной части при выводе вещественных чисел;

int x_fill – символ заполнения поля вывода.

Для управления этими полями используются методы width, precision и fill:

int ios::width() – возвращает значение ширины поля вывода;

int ios::width(int) – устанавливает ширину поля вывода в соответствии со значением параметра;

int ios::precision() – возвращает значение точности представления при вы­воде вещественных чисел;

int ios:: precision (int) — устанавливает значение точности представления при выводе вещественных чисел, возвращает старое зна­чение точности;

char fill() – возвращает текущий символ заполнения;

char fill (char)– устанавливает значение текущего символа заполнения, возвращает старое значение символа.

Пример форматирования при помощи флагов.

#include <iostream.h>

int main()

{

long a =1000, b = 077;

cout.width(7);

cout.setf(ios::hex | ios::showbase | ios::uppercase);//шестнадцатеричная СС, показать //основание СС , верхний регистр

cout <<a;

cout.width(7);

cout <<b<< endl;

double d = 0.12, с = 1.3е-4;

cout.setf(ios::left);//прижать к левому краю

cout << d << endl:

cout <<c;

return 0;

}

Результаты работы программы:

0X3E8 0X3F

0.12

0.00013

Манипуляторы - это функции, которые можно включать в цепочку опе­раций помещения и извлечения для форматирования данных, т. е. их можно включать прямо в поток. Манипуляторы де­лятся на простые, не требующие указания аргументов, и параметризованные. Пользоваться манипуляторами более удобно, чем методами установки флагов форматирования.

Простые манипуляторы:

dec – устанавливает при вводе и выводе флаг десятичной системы счисления;

oct– устанавливает при вводе и выводе флаг восьмеричной системы счисления;

hex – устанавливает при вводе и выводе флаг шестнадцатеричной системы счисления;

ws – устанавливает при вводе извлечение пробельных символов;

endl – при выводе включает в поток символ новой строки и выгружает буфер;

ends – при выводе включает в поток нуль-терминатор;

flush – при выводе выгружает буфер.

Параметризированные манипуляторы требуют указания аргумента. Для их использования к программе надо подключить заголовочный файл <iomanip>.

setbase(int n) – задает основание системы счисления( n=10|8|16|0, 0 – по умолчанию, десятичное число, кроме случаев, когда вводятся 8-чные или 16-ичные числа).

resetiosflags(long) – сбрасывает флаги состояния потока, биты которых уста­новлены в параметре;

setiosflags(long) – устанавливает флаги состояния потока, биты которых в па­раметре равны 1.

setfill(int) – устанавливает символ-заполнитель с кодом, равным значению параметра;

setprecision(int) – устанавливает максимальное количество цифр в дробной части для вещественных чисел;

setw(int) – устанавливает максимальную ширину поля вывода.

Пример использования параметризированных манипуляторов:

#include <iostream.h>

#include <iomanip.h>

int main()

{

double d[]={1.234,-12.3456,123.45657,-1.2345,0.00001};

cout<<setfill('.')<<setprecision(3);//установили заполнитель и количество цифр в дробной //части

cout<<setiosflags(ios::showpoint|ios::fixed);//печатать десятичную точку и дробную //часть, печатать вщественные числа в форме с фиксированной точкой

for(int i=0;i<5;i++)

cout<<setw(12)<<d[i]<<endl;//устанавливает максимальную ширину поля вывода

return 0;

}

Результаты работы программы:

.......1.234

.....-12.346

.....123.457

......-1.234

.......0.000

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

Пользователь может создать свой собственный манипулятор и определить в нем правила, по которым будет осуществляться вывод информации в поток.

Пример файла “manip.h”, в котором описывается пользовательский манипулятор

typedef ostream&( *point)(ostream&, int n, char c);//тип-указатель на функцию манипулятора, параметрами функции являются int n – максимальная ширина поля вывода и char c – символ-заполнитель

class mnp

{

int w;//ширина

char fill;// заполнитель

point f;//функция, которая устанавливает ширину и заполнитель

public:

mnp( point F, int W, char FILL){w=W; fill=FILL; f=F;}//конструктор манипулятора

friend ostream& operator<<(ostream&, mnp);//перегруженная функция-операция для вывода в //поток

};

ostream& operator<<(ostream& out, mnp x)

{

return x.f(out, x.w, x.fill );//возвращает поток как результат выполнения функции манипулятора

}

ostream& func(ostream& out, int w, char fill)

{

//функция, которая выполняет форматирование

out.width(w);//ширина

out.flags(ios::right);//выравнивание

out.fill(fill);//заполнитель

return out;

}

mnp mm(int w, char fill) //функция, которая выполняет форматирование

//принимает параметры манипулятора и возвращает объект класса mnp

{

return mnp ( func, w, fill );

}

Использовать манипулятор при выводе можно так:

cout<<mm(15,' . ')<<a;//объект а выводится на 15 позициях, при выводе выполняется сдвиг вправо, свободные позиции заполняются точками.