Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование на C / C++ / Ален И. Голуб. Правила программирования на Си и Си++ [pdf]

.pdf
Скачиваний:
138
Добавлен:
02.05.2014
Размер:
5.67 Mб
Скачать

С++ для начинающих

1102

template< class InputIterator, class Predicate > InputIterator

find_if( InputIterator first,

Алгоритм find_if()

InputIterator last, Predicate pred );

К каждому элементу из диапазона [first,last) последовательно применяется предикат pred. Если он возвращает true, поиск прекращается. find_if() возвращает итератор типа InputIterator, указывающий на найденный элемент; в противном случае возвращается last.

С++ для начинающих

1103

#include <algorithm> #include <list> #include <set> #include <string> #include <iostream.h>

//альтернатива оператору равенства

//возвращает true, если строка содержится в объекте-члене FriendSet

class OurFriends { // наши друзья public:

bool operator()( const string& str ) { return ( friendset.count( str ));

}

static void

FriendSet( const string *fs, int count ) { copy( fs, fs+count,

inserter( friendset, friendset.end() ));

}

private:

static set< string, less<string>, allocator > friendset;

};

set< string, less<string>, allocator > OurFriends::friendset;

int main()

{

string Pooh_friends[] = { "Пятачок", "Тигра", "Иа-Иа" }; string more_friends[] = { "Квазимодо", "Чип", "Пятачок" }; list<string,allocator> lf( more_friends, more_friends+3 );

// заполнить список друзей Пуха

OurFriends::FriendSet( Pooh_friends, 3 );

list<string,allocator>::iterator our_mutual_friend; our_mutual_friend =

find_if( lf.begin(), lf.end(), OurFriends());

//печатается:

//Представьте-ка, наш друг Пятачок - также друг Пуха. if ( our_mutual_friend != lf.end() )

cout << "Представьте-ка, наш друг "

<<*our_mutual_friend

<<" также друг Пуха.\n";

return 0;

}

С++ для начинающих

1104

template< class ForwardIterator1, class ForwardIterator2 > ForwardIterator1

find_end( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2 );

template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >

ForwardIterator1

find_end( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2,

Алгоритм find_end()

BinaryPredicate pred );

В последовательности, ограниченной итераторами [first1,last1), ведется поиск последнего вхождения последовательности, ограниченной парой [first2,last2). Например, если первая последовательность это Mississippi, а вторая ss, то find_end() возвращает итератор, указывающий на первую s во втором вхождении ss. Если вторая последовательность не входит в первую, то возвращается last1. В первом варианте используется оператор равенства, определенный для типа элементов контейнера, а во втором бинарный предикат, переданный пользователем.

С++ для начинающих

1105

#include <algorithm> #include <vector> #include <iostream.h> #include <assert.h>

int main()

{

int

array[ 17

]

=

{

7,3,3,7,6,5,8,7,2,1,3,7,6,3,8,4,3 };

int

subarray[

3

] =

{

3, 7, 6 };

int *found_it;

//find найти последнее вхождение последовательности 3,7,6

//в массив и вернуть адрес первого ее элемента ...

found_it = find_end( &array[0], &array[17], &subarray[0], &subarray[3] );

assert( found_it == &array[10] );

vector< int, allocator > ivec( array, array+17 ); vector< int, allocator > subvec( subarray, subarray+3 ); vector< int, allocator >::iterator found_it2;

found_it2 = find_end( ivec.begin(), ivec.end(), subvec.begin(), subvec.end(), equal_to<int>() );

assert( found_it2 == ivec.begin()+10 );

cout << "ok: find_end правильно вернула начало "

<< "последнего вхождения последовательности: 3,7,6!\n";

}

template< class ForwardIterator1, class ForwardIterator2 > ForwardIterator1

find_first_of( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2 );

template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >

ForwardIterator1

find_first_of( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2,

Алгоритм find_first_of()

BinaryPredicate pred );

Последовательность, ограниченная парой [first2,last2), содержит элементы, поиск которых ведется в последовательности, ограниченной итераторами [first1,last1). Допустим, нужно найти первую гласную в последовательности символов synesthesia. Для этого определим вторую последовательность как aeiou. find_first_of() возвращает итератор, указывающий на первое вхождение любого элемента

