До сих пор мы обходились без форматирования. Это было возможно, поскольку в системе ввода-вывода установлены режимы форматирования по умолчанию для всех стандартных типов данных. Однако часто требуется управлять форматированием явным образом, не полагаясь на умолчания. Форматировать можно стандартные и строковые потоки, а также потоки, связанные с текстовыми файлами. Во всех случаях средства форматирования применяются совершенно одинаково. Собственно, нас более других интересуют ответы на следующие вопросы:
• Каким образом задать ширину поля вывода?
• Как указать выравнивание данных внутри поля?
• Как вывести дробные числа с заданной точностью?
Все это можно сделать с помощью стандартных средств, к которым относятся:
• флаги форматирования;
• методы форматирования;
• манипуляторы.
Флаги форматирования
Флаги — это, как обычно, битовые константы. Флаги форматирования (см. п. п. 27.4.2.1.2 в [1]) определены в базовом классе библиотеки ввода-вывода i os_base (см. п. п. 27.4.2 в [1]):
left = 0X0001, // выравнивание влево
right = 0x0002, // выравнивание вправо
internal = 0x0004, // знак влево, число вправо
dec = 6x0008, // вывод десятичного целого
hex = 0X0010, // вывод шестнадцатеричного целого
oct = 0x0020, // вывод восьмеричного целого
fixed = 0x0040, // вывод дробного в виде dddd.dd (%f в printfO)
scientific = 0x0080, // вывод дробного в научном виде (%е в printfO)
boolalpha = 0X0100. // вывод true и false вместо 1 и 0
showbase 0x0200, // вывод префиксов для целых oct и hex
showpoint = 0x0400, // вывод незначащих нулей спереди
showpos = 0x0800, // вывод знака + для положительных целых
skipws = 0x1000, // пропускать символы-разделители (по умолчанию)
uni tbuf = 0x2000, // очищать буфер после каждой операции
uppercase = 0x4000 // вывод символов Е и X вместо е и х
Названия и назначение флагов являются стандартными, а вот конкретные значения битов в стандарте, естественно, не определены. В данном случае приведены значения, определенные в библиотеке STLport, которая поставляется вместе с системой Borland С++ Builder 6.
// получить флаги
// получить и установить флаги
// получить и установить флаги
// сбросить флаги
Для манипуляции флагами определено несколько методов (см. п. п. 27.4.2.2 в [1]):
fmtflags flags() const; fmtflags flags(fmtflags flags); fmtflags setf(fmtflags flag); void unsetf(fmtflags flags);
Флаги сохраняются в поле типа ios::fmtflags. Установить (присвоить единичный бит) несколько флагов для стандартного потока cout можно любым из следующих способов:
cout.flags(ios::showpos|ios::showbase|ios::uppercase); cout.setf(ios::showpos|ios::showbase|ios:uppercase);
Однако нужно помнить, что метод f lags() предварительно сбрасывает все флаги (присваивает нулевой бит всем флагам), а метод setf () — не сбрасывает. Отдельные флаги сбрасываются методом unsetf ():
cout.unsetf(ios::showpos|ios::showbase|ios:uppercase);
Все флаги, кроме флага ski pws, сброшены. Флаг ski pws по умолчанию установлен, поэтому, если мы хотим, чтобы символы-разделители не пропускались, мы его должны сбросить:
cout.unsetf(std::ios::skipws);
Важным флагом является uni tbuf. По умолчанию он сброшен, что означает накопление символов потока в буфере вывода. Если же флаг установить, то вывод выполняется практически без буферизации — выходной буфер очищается после каждой операции вывода. Этот флаг устанавливается по умолчанию для потока се г г.
Ряд флагов объединяется в группы (см. п. п. 27.4.2.1.2 в [1]). Для каждой группы определена маска, чтобы с флагами в группе было проще работать:
adjustfield = internal | left | right basefield = dec | hex | oct floatfield = fixed | scientific
В каждый конкретный момент времени только один из флагов группы может быть установлен. Для работы с такими флагами перегружен метод setf ():
fmtflags setf(fmtflags flag, fmtflags mask);
Этот метод сначала сбрасывает все флаги группы, а потом устанавливает требуемый. Например, восьмеричная система счисления для стандартного потока cout задается так:
cout.setf(std::ios::oct, std::ios::basefield);
Метод copyfmtO (см. п. п. 27.4.4.2 в [1]) позволяет скопировать состояние формата потока в другой поток, например:
strm.copyfmt(cout);
Поток strm получает состояние формата стандартного потока cout. |