Программирование на C / C++ / Ален И. Голуб. Правила программирования на Си и Си++ [pdf]
.pdf
С++ для начинающих |
1082 |
template < class InputIterator, class Type > Type accumulate(
InputIterator first, InputIterator last, Type init );
template < class InputIterator, class Type, class BinaryOperation >
Type accumulate(
InputIterator first, InputIterator last,
Type init, BinaryOperation op );
Первый вариант accumulate() вычисляет сумму значений элементов последовательности из диапазона, ограниченного парой итераторов [first,last), с начальным значением, которое задано параметром init. Например, если дана последовательность {1,1,2,3,5,8} и начальное значение 0, то результатом работы алгоритма будет 20. Во втором варианте вместо оператора сложения к элементам применяется переданная бинарная операция. Если бы мы передали алгоритму accumulate() объект-функцию times<int> и начальное значение 1, то получили бы результат 240. accumulate() – это один из численных алгоритмов; для его
#include <numeric> #include <list> #include <functional> #include <iostream.h>
/*
*выход:
*accumulate()
*работает с последовательностью {1,2,3,4}
*результат для сложения по умолчанию: 10
*результат для объекта-функции plus<int>: 10
*/
int main()
{
int ia[] = { 1, 2, 3, 4 }; list<int,allocator> ilist( ia, ia+4 );
int ia_result = accumulate(&ia[0], &ia[4], 0); int ilist_res = accumulate(
ilist.begin(), ilist.end(), 0, plus<int>() );
cout << "accumulate()\n\t"
<<"работает с последовательностью {1,2,3,4}\n\t"
<<"результат для сложения по умолчанию: "
<<ia_result << "\n\t"
<<"результат для объекта-функции plus<int>: "
<<ilist_res
<<endl;
return 0;
использования в программу необходимо включить заголовочный файл <numeric>.
}
С++ для начинающих |
1083 |
template < class InputIterator, class OutputIterator > OutputIterator adjacent_difference(
InputIterator first, InputIterator last, OutputIterator result );
template < class InputIterator, class OutputIterator > class BinaryOperation >
OutputIterator adjacent_difference( InputIterator first, InputIterator last,
Алгоритм adjacent_difference()
OutputIterator result, BinaryOperation op );
Первый вариант adjacent_difference() создает новую последовательность, в которой значение каждого элемента, кроме первого, равно разности между текущим и предыдущим элементами исходной последовательности. Например, если дано {0,1,1,2,3,5,8}, то первым элементом новой последовательности будет копия: 0. Вторым – разность первых двух элементов исходной последовательности: 1. Третий элемент равен разности третьего и второго элементов: 1-1=0, и т.д. В результате мы получим последовательность {0,1,0,1,1,2,3}.
Во втором варианте разность соседних элементов вычисляется с помощью указанной бинарной операции. Возьмем ту же исходную последовательность и передадим объект- функцию times<int>. Как и раньше, первый элемент просто копируется. Второй элемент – это произведение первого и второго элементов исходной последовательности; он тоже равен 0. Третий элемент – произведение второго и третьего элементов исходной последовательности: 1 * 1 = 1, и т.д. Результат – {0,1,2,6,15,40}.
В обоих вариантах итератор OutputIterator указывает на элемент, расположенный за последним элементом новой последовательности. adjacent_difference() – это один из численных алгоритмов, для его использования в программу необходимо включить заголовочный файл <numeric>.
С++ для начинающих |
1084 |
#include <numeric> #include <list> #include <functional> #include <iterator> #include <iostream.h>
int main()
{
int ia[] = { 1, 1, 2, 3, 5, 8 };
list<int,allocator> ilist(ia, ia+6); list<int,allocator> ilist_result(ilist.size());
adjacent_difference(ilist.begin(), ilist.end(), ilist_result.begin() );
//на выходе печатается:
//1 0 1 1 2 3
copy( ilist_result.begin(), ilist_result.end(), ostream_iterator<int>(cout," "));
cout << endl;
adjacent_difference(ilist.begin(), ilist.end(), ilist_result.begin(), times<int>() );
//на выходе печатается:
//1 1 2 6 15 40
copy( ilist_result.begin(), ilist_result.end(), ostream_iterator<int>(cout," "));
cout << endl;
}
template < class ForwardIterator > ForwardIterator
adjacent_find( ForwardIterator first, ForwardIterator last );
template < class ForwardIterator, class BinaryPredicate > ForwardIterator
adjacent_find( ForwardIterator first,
Алгоритм adjacent_find()
ForwardIterator last, Predicate pred );
adjacent_find() ищет первую пару одинаковых соседних элементов в диапазоне, ограниченном итераторами [first,last). Если соседние дубликаты найдены, то алгоритм возвращает однонаправленный итератор, указывающий на первый элемент пары, в противном случае возвращается last. Например, если дана последовательность {0,1,1,2,2,4}, то будет найдена пара [1,1] и возвращен итератор, указывающий на первую единицу.
С++ для начинающих |
1085 |
#include <algorithm> #include <vector> #include <iostream.h> #include <assert.h>
class TwiceOver { public:
bool operator() ( int val1, int val2 )
{ return val1 == val2/2 ? true : false; }
};
int main()
{
int ia[] = { 1, 4, 4, 8 };
vector< int, allocator > vec( ia, ia+4 );
int *piter;
vector< int, allocator >::iterator iter;
// piter указывает на ia[1]
piter = adjacent_find( ia, ia+4 ); assert( *piter == ia[ 1 ] );
// iter указывает на vec[2]
iter = adjacent_find( vec.begin(), vec.end(), TwiceOver() ); assert( *iter == vec[ 2 ] );
// пришли сюда: все хорошо
cout << "ok: adjacent-find() завершился успешно!\n"; return 0;
}
template < class ForwardIterator, class Type > bool
binary_search( ForwardIterator first,
ForwardIterator last, const Type &value );
template < class ForwardIterator, class Type > bool
binary_search( ForwardIterator first,
ForwardIterator last, const Type &value,
Алгоритм binary_search()
Compare comp );
binary_search() ищет значение value в отсортированной последовательности, ограниченной парой итераторов [first,last). Если это значение найдено, возвращается true, иначе – false. В первом варианте предполагается, что контейнер отсортирован с помощью оператора “меньше”. Во втором варианте порядок определяется указанным объектом-функцией.
С++ для начинающих |
1086 |
#include <algorithm> #include <vector> #include <assert.h>
int main()
{
int ia[] = {29,23,20,22,17,15,26,51,19,12,35,40}; vector< int, allocator > vec( ia, ia+12 );
sort( &ia[0], &ia[12] );
bool found_it = binary_search( &ia[0], &ia[12], 18 ); assert( found_it == false );
vector< int > vec( ia, ia+12 );
sort( vec.begin(), vec.end(), greater<int>() ); found_it = binary_search( vec.begin(), vec.end(),
26, greater<int>() ); assert( found_it == true );
}
template < class InputIterator, class OutputIterator > OutputIterator
copy( InputIterator first1, InputIterator last,
Алгоритм copy()
OutputIterator first2 )
copy() копирует последовательность элементов, ограниченную парой итераторов [first,last), в другой контейнер, начиная с позиции, на которую указывает first2. Алгоритм возвращает итератор, указывающий на элемент второго контейнера, следующий за последним вставленным. Например, если дана последовательность
int ia[] = {0, 1, 2, 3, 4, 5 };
// сдвинуть элементы влево на один, получится {1,2,3,4,5,5}
{0,1,2,3,4,5}, мы можем сдвинуть элементы на один влево с помощью такого вызова: copy( ia+1, ia+6, ia );
copy() начинает копирование со второго элемента ia, копируя 1 в первую позицию, и так далее, пока каждый элемент не окажется в позиции на одну левее исходной.
С++ для начинающих |
1087 |
#include |
<algorithm> |
#include |
<vector> |
#include |
<iterator> |
#include <iostream.h> |
|
/* печатается: |
|
0 1 1 |
3 5 8 13 |
сдвиг |
массива влево на 1: |
1 1 3 |
5 8 13 13 |
сдвиг |
вектора влево на 2: |
1 3 5 |
8 13 8 13 |
*/ |
|
int main()
{
int ia[] = { 0, 1, 1, 3, 5, 8, 13 }; vector< int, allocator > vec( ia, ia+7 );
ostream_iterator< int > ofile( cout, " " );
cout << "исходная последовательность элементов:\n"; copy( vec.begin(), vec.end(), ofile ); cout << '\n';
// сдвиг влево на один элемент copy( ia+1, ia+7, ia );
cout << "сдвиг массива влево на 1:\n"; copy( ia, ia+7, ofile ); cout << '\n';
// сдвиг влево на два элемента
copy( vec.begin()+2, vec.end(), vec.begin() );
cout << "сдвиг вектора влево на 2:\n";
copy( vec.begin(), vec.end(), ofile ); cout << '\n';
}
template < class BidirectionalIterator1, class BidirectionalIterator2 >
BidirectionalIterator2
copy_backward( BidirectionalIterator1 first, BidirectionalIterator1 last1,
Алгоритм copy_backward()
BidirectionalIterator2 last2 )
copy_backward() ведет себя так же, как copy(), только элементы копируются в обратном порядке: копирование начинается с last1-1 и продолжается до first. Кроме того, элементы помещаются в целевой контейнер с конца, от позиции last2-1, пока не будет скопировано last1-first элементов.
Например, если дана последовательность {0,1,2,3,4,5}, мы можем скопировать последние три элемента (3,4,5) на место первых трех (0,1,2), установив first равным адресу значения 0, last1 – адресу значения 3, а last2 – адресу значения 5. Тогда
С++ для начинающих |
1088 |
||
элемент 5 попадает на место элемента 2, элемент 4 – на место 1, а элемент 3 – на место |
|
||
|
|
#include <algorithm> |
|
|
|
|
|
|
|
#include <vector> |
|
|
|
#include <iterator> |
|
|
|
#include <iostream.h> |
|
|
|
class print_elements { |
|
|
|
public: |
|
|
|
void operator()( string elem ) { |
|
|
|
cout << elem |
|
|
|
<< ( _line_cnt++%8 ? " " : "\n\t" ); |
|
|
|
} |
|
|
|
static void reset_line_cnt() { _line_cnt = 1; } |
|
|
|
private: |
|
|
|
static int _line_cnt; |
|
|
|
}; |
|
|
|
int print_elements::_line_cnt = 1; |
|
|
|
/* печатается: |
|
|
|
исходный список строк: |
|
|
|
The light untonsured hair grained and hued like |
|
|
|
pale oak |
|
|
|
после copy_backward( begin+1, end-3, end ): |
|
|
|
The light untonsured hair light untonsured hair grained |
|
|
|
and hued |
|
|
|
*/ |
|
|
|
int main() |
|
|
|
{ |
|
|
|
string sa[] = { |
|
|
|
"The", "light", "untonsured", "hair", |
|
|
|
"grained", "and", "hued", "like", "pale", "oak" }; |
|
|
|
vector< string, allocator > svec( sa, sa+10 ); |
|
|
|
cout << "исходный список строк:\n\t"; |
|
|
|
for_each( svec.begin(), svec.end(), print_elements() ); |
|
|
|
cout << "\n\n"; |
|
|
|
copy_backward( svec.begin()+1, svec.end()-3, svec.end() ); |
|
|
|
print_elements::reset_line_cnt(); |
|
|
|
cout << "после copy_backward( begin+1, end-3, end ):\n"; |
|
|
|
for_each( svec.begin(), svec.end(), print_elements() ); |
|
|
|
cout << "\n"; |
|
0. В результате получим последовательность {3,4,5,3,4,5}. |
|
||
|
|
} |
|
|
|
||
|
|
|
|
Алгоритм count()
С++ для начинающих |
1089 |
template < class InputIterator, class Type > iterator_traits<InputIterator>::distance_type count( InputIterator first,
InputIterator last, const Type& value );
count() сравнивает каждый элемент со значением value в диапазоне, ограниченном парой итераторов [first,last), с помощью оператора равенства. Алгоритм возвращает число элементов, равных value. (Отметим, что в имеющейся у нас
реализации стандартной библиотеки поддерживается более ранняя спецификация count().)
С++ для начинающих |
1091 |
}
template < class InputIterator, class Predicate > iterator_traits<InputIterator>::distance_type count_if( InputIterator first,
Алгоритм count_if()
InputIterator last, Predicate pred );
count_if() применяет предикат pred к каждому элементу из диапазона, ограниченного парой итераторов [first,last). Алгоритм сообщает, сколько раз предикат оказался равным true.
