|
Программирование >> Поддержка объектно-ориентированного программирования
Бьерн Страуструп. Язык программирования С++ 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); }
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |