Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lek13_14.doc
Скачиваний:
9
Добавлен:
13.07.2019
Размер:
695.3 Кб
Скачать

Флаги и функции форматирования

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

Флаги можно устанавливать с помощью функции setf(), а сбрасывать — с помощью функции unsetf (). Есть два варианта функции setf() с одним аргументом типа long и с двумя. Первым аргументом является набор флагов, объединенных с помощью операции побитового ИЛИ (|). Возможные флаги перечислены в таблице 5.

Таблица 5. Флаги форматирования

Флаг 

Назначение

skipws    

при вводе пробельные литеры пропускаются

left 

выводимые данные выравниваются по левому краю с дополнением символами-заполнителями по ширине поля

right

выводимые данные выравниваются по правому краю с дополнением символами-заполнителями по ширине поля (установлен по умолчанию)

internal 

при выравнивании символы-заполнители вставляются между символом знака или префиксом основания системы счисления и числом

dec   

 целые числа выводятся по основанию 10 (установлен по умолчанию); устанавливается также манипулятором dec

oct  

целые числа выводятся по основанию 8; устанавливается также манипулятором oct

hex 

целые числа выводятся по основанию 16; устанавливается также манипулятором hex

showbase

 при выводе целых чисел отображается префикс, указывающий на основание системы счисления

showpoint

при выводе чисел с плавающей запятой всегда отображается десятичная точка, а хвостовые нули не отбрасываются

uppercase 

 шестнадцатеричные цифры от А до F, а также символ экспоненты Е отображаются в верхнем регистре

showpos

 при выводе положительных чисел отображается знак плюс

scientific

числа с плавающей запятой отображаются в научном формате (с экспонентой)

fixed

числа с плавающей запятой отображаются в фиксированном формате (без экспоненты)

unitbuf 

при каждой операции вывода буфер потока должен очищаться

stdio

при каждой операции вывода буферы потоков stdout и stderr должны очищаться

  Вторым аргументом является специальная битовая маска, определяющая, какую группу флагов можно модифицировать. Имеются три стандартные маски:

adjustfield =     internal | left | right

basefield  =    dec | oct | hex

floatfield =    fixed | scientific

Оба варианта функции setf() возвращают значение типа long, содержащее предыдущие установки всех флагов.

Все перечисленные флаги, а также константы битовых масок и упоминавшиеся манипуляторы dec, hex и oct являются членами класса ios - базового в иерархии всех классов ввода-вывода. В этот класс входят, помимо прочего, функции fill() , precision ( ) и width ( ) , тоже связанные с форматированием выводимых данных!

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

Когда установлен флаг scientific или fixed, функция precision() задает точность представления чисел с плавающей запятой, в противном случае определяет общее количество значащих цифр. Аналогичные действия выполняет манипулятор setprecision() . По умолчанию точность равна 6. Вызванная без аргументов, функция возвращает текущее значение точности.

Функция width() определяет минимальную ширину поля вывода в символах. Если при выводе количество символов оказывается меньшим ширины поля, оно дополняется специальными символами-заполнителями. После каждой операции записи значение ширины поля сбрасывается в 0. Аналогичные действия выполняет манипулятор setw( ) . Вызванная без аргументов, функция возвращает текущую ширину поля.

Манипуляторы setfill () , setprecision() и setw(), также являющиеся членами класса ios, относятся к категории параметризованных, и для работы с ними необходимо дополнительно подключить к программе файл IOMANIP.

Следующая программа является написанным на C++ аналогом программы printf.c, рассмотренной в предыдущей главе.

// //   ioflags.cpp //   Эта программа на языке C++ демонстрирует применение //   флагов и функций форматирования. //

#include <strstrea.h>

#define MAX_LENGTH 20

void row ();

