Чтение онлайн

на главную - закладки

Жанры

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

Когсуэлл Джефф

Шрифт:

 v.push_back(anand);

 v.push_hack(topalov);

 cout << "the best player is ";

 cout << max_element(v.begin, v.end, IsWeakerPlayer)->name_;

 cout << endl;

}

Программа примера 11.4 выдает следующий результат.

the best player is Garry Kasparov (лучший игрок - Гарри Каспаров)

Функторы

Многие STL-алгоритмы в качестве параметров используют определенные пользователем объекты-функции и указатели на функции. И те и другие называются функторами (functors).

Иногда в литературе термин «объект-функция» используется как синоним термина «функтор», однако я использую термин «объект-функция» для обозначения только экземпляров класса или структур, которые перегружают
operator
. Какой из двух типов функторов лучше использовать? В большинстве случаев объект-функция более эффективен, потому что большинство компиляторов могут легко его реализовать в виде встроенной функции.

Другая причина применения объекта-функции заключается в том, что он может иметь состояние. Вы можете передавать значения его конструктору, который их сохраняет в соответствующих полях для последующего использования. По выразительным возможностям эти объекты-функции становятся сопоставимы с концепцией замыканий, которая используется в других языках программирования.

Наконец, объекты-функции могут определяться внутри другой функции или класса. Указатели на функции приходится объявлять в области видимости пространства имен.

В примере 11.4 я показал, как в функции

max_element
можно использовать пользовательский предикат. Этот предикат является объектом-функцией
IsWeakerPlayer
.

Альтернативой пользовательскому предикату, показанному в примере 11.4, является перегрузка оператора

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

11.3. Вычисление суммы и среднего значения элементов контейнера

Проблема

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

Решение

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

accumulate
из заголовочного файла
<numeric>
и затем разделить ее на количество элементов, получая среднее значение. Пример 11.5 демонстрирует, как это можно сделать, используя вектор.

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

#include <numeric>

#include <iostream>

#include <vector>

using namespace std;

int main {

 vector<int> v;

 v.push_back(1);

 v.push_back(2);

 v.push_back(3);

 v.push_back(4);

 int sum = accumulate(v.begin, v.end, 0);

 double mean = double(sum) / v.size;

 cout << "sum = " << sum << endl;

 cout << "count = " << v.size << endl;

 cout << "mean = " << mean << endl;

}

Программа примера 11.5 выдает следующий результат.

sum = 10

count = 4

mean = 2.5

Обсуждение

Как правило, функция

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

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

Пример 11.6. Обобщенная функция по расчету среднего значения

template<class Iter_T>

double computeMean(Iter_T first, Iter_T last) {

 return static_cast<double>(accumulate(first, last, 0.0))

/ distance(first, last);

}

Функция

computeMean
из примера 11.6 подойдет в большинстве случаев, но она имеет одно ограничение: не работает она с такими итераторами ввода, как
istream_iterator
.

Итераторы istream_iterator и ostream_iterator

Шаблоны классов

istream_iterator
и
ostream_iterator
представляют собой специализированные итераторы, определенные в заголовочном файле
<iterator>
которые позволяют рассматривать потоки как однопроходные контейнеры.

istream_iterator
является итератором ввода, который выступает в роли оболочки такого потока ввода, как
cin
или
ifstream
, позволяя использовать его в качестве параметра во многих обобщенных функциях.
ostream_iterator
является итератором вывода, который позволяет использовать потоки вывода, как будто они являются контейнерами. Использование итераторов
istream_iterator
и
ostream_iterator
является хорошей привычкой, так как с их помощью легче создавать повторно используемый программный код

Итератор

istream_iterator
позволяет выполнить только один проход по данным, поэтому вы можете вызвать либо
accumulate
, либо
distance
, но если вы вызываете обе функции, данные становятся недействительными, и всякая последующая попытка их просмотра, вероятно, приведет к неудаче. Пример 11.7 показывает, как можно написать более обобщенную функцию по расчету среднего значения за один проход последовательности чисел.

Пример 11.7. Более обобщенная функция по расчету среднего значения

#include <stdexcept>

#include <iostream>

#include <iterator>

using namespace std;

template<class Value_T, class Iter_T>

Value_T computeMean(Iter_T first, Iter_T last) {

 if (first == last) throw domain_error("mean is undefined");

 Value_T sum;

 int cnt = 0;

 while (first != last) {

sum += *first++;

++cnt;

 }

 return sum / cnt;

)

int main {

 cout << "please type in several integers separated by newlines" << endl;

 cout << "and terminated by an EOF character (i.e , Ctrl-Z)" << endl;

 double mean = computeMean<double>(

istream_iterator<int>(cin), istream_iterator<int>);

Поделиться:
Популярные книги

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Герцогиня в ссылке

Нова Юлия
2. Магия стихий
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Герцогиня в ссылке

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Кодекс Охотника. Книга VI

Винокуров Юрий
6. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга VI

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

Душелов. Том 3

Faded Emory
3. Внутренние демоны
Фантастика:
альтернативная история
аниме
фэнтези
ранобэ
хентай
5.00
рейтинг книги
Душелов. Том 3

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Стеллар. Заклинатель

Прокофьев Роман Юрьевич
3. Стеллар
Фантастика:
боевая фантастика
8.40
рейтинг книги
Стеллар. Заклинатель

Возвышение Меркурия. Книга 5

Кронос Александр
5. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 5