Д. Стефенс - C++. Сборник рецептов

Тут можно читать онлайн Д. Стефенс - C++. Сборник рецептов - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство КУДИЦ-ПРЕСС, год 2007. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    C++. Сборник рецептов
  • Автор:
  • Жанр:
  • Издательство:
    КУДИЦ-ПРЕСС
  • Год:
    2007
  • Город:
    Москва
  • ISBN:
    5-91136-030-6
  • Рейтинг:
    3.9/5. Голосов: 101
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Д. Стефенс - C++. Сборник рецептов краткое содержание

C++. Сборник рецептов - описание и краткое содержание, автор Д. Стефенс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Данная книга написана экспертами по C++ и содержит готовые рецепты решения каждодневных задач для программистов на С++. Один из авторов является создателем библиотеки Boost Iostreams и нескольких других библиотек C++ с открытым исходным кодом. В книге затрагивается множество тем, вот лишь некоторые из них: работа с датой и временем; потоковый ввод/вывод; обработка исключений; работа с классами и объектами; сборка приложений; синтаксический анализ XML-документов; программирование математических задач. Читатель сможет использовать готовые решения, а сэкономленное время и усилия направить на решение конкретных задач.

C++. Сборник рецептов - читать онлайн бесплатно полную версию (весь текст целиком)

C++. Сборник рецептов - читать книгу онлайн бесплатно, автор Д. Стефенс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать
Проблема

Требуется иметь манипулятор потока, который делает что-нибудь такое, что не могут делать стандартные манипуляторы. Или вам нужен такой один манипулятор, который устанавливает несколько флагов потока, и вам не приходится вызывать несколько манипуляторов всякий раз, когда необходимо установить конкретный формат вывода.

Решение

Чтобы создать манипулятор, который не имеет аргументов (типа left), напишите функцию, которая принимает в качестве параметра ios_baseи устанавливает для него флаги потока. Если вам нужен манипулятор с аргументом, см. приводимое ниже обсуждение. Пример 10.4 показывает возможный вид манипулятора без аргументов.

Пример 10.4. Простой манипулятор потока

#include

#include

#include

using namespace std;

// вывести числа с плавающей точкой в обычном виде

inline ios_base& floatnormal(ios_base& io) {

io.setf(0, ios_base::floatfield);

return(io);

}

int main() {

ios_base::fmtflags flags = // Сохранить старые флаги

cout.flags();

double pi = 22.0/7.0;

cout << pi = " << scientific // Научный режим

<< pi * 1000 << '\n';

cout << "pi = " << floatnormal << pi << '\n';

cout.flags(flags);

}

Обсуждение

Существует два вида манипуляторов: с аргументами и без аргументов. Манипуляторы без аргументов пишутся просто. Вам требуется только написать функцию, которая принимает в качестве параметра поток, выполнить с ним какие-то действия (установить флаги или изменить установочные параметры) и возвратить его. Сложнее написать манипулятор, который имеет один или несколько аргументов, потому что потребуется создавать дополнительные классы и функции, которые работают «за кулисами». Поскольку манипуляторы без аргументов более простые, начнем с них.

Прочитав рецепт 10.1, вероятно, вы поняли, что существует три формата вывода чисел с плавающей точкой и только два манипулятора для выбора формата. Для используемого по умолчанию формата не предусмотрен манипулятор; вам придется соответствующим образом установить флаг для потока, чтобы вернуться к стандартному формату:

myiostr.setf(0, ios_base::float field);

Но для удобства вы можете добавить свой собственный манипулятор, делающий то же самое. Именно это сделано в примере 10.4. Манипулятор floatnormalустанавливает соответствующий флаг потока для вывода чисел с плавающей точкой в стандартном формате.

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

basic_ostream& operator<<

(basic_ostream& (* pf)basic_ostream&))

Здесь pf— это указатель функции, которая принимает в аргументе ссылку на basic_ostreamи возвращает ссылку на basic_ostream. Этот оператор просто обеспечивает вызов вашей функции, которая принимает в качестве аргумента текущий поток.

Манипуляторы с аргументами более сложные. Чтобы понять причину этого, рассмотрим работу манипулятора без аргументов. Пусть используется, например, следующий манипулятор

myostream << myManip << "foo";

Вы задаете его без скобок, поэтому его имя в действительности заменяется адресом функции вашего манипулятора. В действительности operator<<вызывает функцию манипулятора и передает ей поток, чтобы манипулятор мог выполнить свою работу.

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

myostream << myFancyManip(17) << "apple";

Как это будет работать? Если вы считаете, что myFancyManipявляется функцией, принимающей целочисленный аргумент, то возникает проблема: как передать поток в функцию без включения его в параметры и явного его использования? Вы могли бы написать так.

myostream << myFancyManip(17, myostream) << "apple";

Но это выглядит непривлекательно и избыточно. Одним из удобств манипуляторов является то, что их можно просто добавлять в строку с группой операторов operator<<, и они хорошо воспринимаются и используются.

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

Во-первых, вам необходимо определить временный класс, который делал бы всю работу. Для простоты предположим, что вам требуется написать манипулятор с именем setWidth, который делает то же самое, что и setw. Временная структура, которую вам необходимо построить, будет выглядеть примерно так.

class WidthSetter {

public:

WidthSetter(int n) : width_(n) {}

void operator()(ostream& os) const {os.width(width_);}

private:

int width_;

};

Этот класс содержит простую функцию. Предусмотрите в ней целочисленный аргумент и, когда operator()вызывается с аргументом потока, установите ширину для потока в значение, в какое она была установлена при инициализации этого объекта. В результате мы получим WidthSetter, сконструированный одной функцией и используемый другой. Ваш манипулятор конструирует эту функцию, и это будет выглядеть следующим образом.

WidthSetter setWidth(int n) {

return(WidthSetter(n)); // Возвращает инициализированный объект

}

Эта функция всего лишь возвращает объект WidthSetter, инициализированный целым значением. Этот манипулятор вы будете использовать в строке операторов operator<<следующим образом.

myostream << setWidth(20) << "banana";

Но этого недостаточно, потому что setWidthпросто возвращает объект WidthSetter; operator<<не будет знать, что с ним делать. Вам придется перегрузить operator<<, чтобы он знал, как управлять объектом WidthSetter:

ostream& operator<<(ostream& os, const WidthSetter& ws) {

ws(os); // Передать поток объекту ws

return(os); // для выполнения реальной работы

}

Это решает проблему, но не в общем виде. Вам не захочется писать класс типа WidthSetterдля каждого вашего манипулятора, принимающего аргумент (возможно, вы это и делаете, но были бы не против поступить по-другому), поэтому лучше использовать шаблоны и указатели функций для получения привлекательной, обобщенной инфраструктуры, на базе которой вы можете создавать любое количество манипуляторов. Пример 10.5 содержит класс ManipInfraи версию operator<<, использующую аргументы шаблона для работы с различными типами символов, которые может содержать поток, и с различными типами аргументов, которые могут быть использованы манипулятором потока.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Д. Стефенс читать все книги автора по порядку

Д. Стефенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




C++. Сборник рецептов отзывы


Отзывы читателей о книге C++. Сборник рецептов, автор: Д. Стефенс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x