- •1. Понятие объектно-ориентированного программирования
- •2.Основные принципы ооп. Инкапсуляция
- •4. Конструкторы
- •Конструктор без параметров
- •Конструктор копирования
- •Деструкторы
- •Массивы объектов
- •Виртуальные методы
- •Использование классов функциональных объектов для настройки шаблонных классов
- •2. Стандартные потоки
- •3. Форматирование при вводе/выводе
- •4. Методы обмена с потоками
- •5. Ошибки потоков
- •6. Файловые потоки
- •7. Потоки и типы определяемые пользователем
- •Стандартная библиотека шаблонов stl (4 часа)
- •2. Контейнеры
- •3. Итераторы
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 позициях, при выводе выполняется сдвиг вправо, свободные позиции заполняются точками.