С++ для начинающих

1106

последовательности гласных букв, в данном случае e. Если же первая последовательность не содержит ни одного элемента из второй, то возвращается last1. В первом варианте используется оператор равенства, определенный для типа элементов

#include <algorithm> #include <vector> #include <string> #include <iostream.h>

int main()

{

string s_array[] = { "Ee", "eE", "ee", "Oo", "oo", "ee" };

// возвращает первое вхождение "ee" -- &s_array[2] string to_find[] = { "oo", "gg", "ee" };

string *found_it =

 

 

 

find_first_of( s_array, s_array+6,

 

 

 

to_find, to_find+3 );

 

 

// печатается:

 

 

 

// найдено: ee

0x7fff2dac

 

 

//

&s_array[2]:

 

 

//

&found_it:

0x7fff2dac

 

 

if ( found_it != &s_array[6] )

 

<< "\n\t"

 

cout << "найдено: "

<< *found_it

 

<< "&s_array[2]:\t" << &s_array[2]

<< "\n\t"

 

<< "&found_it:\t"

<< found_it

<< "\n\n";

vector< string, allocator > svec( s_array, s_array+6); vector< string, allocator > svec_find( to_find, to_find+2 );

// возвращает вхождение "oo" -- svec.end()-2 vector< string, allocator >::iterator found_it2;

found_it2 = find_first_of( svec.begin(), svec.end(),

svec_find.begin(), svec_find.end(), equal_to<string>() );

//печатает:

//тоже найдено: oo

//&svec.end()-2: 0x100067b0

//&found_it2: 0x100067b0

if ( found_it2 != svec.end() )

 

<< "\n\t"

cout << "тоже найдено: "

<< *found_it2

<< "&svec.end()-2:\t" <<

svec.end()-2 <<

"\n\t"

<< "&found_it2:\t"

<<

found_it2

<<

"\n";

контейнера, а во втором бинарный предикат pred.

}

Алгоритм for_each()

С++ для начинающих

1107

template< class InputIterator, class Function > Function

for_each( InputIterator first,

InputIterator last, Function func );

for_each() применяет объект-функцию func к каждому элементу в диапазоне [first,last). func не может изменять элементы, поскольку итератор записи не гарантирует поддержки присваивания. Если же модификация необходима, следует воспользоваться алгоритмом transform(). func может возвращать значение, но оно

#include <algorithm> #include <vector> #include <iostream.h>

template <class Type>

void print_elements( Type elem ) { cout << elem << " "; }

int main()

{

vector< int, allocator > ivec;

for ( int ix = 0; ix < 10; ix++ ) ivec.push_back( ix );

void (*pfi)( int ) = print_elements; for_each( ivec.begin(), ivec.end(), pfi );

return 0;

игнорируется.

}

template< class ForwardIterator, class Generator > void

generate( ForwardIterator first,

Алгоритм generate()

ForwardIterator last, Generator gen );

generate() заполняет диапазон, ограниченный парой итераторов [first,last), путем последовательного вызова gen, который может быть объектом-функцией или указателем на функцию.

С++ для начинающих

1108

#include <algorithm> #include <list> #include <iostream.h>

int odd_by_twos() {

static int seed = -1; return seed += 2;

}

template <class Type>

void print_elements( Type elem ) { cout << elem << " "; }

int main()

{

list< int, allocator > ilist( 10 ); void (*pfi)( int ) = print_elements;

generate( ilist.begin(), ilist.end(), odd_by_twos );

//печатается:

//элементы в списке, первый вызов:

//1 3 5 7 9 11 13 15 17 19

cout << "элементы в списке, первый вызов:\n"; for_each( ilist.begin(), ilist.end(), pfi ); generate( ilist.begin(), ilist.end(), odd_by_twos );

//печатается:

//элементы в списке, второй вызов:

//21 23 25 27 29 31 33 35 37 39

cout << "\n\nэлементы в списке, второй вызов:\n"; for_each( ilist.begin(), ilist.end(), pfi );

return 0;

}

template< class OutputIterator,

class Size, class Generator >

void

Алгоритм generate_n()

generate_n( OutputIterator first, Size n, Generator gen );

generate_n() заполняет последовательность, начиная с first, n раз вызывая gen, который может быть объектом-функцией или указателем на функцию.

С++ для начинающих

1109

#include <algorithm> #include <iostream.h> #include <list>

class even_by_twos { public:

even_by_twos( int seed = 0 ) : _seed( seed ){} int operator()() { return _seed += 2; }

private:

int _seed;

};

template <class Type>

void print_elements( Type elem ) { cout << elem << " "; }

int main()

{

list< int, allocator > ilist( 10 ); void (*pfi)( int ) = print_elements;

generate_n( ilist.begin(), ilist.size(), even_by_twos() );

//печатается:

//generate_n с even_by_twos():

//2 4 6 8 10 12 14 16 18 20

cout << "generate_n с even_by_twos():\n";

for_each( ilist.begin(), ilist.end(), pfi ); cout << "\n"; generate_n( ilist.begin(), ilist.size(), even_by_twos( 100 ) );

//печатается:

//generate_n с even_by_twos( 100 ):

//102 104 106 108 110 112 114 116 118 120

cout << "generate_n с even_by_twos( 100 ):\n"; for_each( ilist.begin(), ilist.end(), pfi );

}

template< class InputIterator1, class InputIterator2 > bool

includes( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2 );

template< class InputIterator1, class InputIterator2, class Compare >

bool

includes( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,

Алгоритм includes()

Compare comp );

includes() проверяет, каждый ли элемент последовательности [first1,last1) входит в последовательность [first2,last2). Первый вариант предполагает, что

С++ для начинающих

1110

последовательности отсортированы в порядке, определяемом оператором меньше”;

#include <algorithm> #include <vector> #include <iostream.h>

int main()

{

int ia1[] = { 13, 1, 21, 2, 0, 34, 5, 1, 8, 3, 21, 34 }; int ia2[] = { 21, 2, 8, 3, 5, 1 };

// алгоритму includes следует передавать отсортированные контейнеры

sort( ia1, ia1+12 ); sort( ia2, ia2+6 );

// печатает: каждый элемент ia2 входит в ia1? Да

bool res = includes( ia1, ia1+12, ia2, ia2+6 ); cout << "каждый элемент ia2 входит в ia1? "

<< (res ? "Да" : "Нет") << endl;

vector< int, allocator > ivect1( ia1, ia1+12 ); vector< int, allocator > ivect2( ia2, ia2+6 );

// отсортирован в порядке убывания

sort( ivect1.begin(), ivect1.end(), greater<int>() ); sort( ivect2.begin(), ivect2.end(), greater<int>() );

res = includes( ivect1.begin(), ivect1.end(), ivect2.begin(), ivect2.end(), greater<int>() );

// печатает: каждый элемент ivect2 входит в ivect1? Да

cout << "каждый элемент ivect2 входит в ivect1? " << (res ? "Да" : "Нет") << endl;

второй что порядок задается параметром-типом comp.

}

Алгоритм inner_product()

С++ для начинающих

1111

template< class InputIterator1, class InputIterator2 class Type >

Type inner_product(

InputIterator1 first1, InputIterator1 last, InputIterator2 first2, Type init );

template< class InputIterator1, class InputIterator2 class Type,

class BinaryOperation1, class BinaryOperation2 >

Type inner_product(

InputIterator1 first1, InputIterator1 last, InputIterator2 first2, Type init,

BinaryOperation1 op1, BinaryOperation2 op2 );

Первый вариант суммирует произведения соответственных членов обеих последовательностей и прибавляет результат к начальному значению init. Первая последовательность ограничена итераторами [first1,last1), вторая начинается с first2 и обходится синхронно с первой. Например, если даны последовательности {2,3,5,8} и {1,2,3,4}, то результат вычисляется следующим образом:

2*1 + 3*2 + 5*3 + 8*4

Если начальное значение равно 0, алгоритм вернет 55.

Во втором варианте вместо сложения используется бинарная операция op1, а вместо умножения бинарная операция op1. Например, если для приведенных выше последовательностей применить вычитание в качестве op1 и сложение в качестве op2, то результат будет вычисляться так:

(2+1) - (3+2) - (5+3) - (8+4)

inner_product() это один из численных алгоритмов. Для его использования в программу необходимо включить заголовочный файл <numeric>.