Шаг 113.
Библиотека STL.
Унарные предикаты

    На этом шаге мы рассмотрим использование унарных предикатов.

    Особую разновидность вспомогательных функций, используемых алгоритмами, составляют предикаты. Предикатом называется функция, которая возвращает логическое значение. С помощью предикатов часто определяют критерии сортировки или поиска. В зависимости от способа применения предикаты делятся на унарные и бинарные. Учтите, что не любая унарная или бинарная функция, возвращающая логическую величину, является действительным предикатом. STL требует, чтобы при неизменности входных данных предикат всегда давал постоянный результат. Тем самым из категории предикатов исключаются функции, внутреннее состояние которых изменяется в процессе вызова.

Унарные предикаты

    Унарный предикат проверяет некоторое свойство одного аргумента. Типичный пример - функция, используемая в качестве критерия поиска первого простого числа:

//---------------------------------------------------------------------------

#include <vcl.h>
#include <iostream>
#include <list>
#include <algorithm>
#include <conio.h> //необходимо для getch()
#include <cstdlib> //для abs{)

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
using namespace std;

std::string ToRus(const std::string &in)
{
  char *buff = new char [in.length()+1];
  CharToOem(in.c_str(),buff);
  std::string out(buff);
  delete [] buff;
  return out;
}

// Предикат проверяет, является ли целое число простым 
bool isPrime (int number)
{
  // Знак числа игнорируется 
  number = abs(number);

  // 0 и 1 не являются простыми числами 
  if (number == 0 || number == 1) { 
    return false;
  }

  // Поиск множителя, на который число делятся без остатка
  int divisor;
  for (divisor = number/2; number%divisor != 0; --divisor) { ;
  }
  // Если не найдено ни одного множителя, большего 1. 
  // проверяемое число является простым. 
  return divisor == 1;
}

int main(int argc, char* argv[])
{
  list<int> coll;
  // Вставка элементов со значениями от 24 до 30 
  for (int i=24; i<=30; ++i) { 
    coll.push_back(i);
  }
  // Поиск простого числа 
  list<int>::iterator pos;
  pos = find_if (coll.begin(), coll.end(), // Интервал
    isPrime); // Предикат
  if (pos != coll.end()) {
    // Найдено простое число
    cout << *pos << ToRus(" первое простое найденное число") << endl;
  } else {
    // Простые числа не найдены
    cout << ToRus("Простых чисел нет") << endl;
  }
  cout << endl;

  getch();
  return 0;
}
//---------------------------------------------------------------------------
Текст этого примера можно взять здесь.

    В приведенном примере алгоритм find_if() ищет в заданном интервале первый элемент, для которого передаваемый унарный предикат возвращает true. В качестве предиката передается функция isPrime(), которая проверяет, является ли число простым. В итоге алгоритм возвращает первое простое число в заданном интервале. Если алгоритм не находит ни одного элемента, удовлетворяющего предикату, возвращается конец интервала (второй аргумент). Это условие проверяется после вызова. Коллекция из нашего примера содержит простое число между 24 и 30, поэтому результат выполнения программы выглядит так:


Рис.1. Результат работы приложения

    На следующем шаге мы рассмотрим бинарные предикаты.




Предыдущий шаг Содержание Следующий шаг