Программирование >>  Разработка устойчивых систем 

1 ... 76 77 78 [ 79 ] 80 81 82 ... 196


Или объекта, который может вызываться как функция. Об этом речь пойдет далее.

Функция back inserter() определяется в заголовочном файле <iterator>. О том, как работают итераторы, будет подробно рассказано далее в этой главе.

Поскольку итераторы имеют много общего с указателями, алгоритмы стандартной библиотеки записываются так, чтобы в их аргументах могли передаваться как указатели, так и итераторы. Из-за этого реализация сору() больше похожа на следующий фрагмент:

tempiate<typename Iterator>

void copydterator begin. Iterator end. Iterator dest) { while (begin != end) *begin++ = *dest++:

Какой бы тип аргумента не использовался при вызове, алгоритм сору() предполагает, что он правильно реализует операторы * и ++. Если это условие не выполняется, происходит ошибка компиляции.

Предикаты

Еще одна распространенная задача - копирование точно определенного подмножества одного интервала (например, элементов, удовлетворяющих некоторому условию) в другой интервал. Для этого во многих алгоритмах предусмотрены альтернативные варианты вызова с возможностью передачи предиката (то есть обычной функции, возвращающей логическое значение по некоторому критерию). Допустим, вы хотите выделить в интервале целых чисел только те числа, которые меньше либо равны 15. Задача легко решается разновидностью алгоритма сору(), которая называется remove copy if(): : C06:CopyInts2.cpp

При копировании пропускаются числа, соответствующие предикату linclude <algorithm> linclude <cstddef> linclude <iostream> using namespace std:

Предикат определяется пользователем bool gtl5(int x) { return 15 < x: }

int mainO { int a[] = {10. 20. 30}: const size t SIZE = sizeof a / sizeof a[0]; int b[SIZE]:

int* endb = remove copyJf(a. a+SIZE. b. gtl5): int* beginb = b: while (beginb != endb) cout *beginb++ endl; Выводит только 10 } /:-

Шаблон функции remove copy if() получает стандартную пару указателей, определяющих границы интервала, за которыми следует предикат по выбору пользователя. Предикат передается в виде указателя на функцию. Эта функция получает один аргумент, тип которого соответствует типу элементов интервала, и возвра-



щает bool. В нашем примере функция gtl5 возврашает true, если ее аргумент больше 15. Алгоритм remove copy if() применяет gtl5() к каждому элементу исходного интервала и игнорирует элементы, для которых предикат возвращает true, при записи в приемный (выходной) интервал.

Следующая программа демонстрирует другую разновидность алгоритма сору:

: C06:CopyStrings2.cpp

Замена строк, соответствующих предикату

linclude <algorithm>

linclude <cstddef>

linclude <iostream>

linclude <string>

using namespace std:

Предикат

bool contains e(const strings s) { return s.findCe) != string: :npos:

int mainO { string a[] = { read , my , lips }: const size t SIZE = sizeof a / sizeof a[0]; string b[SIZE]:

string* endb = replace copy if(a. a + SIZE. b.

contains e. string( kiss )): string* beginb = b: while (beginb != endb) cout *beginb++ endl: } III:-

При заполнении выходного интервала алгоритм replace copyJf() заменяет элементы, не соответствующие заданному критерию, фиксированными значениями. Поскольку исходная строка read (единственный элемент, содержащий букву е ) заменяется словом kiss согласно последнему аргументу replace copyJf(), результат выглядит так:

kiss

lips

Алгоритм replace if() изменяет исходный интервал на месте вместо того, чтобы записывать его в отдельный выходной интервал:

: СОб:ReplaceStrings.срр Замена строк на месте linclude <algorithm> linclude <cstddef> linclude <iostream> linclude <string> using namespace std:

bool contains e(const strings s) { return S.findCe ) != string: :npos:

int mainO { string a[] = { read , my , lips }: const size t SIZE = sizeof a / sizeof a[0]: replace if(a. a + SIZE. contains e. string( kiss )):



string* р = а: while (р != а + SIZE) cout *р++ endl: } III-

Потоковые итераторы

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

На помощь приходят потоковые итераторы, которые в качестве исходного или приемного интервала используют потоки ввода-вывода. Например, чтобы задействовать потоковый итератор для исключения цикла вывода из программы CopyInt2.cpp, можно поступить так:

: С06:СоруInts3.срр

Использование потокового итератора при выводе

linclude <algorithm>

linclude <cstclclef>

linclude <iostream>

linclude <iterator>

using namespace std:

bool gtl5(int x) { return 15 < x; }

int mainO { int a[] = {10. 20. 30}: const size t SIZE = sizeof a / sizeof a[0]: remove copy 1f(a. a + SIZE.

ostream iterator<int>(cout. \n ). gtl5):

} III-

B этом примере приемный интервал b в третьем аргументе алгоритма remove copy if() заменяется потоковым итератором вывода. Он представляет собой специализацию шаблона класса ostream Jterator, объявленного в заголовочном файле <iterator>. Этот конкретный экземпляр ostreamjterator связывается со стандартным потоком вывода cout. Каждый раз, когда remove copyJf() выдает в cout целое число из интервала а через этот итератор, последний записывает в cout целое число и строку-разделитель, переданную во втором аргументе (в нашем примере это символ перевода строки).

Так же просто данные можно записать в файл; для этого вместо cout передается файловый поток вывода:

: C06:CopyIntsToFile.cpp

Использование потокового итератора вывода с файлом

linclude <algorithm>

linclude <cstddef>

linclude <fstream>

linclude <iterator>

using namespace std:

bool gtl5(int X) {



1 ... 76 77 78 [ 79 ] 80 81 82 ... 196

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика