Программирование >>  Поддержка объектно-ориентированного программирования 

1 ... 84 85 86 [ 87 ] 88 89 90 ... 120


Бьерн Страуструп. Язык программирования С++

1234 1234 2322 2322 4d2 4d2

Если появится необходимость указывать систему счисления для каждого выдаваемого числа, следует установить флаг showbase. Поэтому, добавив перед приведенными выше обращениями

cout.setf(ios::showbase); мы получим

1234 1234 02322 02322 0x4d2 0x4d2

Стандартные манипуляторы, приведенные в $$10.4.2.1, предлагают более элегантный способ определения системы счисления при выводе целых.

10.4.1.5 Выравнивание полей

С помощью обращений к setf() можно управлять расположением символов в пределах поля:

cout.setf(ios::left,ios::adjustfield); влево

cout.setf(ios::right,ios::adjustfield); вправо cout.setf(ios::internal,ios::adjustfield); внутреннее

Будет установлено выравнивание в поле вывода, определяемом функцией ios::width(), причем не затрагивая других компонентов состояния потока.

Выравнивание можно задать следующим образом:

cout.width(4);

cout << ( << -12 << )\n ; cout.width(4);

cout.setf(ios::left,ios::adjustfield); cout << ( << -12 << )\n ; cout.width(4);

cout.setf(ios::internal,ios::adjustfield); cout << ( << -12 << \n ;

что выдаст

( -12)

(-12 ) (- 12)

Если установлен флаг выравнивания internal (внутренний), то символы добавляются между знаком и величиной. Как видно, стандартным является выравнивание вправо.

10.4.1.6 Вывод плавающих чисел.

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

cout.setf(ios::scientific,ios::floatfield); cout.setf(ios::fixed,ios::floatfield);

cout.setf(0,ios::floatfield); вернуться к стандартному

установят вид печати вещественных чисел без изменения других компонентов состояния потока. Например:

cout << 1234.56789 << \n;

cout.setf(ios::scientific,ios::floatfield); cout << 1234.56789 << \n; cout.setf(ios::fixed,ios::floatfield); cout << 1234.56789 << \n;

напечатает

1234.57



1.234568e+03 1234.567890

После точки печатается n цифр, как задается в обращении

cout.precision(n)

По умолчанию n равно 6. Вызов функции precision влияет на все операции ввода-вывода с вещественными до следующего обращения к precision, поэтому

cout.precision(8);

cout << 1234.56789 << \n;

cout << 1234.56789 << \n; cout.precision(4);

cout << 1234.56789 << \n;

cout << 1234.56789 << \n;

выдаст

1234.5679 1234.5679

1235 1235

Заметьте, что происходит округление, а не отбрасывание дробной части.

Стандартные манипуляторы, введенные в $$10.4.2.1, предлагают более элегантный способ задания формата вывода вещественных.

10.4.2 Манипуляторы

К ним относятся разнообразные операции, которые приходится применять сразу перед или сразу после операции ввода-вывода. Например:

cout << x; cout.flushO; cout << y; cin.eatwhiteO; cin >> x;

Если писать отдельные операторы как выше, то логическая связь между операторами неочевидна, а если утеряна логическая связь, программу труднее понять.

Идея манипуляторов позволяет такие операции как flush() или eatwhite() прямо вставлять в список операций ввода-вывода. Рассмотрим операцию flush(). Можно определить класс с операцией operator<<(), в котором вызывается flush():

class Flushtype { };

ostream& operator<<(ostream& os, Flushtype)

return flush(os);

определить объект такого типа

Flushtype FLUSH;

и добиться выдачи буфера, включив FLUSH в список объектов, подлежащих выводу:

cout << x << FLUSH << y << FLUSH ;

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

typedef ostream& (*Omanip) (ostream&);



ostream& operator<<(ostream& os, Omanip f)

return f(os);

Здесь операция вывода использует параметры типа указатель на функцию, имеющую аргумент ostream& и возвращающую ostream& . Отметив, что flush() есть функция типа функция с аргументом ostream& и возвращающая ostream& , мы можем писать

cout << x << flush << y << flush; получив вызов функции flush(). На самом деле в файле <iostream.h> функция flush() описана как

ostream& flush(ostream&); а в классе есть операция operator , которая использует указатель на функцию, как указано выше:

class ostream : public virtual ios {

...

public:

ostream& operator<<(ostream& ostream& (*)(ostream&)); ...

В приведенной ниже строке буфер выталкивается в поток cout дважды в подходящее время:

cout << x << flush << y << flush; Похожие определения существуют и для класса istream:

istream& ws(istream& is ) { return is.eatwhiteO; }

class istream : public virtual ios {

...

public:

istream& operator>>(istream&, istream& (*) (istream&)); ...

поэтому в строке

cin >> ws >> x;

действительно обобщенные пробелы будут убраны до попытки чтения в x. Однако, поскольку по умолчанию для операции >> пробелы съедаются и так, данное применение ws() избыточно.

Находят применение и манипуляторы с параметрами. Например, может появиться желание с помощью

cout << setprecision(4) << angle;

напечатать значение вещественной переменной angle с точностью до четырех знаков после точки.

Для этого нужно уметь вызывать функцию, которая установит значение переменной, управляющей в потоке точностью вещественных. Это достигается, если определить setprecision(4) как объект, который можно выводить с помощью operator<<():

class Omanip int { int i;

ostream& (*f) (ostream&,int); public:

Omanip int(ostream& (*ff) (ostream&,int), int ii)

: f(ff), { }

friend ostream& operator<<(ostream& os, Omanip& m)

{ return m.f(os,m.i); }



1 ... 84 85 86 [ 87 ] 88 89 90 ... 120

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика