Программирование на C / C++ / Ален И. Голуб. Правила программирования на Си и Си++ [pdf]
.pdfС++ для начинающих |
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.
С++ для начинающих |
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>.