Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Введение в С++. Страуструп..doc
Скачиваний:
63
Добавлен:
02.05.2014
Размер:
3.46 Mб
Скачать

10.4.1.2 Поля вывода

Функция width() устанавливает минимальное число символов, использующееся

в последующей операции вывода числа или строки. Так в результате

следующих операций

cout.width(4);

cout << '(' << 12 << ')';

получим число 12 в поле размером 4 символа, т.е.

( 12)

Заполнение поля заданными символами или выравнивание можно установить с

помощью функции fill(), например:

cout.width(4);

cout.fill('#');

cout << '(' << "ab" << ')';

напечатает

(##ab)

По умолчанию поле заполняется пробелами, а размер поля по умолчанию

есть 0, что означает "столько символов, сколько нужно". Вернуть размеру

поля стандартное значение можно с помощью вызова

cout.width(0); // ``столько символов, сколько надо''

Функция width() задает минимальное число символов. Если появится больше

символов, они будут напечатаны все, поэтому

cout.width(4);

cout << '(' << "121212" << ")\n";

напечатает

(121212)

Причина, по которой разрешено переполнение поля, а не усечение вывода,

в том, чтобы избежать зависания при выводе. Лучше получить правильную

выдачу, выглядящую некрасиво, чем красивую выдачу, являющуюся

неправильной.

Вызов width() влияет только на одну следующую за ним операцию

вывода, поэтому

cout.width(4);

cout.fill('#');

cout << '(' << 12 << "),(" << '(' <<12 << ")\n";

напечатает

(##12),(12)

а не

(##12),(##12)

как можно было бы ожидать. Однако, заметьте, что если бы влияние

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

еще более неожиданный результат:

(##12#),(##12#

)

С помощью стандартного манипулятора, показанного в 10.4.2.1, можно более

элегантно задавать размера поля вывода.

10.4.1.3 Состояние формата

В классе ios содержится состояние формата, которое управляется

функциями flags() и setf(). По сути эти функции нужны, чтобы

установить или отменить следующие флаги:

class ios {

public:

// управляющие форматом флаги:

enum {

skipws=01, // пропуск обобщенных пробелов для input

// поле выравнивания:

left=02, // добавление перед значением

right=04, // добавление после значения

internal=010, // добавление между знаком и значением

// основание целого:

dec=020, // восьмеричное

oct=040, // десятичное

hex=0100, // шестнадцатеричное

showbase=0200, // показать основание целого

showpoint=0400, // выдать нули в конце

uppercase=01000, // 'E', 'X' , а не 'e', 'x'

showpos=02000, // '+' для положительных чисел

// запись числа типа float:

scientific=04000, // .dddddd Edd

fixed=010000, // dddd.dd

// сброс в выходной поток:

unitbuf=020000, // после каждой операции

stdio=040000 // после каждого символа

};

//...

};

Смысл флагов будет разъяснен в последующих разделах. Конкретные

значения флагов зависят от реализации и даны здесь только для того,

чтобы избежать синтаксически неверных конструкций.

Определение интерфейса как набора флагов и операций для их

установки или отмены - это оцененный временем, хотя и несколько

устаревший прием. Основное его достоинство в том, что пользователь

может собрать воедино набор флагов, например, так:

const int my_io_options =

ios::left|ios::oct|ios::showpoint|ios::fixed;

Такое множество флагов можно задавать как параметр одной операции

cout.flags(my_io_options);

а также просто передавать между функциями одной программы:

void your_function(int ios_options);

void my_function()

{

// ...

your_function(my_io_options);

// ...

}

Множество флагов можно установить с помощью функции flags(), например:

void your_function(int ios_options)

{

int old_options = cout.flags(ios_options);

// ...

cout.flags(old_options); // reset options

}

Функция flags() возвращает старое значение множества флагов. Это

позволяет переустановить значения всех флагов, как показано выше,

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

myostream.flags(myostream.flags()|ios::showpos);

заставляет класс myostream выдавать положительные числа со знаком

+ и, в то же время, не меняет значения других флагов. Получается

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

операции | флаг showpos. Функция setf() делает то же самое,

поэтому эквивалентная запись имеет вид

myostream.setf(ios::showpos);

После установки флаг сохраняет значение до явной отмены.

Все-таки управление вводом-выводом с помощью установки и отмены

флагов - грубое и ведущее к ошибкам решение. Если только вы тщательно

не изучите свое справочное руководство и не будете применять флаги

только в простых случаях, как это делается в последующих разделах, то

лучше использовать манипуляторы (описанные в 10.4.2.1). Приемы работы

с состоянием потока лучше изучить на примере реализации класса, чем

изучая интерфейс класса.