Некоторые представленные в табл. 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 в форматированном
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 = // Сохранить старые флаги