main{) {

char  с = 'A', psz[]  = "Строка для экспериментов", strbuffer[MAX_LENGTH];

int   ivalue = 1234;

double dPi   = 3.14159265;

// вывод символа с row(); // [ 1] cout<< с;

// вывод ASCII-кода символа с row() ; // [2] cout << (int)c;

// вывод символа с ASCII-кодом 90 

row (); // [ 3]    

cout << (char)90; 

// вывод значения ivalue в восьмеричной системе

row(); //[4]   

cout << oct << ivalue;

// вывод значения ivalue в шестнадцатеричной системе

//сбуквами в нижнем регистре

row (); // [5]

cout << hex << ivalue;

// вывод значения ivalue в шестнадцатеричной системе

// с буквами в верхнем регистре

row (); // [ 6]

cout.setf(ios::uppercase);

cout << hex << ivalue;

cout.unsetf(ios::uppercase); // отмена верхнего регистра символов

cout<< dec;              // возврат к десятичной системе

// вывод одного символа, минимальная ширина поля равна 5, // выравнивание вправо с дополнением пробелами row();// [ 7] cout.width(5); cout<< с;

// вывод одного символа, минимальная ширина поля равна 5,

// выравнивание влево с дополнением пробелами

row(); // [ 8]

cout.width(5);

cout.setf(ios::left);

cout << c;

cout.unsetf(ios::left);

// вывод строки, отображаются 24 символа row();// [9] cout<< psz;

// вывод минимум 5-ти символов строки row();// [10] cout.width(5); cout<< psz;

// вывод минимум 38-ми символов строки,

// выравнивание вправо с дополнением пробелами

row();// [11]

cout.width(38); cout << psz;

// вывод минимум 38-ми символов строки,

// выравнивание влево с дополнением пробелами

row ();// [12] 

cout.width(38);

cout.setf(ios::left);

cout << psz;

cout.unsetf(ios::left);

// вывод значения ivalue, по умолчанию отображаются 4 цифры row();// [13] cout<< ivalue;

// вывод значения ivalue со знаком

row ();// [14]

cout.setf(ios::showpos);

cout << ivalue;

cout.unsetf(ios::showpos) ;

// вывод значения ivalue минимумиз 3-х цифр, отображаются 4 цифры row ();// [15] cout.width(3); cout << ivalue;

// вывод значения ivalue минимум из 10-ти цифр, } // выравнивание вправо с дополнением пробелами row();// [16] cout.width(10); cout<< ivalue;

// вывод значения ivalue минимум из 10-ти цифр,

// выравнивание влево с дополнением пробелами

row();// [17]

cout.width(10);

cout.setf(ios::left) ;

cout << ivalue;

cout.unsetf(ios::left);

// вывод значения ivalue минимум из 10-ти цифр,

// выравнивание вправо с дополнением нулями

row (); // [18]

cout.width (10);

cout.fill ('0');

cout << ivalue;

cout.fill (' ');

// вывод значения dPiс форматированием по умолчанию row(); // [19] cout<< dPi;

// вывод значения dPi, минимальная ширина поля равна 20, // выравнивание вправо с дополнением пробелами row{); // [20] cout.width (20); cout<< dPi;

// вывод значения dPi, минимальная ширина поля равна 20,

// выравнивание вправо с дополнением нулями

row();// [21]

cout.width(20);

cout.fill('0');

cout << dPi;

cout. fill (' ');

// вывод значения dPi, минимальная ширина поля равна 20,

// выравнивание влево с дополнением пробелами

row();// [22]

cout.width(20);

cout.setf(ios::left) ;

cout<< dPi;

// вывод значения dPi, минимальная ширина поля равна 20,

// выравнивание влево с дополнением нулями

row();// [23]

cout.width(20);

cout. fill ('0');

cout << dPi;

cout.unsetf(ios::left);

cout.fill(' ');

// вывод 19-ти символов строки, минимальная ширина поля равна 19

row();// [24]

ostrstream(strbuffer, 20).write(psz,19)<< ends;

cout.width(19);

cout << strbuffer;

// вывод первых двух символов строки

row(); // [25]  

ostrstream(strbuffer, 3).write(psz,2) << ends;

cout<< strbuffer;

// вывод первых двух символов строки, минимальная ширина поля равна 19, // выравнивание вправо с дополнением пробелами

row();// [26] cout.width(19); cout << strbuffer;

// вывод первых двух символов строки, минимальная ширина поля равна 19, // выравнивание влево с дополнением пробелами row();// [27] cout.width(19);

cout .setf (ios :: left) ; cout << strbuffer; cout .unsetf (ios :: left) ;

// вывод значенияdPi из5-ти значащих цифр row ();// [28] cout .precision (9); cout << dPi;

// вывод значения dPiиз 2-х значащих цифр, минимальная ширина поля

// равна 20, выравнивание вправо с дополнением пробелами

row ();// [29]

cout. width (20) ;

cout .precision (2);

cout << dPi;

// выводзначенияdPi из 4-хзначащихцифр row () ; // [30] cout .precision (4); cout << dPi;

// вывод значения dPi из 4-х значащих цифр, минимальная ширина поля // равна 20, выравнивание вправо с дополнением пробелами row(); // [31] cout. width(20); cout<< dPi;

// вывод значения dPi, минимальная ширина поля равна 20,

// 4 цифры после десятичной точки, выравнивание вправо

IIс дополнением пробелами, научный формат (с экспонентой)

row ();// [32]

cout . setf (ios :: scientific) ;

cout. width ( 20 );

cout << dPi;

cout. unset f (ios: : scientific );

return (0);

}

