Шаг 487.
Библиотека STL. Ввод-вывод с использованием потоковых классов. Форматирование. Ширина поля, заполнитель, выравнивание

    На этом шаге мы рассмотрим использование перечисленных параметров при использовании форматного ввода-вывода.

    Функции width() и fill() определяют ширину поля и заполнитель (таблица 1).

Таблица 1. Функции для работы с шириной поля и заполнителем
Функция Описание
width() Возвращает текущую ширину поля
width(val) Задает ширину поля равной val и возвращает предыдущую ширину поля
fill() Возвращает текущий заполнитель
fill(c) Назначает новый и возвращает предыдущий заполнитель

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

    При выводе функция width() определяет минимальную ширину поля. Определение относится только к следующему выводимому форматированному полю. При вызове без аргументов width() возвращает текущую ширину поля. При вызове с целочисленным аргументом функция width() изменяет ширину поля и возвращает ее предыдущее значение. По умолчанию минимальная ширина равна 0; это означает, что размер поля может быть произвольным. Такое значение устанавливается после вывода.

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

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

    Тип выравнивания данных внутри поля определяется тремя флагами, перечисленными в таблице 2. Эти флаги определяются в классе ios_base вместе с соответствующей маской.

Таблица 2. Флаги типа выравнивания
Маска Флаг Описание
adjustfield left Выравнивание по левому краю
right Выравнивание по правому краю
internal Выравнивание знака по левому краю, а значения - по правому краю
нет Выравнивание по правому краю (по умолчанию)

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

    В таблице 3 показаны результаты применения разных флагов. В качестве заполнителя используется символ подчеркивания.

Таблица 3. Примеры выравнивания
Флаг width() -42 0.12 "Q" 'Q'
left 6 -42___ 0.12__ Q_____ Q_____
right 6 ___-42 __0.12 _____Q _____Q
internal 6 -___42 __0.12 _____Q _____Q

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

    В таблице 4 перечислены манипуляторы, изменяющие ширину поля, заполнитель и тип выравнивания.

Таблица 4. Манипуляторы для управления шириной поля, заполнителем и типом выравнивания
Манипулятор Описание
setw(val) Устанавливает ширину поля при вводе и выводе равной val (соответствует функции width())
seffill(c) Назначает заполнителем символ с (соответствует функции fill())
left Устанавливает выравнивание по левому краю
right Устанавливает выравнивание по правому краю
internal Устанавливает выравнивание знака по левому краю, а значения - по правому краю

    Манипуляторам setw() и setfill() должен передаваться аргумент, поэтому для их использования в программу необходимо включить заголовочный файл <iomanip>. Например, рассмотрим такой фрагмент:

#include <iostream> 
#include <iomanip>
.   .   .   .   .
std::cout << std::setw(8) << std::setfill('_') << -3.14
          << ' ' << 42 << std::endl;
std::cout << std::setw(8) << "sum: "
          << std::setw(8) << 42 << std::endl;

    Этот фрагмент выводит следующий результат:

___-3.14 42
__sum:______42

Использование при вводе ширины поля

    Ширина поля также позволяет задать максимальное количество символов, вводимых при чтении последовательностей символов типа char*. Если значение width() отлично от 0, то из потока данных читаются не более width()-l символов.

    Поскольку обычные С-строки не могут увеличиваться при чтении данных, при их чтении оператором >> всегда следует ограничивать максимальный размер ввода функциями width() или setw(). Пример:

char buffer[81];
// Чтение не более 80 символов
cin >> setw(sizeof(buffer)) >> buffer;

    Функция читает не более 80 символов, хотя sizeof(buffer) возвращает 81, поскольку один символ является признаком завершения строки (он присоединяется автоматически). Обратите внимание иа распространенную ошибку:

char* s;
cin >> setw(sizeof(s)) >> s;   // ОШИБКА ВРЕМЕНИ ВЫПОЛНЕНИЯ

    Дело в том, что s объявляется как указатель без выделения памяти под символы, поэтому sizeof(s) возвращает размер указателя вместо размера памяти, на которую он ссылается. Это одна из типичных ошибок, возникающих при работе с С-строками. Строковые классы позволяют предотвратить подобные ошибки:

string buffer;
cin >> buffer;  //OK

    На следующем шаге мы рассмотрим отображение знака для положительных чисел и вывод в верхнем регистре.




Предыдущий шаг Содержание Следующий шаг