Иллюстрированный самоучитель по Visual Studio.Net

         

Поиск с помощью предиката


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

//========= Предикат принадлежности к teenager

friend bool Teen (Man& m);

Тело этой функции определите глобально, то есть вне класса:

//========= Предикат принадлежности к teenager

bool Teen(Man& m)

{

return 13 < m.m_Age && m.m_Age < 19;

}

Теперь покажем, как искать в контейнере первый элемент, удовлетворяющий предикату, а также все элементы, удовлетворяющие этому условию. Ниже нам понадобятся несколько объектов класса Man, поэтому мы ввели их объявление в начало функции main. Далее везде мы будем считать, что эти объекты присутствуют в функции main, но не будем приводить их заново:

void main ()

{

//======== Набор объектов класса Man

Man joe("Joe Doe",30),

joy ("Joy Amore", 18) ,



Mаrу("Mary Poppins",36),

duke("Duke Ellington",90),

liza("Liza Dale", 17),

simon("Simon Paul",15),

zoran("Zoran Todorovitch",27) ,

Charlie("Charlie Parker",60),

win("Winton Kelly",50),

mela("Melissa Robinson",9);

vector<Man> men;

men.push_back (zoran);

men.push_back (liza);

men.push_back (simon);

men.push_back (mela);

// Поиск первого объекта, удовлетворяющего предикату

vector<Man>::iterator p =

find_if (men .begin () ,

men.endO, Teen);

//======== Ручной поиск всех таких объектов

while (p != men.end())

{

cout « "\nTeen: " « *p;

p = find_if(++p, men.endO, Teen);

}

cout « "\nNo more Teens\n";

//======== Подсчет всех teenagers

uint teen = count_if (men.begin (),men.endO , Teen);

cout « "\n\n Teen totals: " « teen;

//======== Выполняем функцию для всех объектов

for_each(men.begin(),men.end(),OutTeen) ;

//======== Используем обратный итератор



cout«"\n\nMan in reverse\n";

for (vector<Man>::reverse_iterator

r = men.rbegin();

r != men.rendO; r++) cout«*r«";

//======== Заполняем вектор целых

vector<int> v;

for (int i=l; i<4; i++) v.push_back(i);

//======== Иллюстрируем алгоритм и адаптивный functor

transform(v.begin () , v.end(), v.begin (), negate<int> () ) ;

pr(v,"Integer Negation");

//======== Создаем еще два вектора целых

vector<int> vl(v.size()), v2 (v.size());

//======== Иллюстрируем алгоритм заполнения вектора

fill (vl.begin (), vl.endO, 100);

//======== Иллюстрируем проверку

assert (vl .size () >= v.size() && v2.size() >= v.sizeO);

//======== Иллюстрируем вторую версию transform

transform(v.begin(), v.end(), vl.begin(), v2.begin(),

plus<int>() ) ;

pr(v2,"Plus");

cout « "\n\n";

}

В рассмотренном фрагменте мы иллюстрируем использование алгоритма count_if, который проходит по заданному диапазону последовательности и возвращает количество объектов, удовлетворяющих предикату. Алгоритм f or_each позволяет выполнить определенное действие для заданного диапазона последовательности. В примере функция OutTeen вызывается для всех элементов контейнера. Приведем тело этой функции:

void OutTeen(Man& m)

{

// Если парамтр удовлетворяет предикату, то выводим его

if (Teen(m))

cout « "\nTeen: " « m;

}

Далее в коде демонстрируется, как использовать обратный итератор reverse_ iterator. Для него справедливы позиции rbegin — последний элемент последовательности и rend — барьер, ограничивающий последовательность спереди. Операция ++ сдвигает итератор на один элемент в сторону к началу последовательности.

Последний фрагмент функции main демонстрирует использование алгоритма transform, который воздействует на каждый элемент указанного диапазона и модифицирует его в соответствии либо с unary function (первая версия), либо с binary function (вторая версия). Суть модификации определяется последним параметром.В нашем случае мы используем negator (отрицатель) и бинарную операцию plus, настроенную на тип int. Сложить два контейнера можно и другими способами.

Если вы подключите файл заголовков <assert. h>, то сможете осуществлять логические проверки с помощью функции assert. Она проверяет свой аргумент и, если он равен false, выводит на экран сообщение вида:

Assertion failed: s.topQ == joy,

file C:\My ProjectsXStack.cpp, line 29

abnormal program termination

Затем прекращает процесс вызовом функции abort. Если результатом выражения (аргумента функции assert) будет true, то выполнение продолжается.




Содержание раздела