Программирование на C и C++

Онлайн справочник программиста на C и C++

Форматирование с помощью функций-членов ios

В заголовочном файле iostream.h определены следующие переменные перечисляемого типа:

// флаги форматирования
enum {
skipws = 0x0001,
left = 0x0002,
right = 0x0004,
internal = 0x0008,
dec = 0x0010,
oct = 0x0020,
hex = 0x0040,
showbase = 0x0080,
showpoint = 0x0100,
uppercase = 0x0200,
showpos = 0x0400,
scientific = 0x0800,
fixed = 0x1000,
unitbuf = 0x2000,
stdio = 0x4000,
boolalpha = 0x8000
};

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

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

При установке флага left осуществляется вывод с левым выравниванием. Соответственно при установке флага right вывод осуществляется с правым выравниванием. При установке флага internal добавляется числовое значение для того, чтобы заполнить поле вставкой пробелов до знака или буквы. Далее будет показано, как указать ширину поля. По умолчанию вывод осуществляется с выравниванием по правому краю.

Также по умолчанию численные значения выводятся в десятичной форме. Однако можно пере­определить такой способ. Например, устанавливая флаг oct, по умолчанию задается вывод в восьме­ричной форме. Установка флага hex задаст вывод в шестнадцатиричной форме. Для возвращения к десятичному выводу устанавливается флаг dec.

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

Установка флага showpoint приводит к выводу десятичной запятой и нулей справа для всех чисел с плавающей запятой вне зависимости, нужно это или нет.

По умолчанию при выводе научных данных, т.е. при использовании экспоненциальной формы записи чисел с плавающей запятой, используется 'е' в нижнем регистре. Также при выводе шест­надцатиричных величин символ 'x' выводится в нижнем регистре. При установке флага uppercase эти символы будут выводиться в верхнем регистре.

Установка флага showpos приводит к тому, что перед положительными числами будет выво­диться знак «плюс».

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

При установке флага unitbuf при каждой операции вставки данные немедленно заносятся в поток.

При установке флага stdio после каждого вывода данные заносятся в потоки stdout и stderr.

При установке флага boolalpha можно вводить и выводить данные булевого типа.

Флаги хранятся в формате длинных целых. В проекте стандарта ANSI для языка С++ этот тип обозначается как fmtrlags, но в Borland С++ флаги имеют тип long.

Для установки флагов используется функция setf(), чей формат имеет следующий вид:

long setf(long flags);

Эта функция возвращает предыдущее значение флага, устанавливая его новое значение равным зна­чению, заданному параметром flags. При этом все остальные флаги остаются неизменными. Напри­мер, для того чтобы установить флаг showbase, можно использовать следующую инструкцию:

stream.setf(ios::showbase);

Здесь stream является каким-либо потоком, на который надо оказать воздействие. Например, следующая программа устанавливает флаги showpos и scientific для cout:

#include <iostream.h>
int main()
{
cout.setf (ios::showpos);
cout.setf(ios::scientific);
cout << 123 << " " << 123.23 << " ";
return 0;
}

Данная программа выводит на экран следующие данные:

+123 +1.232300е+02

С помощью операции побитового ИЛИ можно установить одновременно столько флагов, сколько надо. Например, можно изменить программу таким образом, что будет осуществляться только один вызов функции setf() при установке обоих флагов scientific и showpos:

cout.setf (ios::scientific | ios::showpos);

Для отключения флагов надо использовать функцию unsetf(). Она имеет следующий прототип:

long unsetf(long flags);

Функция возвращает значение предыдущей установки флага и сбрасывает флаги, определяемые параметром flags.

Иногда бывает полезным знать текущую установку флагов. Можно получить текущие значения флагов, используя функцию flags(), которая имеет следующий прототип:

long flags( );

Эта функция возвращает текущие значения флагов, ассоциированных с тем потоком, членом ко­торого она является. Используя следующую форму функции flags(), можно установить значения флагов на указанные в параметрах flags() и возвратить предыдущие значения флагов:

long flags(long flags);

Для того, чтобы познакомиться с работой функций flags() и unsetf(), рассмотрим следующую программу. Она включает в себя функцию, называемую showflags(), которая выводит значения флагов.

#include <iostream.h>
void showflags(long f);
int main()
{
long f;
f = cout.flags ();
showflags(f);
cout.setf(ios::showpos);
cout.setf(ios::scientific);
f = cout.flags ();
showflags(f);
cout.unsetf(ios::scientific);
f = cout.flags ();
showflags(f);
return 0;
}
void showflags(long f)
{
long i;
for (i=0x8000; i; i = i >> 1)
if (i & f) cout << "1 ";
else cout << "0 ";
cout << "\n";
}

Исполнение данной программы выдаст следующие данные:

0000000000000001
0000110000000001
0000010000000001

Кроме флага форматирования также можно установить ширину поля потока, символ для за­полнения и число цифр после десятичной запятой. Для этого используются следующие функции:

int width(int len);

char fill(char ch);

int precision(int num);

Функция width() возвращает текущую ширину поля потока и устанавливает новое значение, опреде­ляемое параметром len. По умолчанию ширина поля изменяется в зависимости от числа симво­лов, необходимых для записи данных. Функция filld() возвращает текущее значение символа для заполнения, которым по умолчанию является пробел, и устанавливает текущий символ заполне­ния равным ch. Символ заполнения используется для заполнения пустых мест в соответствии с заданной спецификацией ширины поля. Функция precision() возвращает число цифр после деся­тичной запятой и устанавливает новое значение, задаваемое параметром num. Ниже представлена программа, демонстрирующая использование этих трех функций:

#include <iostream.h>
int main()
{
cout.setf (ios::showpos);
cout.setf (ios::scientific);
cout << 123 << " " << 123.23 << "\n";
cout.precision (2); // две цифры после запятой
cout.width(10); // в поле из десяти символов
cout << 123 << " " << 123.23 << " \ n";
cout.fill ('#'); // заполнение с помощью #
cout.width(10); // в поле из десяти символов
cout <<123 << " " << 123.23;
return 0;
}

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

+123 +1.232300е+02
                   +123 +1.23е+02
######+123 +1.23е+02

Надо помнить, что флаги одного потока независимы от флагов другого потока. Изменение флагов в одном потоке не влияет на флаги другого.