|
Программирование >> Разработка устойчивых систем
Или объекта, который может вызываться как функция. Об этом речь пойдет далее. Функция 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) {
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |