Поиск
с помощью предиката
Поиск первого
объекта, который удовлетворяет условию, заданному предикатом, осуществляется
с помощью шаблона функции 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, то выполнение продолжается.