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