void row() {

static int ln = 0;

cout << " \n [";

cout.width(2) ;

cout<< ++ln<< "] "; }

Результат работы программы будет выглядеть следующим образом:

[ 1]   А 

[ 2]    65

[ 3]    Z

[ 4]   2322

[ 5]    4d2

[ 6]    4D2

[ 7]А

[ 8]А

[ 9]  Строка для экспериментов

[10]  Строка для экспериментов

[11]'       Строка для экспериментов

[12]Строка для экспериментов

[13]1234

[14]+1234

[15]1234

[16]1234

[17]  1234

[18]   0000001234

[19]  3.14159

[20]   3.14159

[21]   00000000000003.14159

[22]   3.14159

[23]    3.141590000000000000

[24]  Строка для эксперим

[25]  Ст

[26] Ст

[27] Ст

[28] 3.14159265

[29] 3.1

[30] 3.142

[31]3.142

[32] 3.1416e+000

В этой программе следует обратить внимание на использование класса ostrstream в пунктах 24 и 25, а также неявно в пунктах 26 и 27. Этот класс управляет выводом строк. Необходимость в нем возникла в связи с тем, что флаги форматирования оказывают влияние на работу оператора <<, но не функции write() класса ostream(класс ostrstream является его потомком и наследует данную функцию), которая записывает в поток указанное число символов строки. Выводимые ею данные всегда прижимаются к левому краю. Поэтому мы поступаем следующим образом:

ostrstream(strbuffer, 20).write(psz,19)<< ends; cout.width(19); cout << strbuffer;

Разберем этот фрагмент шаг за шагом. Сначала вызывается конструктор класса ostrstream, создающий временный безымянный объект данного класса, автоматически уничтожаемый по завершении строки. Если вы еще не знакомы с понятием конструктора, то поясним, что это особая функция, предназначенная для динамического создания объектов своего класса. Конструктор класса ostrstream требует указания двух аргументов: буферной строки, в которую будет осуществляться вывод, и размера буфера. Особенность заключается в том, что реальный размер буферного массива может быть больше указанного, но все данные, записываемые сверх лимита, будут отсекаться.

Итак, конструктор создал требуемый объект, связанный с буфером strbuffer. Этот объект является обычным потоком в том смысле, что им можно управлять как и любым другим потоком вывода, только данные будут направляться не на экран, а в буфер. Вторым действием вызывается функция write() объекта, записывающая в поток первые 19 символов строки psz. Оператор точка (.) в данном случае обозначает операцию доступа к члену класса. Здесь тоже есть своя особенность: функция write() возвращает адрес потока, из которого она была вызвана. А это, в свою очередь, означает, что мы можем тут же применить к потоку оператор вывода <<. Итого, три действия в одном выражении! Манипулятор ends класса ostream вставляет в поток символ \0,служащий признаком завершения строки. Именно поэтому в буфере было зарезервировано 20 ячеек — на единицу больше, чем количество выводимых символов строки psz. В результате выполненных действий в буфере оказалась сформированной готовая строка, которая, в конце концов, и направляется в поток cout.

Теперь рассмотрим, что происходит в пункте 25:

ostrstream (strbuf fer, 3) .write (psz, 2) << ends; cout << strbuffer;

Последовательность действий та же, но резервируется не весь буфер, а только первые три ячейки. Трюк в том, что объект cout воспринимает массив strbuffer как обычную строку, но поскольку в третьей ячейке стоит символ \0,то получается, что строка состоит из двух символов! В пунктах 26 и 27 используется содержимое буфера, полученное в пункте 25.

Важно также помнить, что функция width( ) оказывает влияние только на следующий за ней оператор вывода, тогда как, например, действие функции precision() останется в силе до тех пор, пока она не будет выполнена снова либо не будет вызван манипулятор setprecision( ) .

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]