Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
_24-29_ООП_MatiasRust_DC_CT_LE_LcMS.doc
Скачиваний:
2
Добавлен:
01.03.2025
Размер:
122.88 Кб
Скачать

Форматирование данных, флаги и манипуляторы потоков.

Непосредственное применение операций вывода << (включение в поток) и ввода >> (извлечение из потока) к стандартным потокам cout, cin, cerr, clog для данных базовых типов приводит к использованию "умалчиваемых" форматов внешнего представления пересылаемых значений.

Форматы могут быть изменены программистом с помощью флагов форматирования. Эти флаги унаследованы всеми потоками библиотеки из базового класса ios. Флаги реализованы в виде отдельных фиксированных битов чисел типа long, поэтому несколько флагов с помощью логических битовых выражений можно объединять, тем самым по-разному комбинируя свойства потока. Некоторые флаги:

left = 0x0002 – вывод значения с левым выравниванием (прижать к левому краю поля);

right = 0x0004 – вывод значения с правым выравниванием (прижать к правому краю поля);

dec = 0x0010 – десятичная система счисления;

oct = 0x0020 – восьмеричная система счисления;

hex = 0x0040 – шестнадцатеричная система счисления;

showbase = 0x0080 – напечатать при выводе признак системы счисления;

showpos = 0x0400 – печатать знак числа (символ '+') при выводе положительных чисел;

Все флаги форматирования в виде отдельных фиксированных битов входят в компонент класса ios:

long x_flags;

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

int x_width – задает минимальную ширину поля вывода;

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

int x_fill – определяет символ заполнения поля вывода до мин. ширины, определенной x_width. По умолчанию x_fill имеет значение пробела.

Пример форматирования

#include <strstream.h>

void main (){

char name[] = "Строка длиной 52 символа в поле шириной 58 позиций.";

cout.width(58); // Ширина поля вывода для потока cout.

cout.fill('$'); // Символ заполнения пустых позиций поля

cout << name << endl; // Первый вывод строки в поток cout

cout.width(58);

cout.setf (ios::left,ios::adjustfield); // Смена выравнивания

cout.fill('#'); // Символ заполнения пустых позиций поля

cout << name << endl; // Второй вывод строки в поток cout}

Результат

$$$$$$Строка длиной 52 символа в поле шириной 58 позиций.

Строка длиной 52 символа в поле шириной 58 позиций.######

Манипуляторы – специальные функции, позволяющие программисту изменять состояния и флаги потока. Особенность манипуляторов и их отличие от обычных функций состоит в том, что их имена (без параметров) и вызовы (с параметрами) можно использовать в качестве правого операнда для операции обмена (<< или >>). В качестве левого операнда в этом выражении, как обычно, используется поток (ссылка на поток), и именно на этот поток оказывает влияние манипулятор.

Манипуляторы библиотеки классов ввода-вывода языка С++ делятся на две группы: манипуляторы с параметрами и манипуляторы без параметров.

Манипуляторы без параметров:

dec/hex/oct – при вводе и выводе устанавливает флаг десятичной/ 16-й/ 8-й системы счисления;

ws – действует только при вводе и предусматривает извлечение из входного потока пробельных символов (пробел, знаки табуляции '\t' и '\v', символ перевода строки '\n', символ возврата каретки '\r', символ перевода страницы '\f');

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

ends – действует только при выводе, включает в поток нулевой признак конца строки;

flush - действует только при выводе и очищает выходной поток, т.е. сбрасывает его буфер.

Манипулятор endl рекомендуется использовать при каждом выводе, который должен быть незамедлительно воспринят пользователем. Например, его использование просто необходимо в таком операторе: cout << "Ждите! Идет набор статистики." << endl;

При отсутствии endl здесь нельзя гарантировать, что сообщение пользователю не останется в буфере потока cout до окончания набора статистики.

Манипуляторы с параметрами определены в файле iomanip.h. Перечислим их:

setbase (int n) – устанавливает основание (n) системы счисления. Значениями могут быть: 0, 8, 10, 16.

resetiosflags (long L) – сбрасывает (очищает) отдельные флаги состояния потоков ввода и вывода в соответствии с единичными битами параметра L;

setiosflags (long L) – устанавливает отдельные флаги состояния (форматные биты) потоков ввода-вывода в соответствии с единичными битами параметра L;

setfill (int n) – устанавливает символ-заполнитель пустого пространства;

setprecision (int n) – устанавливает макс. число цифр дробной части числа при вводе и выводе;

setw (int n) – задает мин. ширину поля вывода.

Перегрузка операций << / >> для нестандартных типов данных

Каждая из операций обмена << и >> бинарная, причем левым операндом служит объект, связанный с потоком, а правый операнд должен иметь желаемый тип. Первый параметр функции – ссылка на объект потокового класса (тип istream& либо ostream&), второй параметр – ссылка или объект желаемого типа. Тип возвращаемого значения должен быть ссылкой на тот поток, для которого предназначена операция. Таким образом, формат операции-функции для перегрузки операций таков:

ostream& operator << (ostream& out, MyClass X) {

... // Любые операторы для параметра X.

out <<... // Вывод значений X.

return out; // Возврат ссылки на объект класса ostream.

}

istream& operator >> (istream& in, MyClass X) {

... // Любые операторы для параметра X.

in >>... // Ввод значений X.

return in; // Возврат ссылки на объект класса ostream.

}

Шаблоны функций и классов – параметризированные типы. Синтаксис определения шаблонов семейства функций и шаблонов семейства классов.

Шаблоны (англ. template) – средство языка C++ для кодирования обобщённых алгоритмов, без привязки к некоторым параметрам (типам данных, размерам буферов, значениям по умолчанию...). Шаблоны позволяют создавать параметризованные классы и функции.

Шаблоны классов. Например, нам нужен класс:

class MyClass { int Value; int Array[20]; ... }

Для одной конкретной цели мы можем использовать этот класс. Но если понадобится еще один класс, где нужно 30 элементов массива Array и вещественный тип Value, тогда мы можем абстрагироваться от конкретных типов и использовать шаблоны с параметрами.

Перед объявлением класса пишется слово template и указываются параметры в угловых скобках. template <int Len, typename T> class MyClass { T Value; T Array[Len];}

Тогда для первой модели пишем: SomeClass < 20, int > SomeVariable;

для второй: SomeClass < 30, double > SomeVariable2;

Пример использования

В классе, реализующем связный список целых чисел, алгоритмы добавления нового элемента списка, поиска нужного элемента не зависят от того, что элементы списка – целые числа. Те же алгоритмы применялись бы и для списка символов, строк, дат, классов игроков, и так далее.

template <class T> class List{

public: void Add (const T& Element);

bool Find (const T& Element);};

Для использования шаблона класса, необходимо указать его параметры:

List <int> li; li.Add (17);

List <string> ls; ls.Add ("Hello!");

Шаблоны функций

Шаблон функции начинается с ключевого слова template, за которым в угловых скобках следует список параметров. Затем следует объявление функции:

template <typename T> void sort (T Array[], int size);

Ключевое слово typename появилось сравнительно недавно, поэтому стандарт допускает использование class вместо typename: template < class T >

Пример использования

template <typename T> T min (T a, T b)

{ return a<b ? a : b; }

Для вызова этой функции можно просто использовать её имя:

min (1, 2); min ('a', 'b'); min (string("abc"),string("cde"));

Параметры шаблонов

Параметрами шаблонов могут быть: параметры-типы, параметры обычных типов, параметры-шаблоны.

Для параметров любого типа можно указывать значения по умолчанию.

template <class T1, // параметр-тип

typename T2, // параметр-тип