Чтение онлайн

ЖАНРЫ

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

Некоторые представленные в табл. 10.1 (и в табл. 10.2 в следующем рецепте) манипуляторы переключают бинарные флаги потоков и в действительности реализуются как два манипулятора, которые включают и отключают флаг. Например, возьмем манипулятор

boolalpha
. Если вы хотите, чтобы булевы значения отображались в соответствии с текущей локализацией (например, «true» и «false»), используйте манипулятор
boolalpha
. Для отключения этого режима, чтобы вместо слов печатались 0 и 1, используйте манипулятор
noboolalpha
(он используется по умолчанию).

Действие всех манипуляторов сохраняется

до тех пор, пока оно не будет явно изменено, исключая манипулятор
setw
. Из примера 10.1 видно, что он вызывается перед каждой записью, однако
left
используется только один раз. Это объясняется тем, что ширина поля устанавливается в нуль после записи каждого значения в поток при помощи оператора
operator<<
; чтобы обеспечить одинаковую ширину всех полей, мне пришлось каждый раз вызывать
setw
.

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

Как и все другие классы стандартной библиотеки, работающие с символами, манипуляторы работают с потоками узких или широких символов. Поэтому вы можете использовать их в шаблонах для написания утилит форматирования, обрабатывающих потоки символов любого вида. В примере 10.2 приводится шаблон класса

TableFormatter
, который форматирует данные в колонки одинаковой ширины и выдает их в поток.

Пример 10.2. Параметрический класс для табличного представления данных

#include <iostream>

#include <iomanip>

#include <string>

#include <vector>

using namespace std;

// TableFormatter выдает в поток вывода символы типа T в форматированном

// виде.

template<typename T>

class TableFormatter {

public:

 TableFormatter(basic_ostream<T>& os) : out_(os) {}

 ~TableFormatter {out_ << flush;}

 template<typename valT>

 void writeTableRow(const vector<valT>& v, int width);

 //...

private:

 basic_ostream<T>& out_;

};

template<typename T, // ссылается на список параметров шаблона класса

 typename valT> // ссылается на список параметров функции-члена

void TableFormatter<T>::writeTableRow(const std::vector<valT>& v,

 int width) {

 ios_base::fmtflags flags = out_.flags;

 out_.flush;

 out_ << setprecision(2) << fixed; // Задать точность в случае применения

// чисел с плавающей точкой

 for (vector<valT>::const_iterator p = v.begin; p != v.end; ++p)

out_ << setw(width) << left << *p; //
Установить ширину поля, его

// выравнивание и записать элемент

out_ << endl; // Очистить буфер

 out setf(flags); // Восстановить стандартное состояние флагов

}

int main {

 TableFormatter<char> fmt(cout);

 vector<string> vs;

 vs.push_back("Sunday");

 vs.push_back("Monday");

 vs.push_back("Tuesday");

 fmt.writeTableRow(vs, 12);

 fmt.writeTableRow(vs, 12);

 fmt.writeTableRow(vs, 12);

 vector<double> vd;

 vd.push_back(4.0);

 vd.push_back(3.0);

 vd.push_back(2.0);

 vd.push_back(1.0);

 fmt.writeTableRow(vd, 5);

}

Вывод представленной в примере 10.2 программы выглядит следующим образом.

Sunday Monday Tuesday

4.00 3.00 2.00 1.00

Смотри также

Таблица 10.1, рецепт 10.2.

10.2. Форматирование вывода чисел с плавающей точкой

Проблема

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

Решение

Используйте стандартные манипуляторы, определенные в

<iomanip>
и
<ios>
, для управления форматом значений чисел с плавающей точкой при их записи в поток. Это можно делать очень многими способами, и в примере 10.3 предлагается несколько способов отображения значения числа «пи».

Пример 10.3. Форматирование числа «пи»

#include <iostream>

#include <iomanip>

#include <string>

using namespace std;

int main {

 ios_base::fmtflags flags = // Сохранить старые флаги

 cout.flags;

 double pi = 3.14285714;

 cout << "pi = " << setprecision(5) // Обычный (стандартный) режим;

<< pi << '\n'; // показать только 5 цифр в сумме

// по обе стороны от точки.

Поделиться с друзьями: