Каждый поток, как и всякий объект, в любой момент времени характеризуется состоянием, определяющим свойства потока. Состояние описывается набором трех групп параметров:
- флаги (признаков) состояния потоков и указателей, которые определяют связь одних потоков с другими;
- флаги и переменные форматирования, которые определяют поведение потока при форматированном вводе-выводе;
- переменная, хранящая текущую позицию потока и флаги режимов работы с устройствами (файлами).
Форматирование представляет собой преобразование последовательности байт потока в соответствии с установленными правилами. Так, при выводе в поток форматирование позволяет получать данные в определенном виде. При вводе форматирование позволяет считывать последовательность байт из потока как значение определенного типа. Флаги и переменные форматирования позволяют задать установленные в потоке правила форматирования, действующие при выполнении операций << и >>.
Класс ostream наследован от класса basic_ios, который, в свою очередь, наследуется от ios_base. Класс ios_base хранит информацию, описывающую состояние формата. Управлять флагами и устанавливать значения переменных форматирования можно или на основе методов класса ios, или с помощью специальных функций – манипуляторов. Так, используя функции-члены ios_base, можно управлять шириной поля, основанием чисел для отображения целых, количеством знаков после запятой, и другими форматами [1-3].
Манипуляторы потоков используются в C++ при решении вопросов, связанных с форматированным вводом-выводом (например, задание точности, ширины полей, пропуск символов-разделителей во входном потоке, и т.д.) и находятся в пространстве имен std. Использование в программе параметризованных манипуляторов потока возможно только после включения заголовочного файла iomanip; непараметризованные манипуляторы потоков могут использоваться и без iomanip (например, endl, dec, oct, hex). Ниже в таблице 1 приведены краткие сведения по использованию некоторых манипуляторов потоков.
Таблица 1. Манипуляторы потоков
Манипулятор потока |
Описание, пример использования |
setw |
Установка ширины поля: cout< Выходная величина Name будет напечатана с шириной поля 5, т.е. ее значение будет содержать, по крайней мере, 5 символьных позиций. Если длина выходной величины менее 5 символов, она будет выровнена в поле по правому символу; в противном случае размер поля будет увеличен, чтобы вместить всю величину. |
width |
Установка ширины поля: cout< Если величина Name имеет меньше символов, чем заданная ширина поля 5, то для заполнения лишних позиций будут использованы заполняющие символы; в противном случае размер поля будет увеличен, чтобы вместить всю величину. Для этих же целей можно использовать функцию-член width(): cout.width(10); cout< Метод width() касается только следующего отображаемого элемента, после чего ширина поля вернется к значению по умолчанию. |
setprecision |
Позволяет управлять точностью печатаемых чисел с плавающей запятой (числом разрядов справа от десятичной точки): cout<ch; Действует для всех последующих операций вывода, пока не будет произведена другая установка точности. С тем же успехом можно использовать функцию-член precision(): cout.precision(4); cout<<ch; |
dec |
Устанавливает десятичный формат представления данных (с основанием 10): cout<ch; |
oct |
Устанавливает восьмеричный формат представления данных (с основанием 8): cout<ch; |
hex |
Устанавливает шестнадцатеричный формат представления данных (с основанием 16): cout<ch; |
setbase |
Изменяет основание потока, принимая какой-либо из целых параметров 8, 10 или 16, задающих основание системы счисления: cout<ch; |
setiosflags |
Используется для установки флагов состояния форматов (то же, что и функция setf, см. ниже): cout< cout<<1.536754345678< |
resetiosflags |
То же, что и функция unsetf (см. ниже). |
setfill |
Устанавливает значение заполняющего символа: cout< cout<<1.536< Для этой же цели можно использовать функцию-член fill(), которая позволяет задать заполняющий символ, использующийся при выравнивании в полях (по умолчанию используются пробелы) и возвращает предыдущий заполняющий символ: cout.fill('*'); В отличие от ширины поля, новый символ-заполнитель остается до тех пор, пока не будет заменен. |
Так как манипуляторы не являются функциями-членами, то они не должны вызываться объектом. Отмечу, что, так как манипуляторы представляют собой функции, то их можно использовать, например, так:
hex(cout);
Здесь вызов функции-манипулятора устанавливает шестнадцатеричный формат основания числа для потока cout.
Для задания видов форматирования используют флаги формата, которые определяются как перечислимый тип в классе ios_base. Установка флагов осуществляется функциями-членами setf(), unsetf() и flags() (однако во многих случаях удобнее использовать манипуляторы потоков). После установки флаг сохраняет свое состояние, пока не будет сброшен. Флаги состояния формата приведены в таблице 2.
Замечание
При использовании компилятора Borland C++ 5.02 вместо класса ios_base необходимо указывать класс ios. Это связано с тем, что члены и методы класса ios_base раньше находились в классе ios. Сейчас класс ios_base выступает базовым классом для ios. В новой системе класс ios – шаблонный класс со спецификациями char и wchar_t, а ios_base содержит в себе не шаблонные средства.
Таблица 2. Флаги состояния формата
Флаг состояния формата |
Описание |
ios_base::boolalpha |
Позволяет выводить символическое представление true и false. |
ios_base::left |
Выравнивание выходных данных по левому краю поля с добавлением необходимых символов-заполнителей справа. |
ios_base::right |
Выравнивание выходных данных по правому краю поля с добавлением необходимых символов-заполнителей слева. |
ios_base::internal |
Показывает, что знак числа должен быть выровнен по левой границе поля, а значение числа – по правой границе. В промежуточные позиции размещаются заполняющие символы. |
ios_base::skipws |
Показывает, что во входном потоке должны пропускаться символы-разделители (принимается как значение по умолчанию). Для сброса флага можно вызвать функцию unsetf(ios_base::skipws); |
ios_base::fixed |
Устанавливается для вывода чисел с плавающей запятой в формате с фиксированной точкой и заданным количеством разрядов справа от десятичной точки (указанным с помощью функции-члена precision() или манипулятора setprecision): cout.precision(4); cout.setf(ios_base::fixed); cout<<1.53600123; Аналогично: cout.precision(4); cout.setf(ios_base::fixed); cout<<setprecision(4)<<1.53600123; Для восстановления формата вывода чисел (по умолчанию) с плавающей запятой, следует написать: cout.setf(0, ios_base::floatfield); |
ios_base::scientific |
Устанавливается для вывода чисел с плавающей запятой в экспоненциальном формате. |
ios_base::showpos |
Указывает, что положительным и отрицательным числам должны предшествовать знаки "плюс" и "минус" соответственно. |
ios_base::showpoint |
Указывает, что числа с плавающей запятой должны выводиться с десятичной точкой. Обычно используют совместно с флагом ios_base::fixed. |
ios_base::uppercase |
Указывает, что прописная буква "E" должна использоваться при представлении значения с плавающей запятой в экспоненциальном формате. Также предполагает использование прописных букв в шестнадцатеричном целом. |
ios_base::oct |
Устанавливает восьмеричный формат представления данных (с основанием 8). |
ios_base::dec |
Устанавливает десятичный формат представления данных (с основанием 10). |
ios_base::hex |
Устанавливает шестнадцатеричный формат представления данных (с основанием 16). |
ios_base::showbase |
Указывает, что основание числа должно выводиться перед числом: для восьмеричных чисел выводится начальный символ "0", десятичные числа выводятся обычным способом, шестнадцатеричные числа выводятся с индикатором "0x" или "0X". |
ios_base::adjustfield |
Обычно задается в качестве второго параметра функции-члена setf(), если устанавливаются флаги left, right или internal (это гарантирует, что функция setf() установит только один из трех флагов). |
ios_base::unitbuf |
Позволяет задать очистку буфера после каждой операции вывода. |
Допускается объединение разных флагов в одно значение (типа long) путем использования операции побитовое ИЛИ (|); можно также использовать операцию "запятая":
cout.setf(ios_base::showpoint | ios_base::showpos); cout<
Текущие установки флагов формата могут быть сохранены в переменной типа long, и в дальнейшем их можно использовать для восстановления исходных установок форматов.
Функция-член unsetf() сбрасывает установленные флаги и возвращает их предыдущие значения. Функция-член flags() позволяет вернуть прежний набор установок.