|
Программирование >> Инициализация объектов класса, структура
правильно: теперь unie copy() вставляет элементы с помощью vres.push back()... unique copy( ivec.begin(), ivec.end(), является сам контейнер. Например, вызов unique copy() можно исправить, написав: back inserter( vres ) ); front inserter() вызывает определенную для контейнера операцию вставки push front() вместо оператора присваивания. Аргументом front inserter() тоже является сам контейнер. Заметьте, однако, что класс vector не поддерживает увы, ошибка: класс vector не поддерживает операцию push front() следует использовать контейнеры dee list unique copy( ivec.begin(), ivec.end(), push front() , так что использовать такой адаптер для вектора нельзя: front inserter( vres ) ); inserter() вызывает определенную для контейнера операцию вставки insert() вместо оператора присваивания. inserter() принимает два аргумента: сам unique copy( ivec.begin(), ivec.end(), контейнер и итератор, указывающий позицию, с которой должна начаться вставка: inserter( vres ), vres.begin() ); Итератор, указывающий на позицию начала вставки, сдвигается вперед после каждой вставки, так что элементы располагаются в нужном порядке, как если бы мы vector< int >::iterator iter = vres.begin(), iter2 = ivec.begin(); for ( ; iter2 != ivec.end() ++ iter, ++iter2 ) написали: vres.insert( iter, *iter2 ); Проблема вызвана тем, что алгоритм unique copy() использует присваивание для копирования значения каждого элемента из вектора ivec, но эта операция завершится неудачно, поскольку в vres не выделено место для хранения девяти целых чисел. Можно было бы написать две версии алгоритма unique copy(): одна присваивает элементы, а вторая вставляет их. Эта последняя версия должна, в таком случае, поддерживать вставку в начало, в конец или в произвольное место контейнера. Альтернативный подход, принятый в стандартной библиотеке, заключается в определении трех адаптеров, которые возвращают специальные итераторы вставки: back inserter() вызывает определенную для контейнера операцию вставки push back() вместо оператора присваивания. Аргументом back inserter() vector< int > const vector< vec0; vector< int >::reverse iterator r iter0 = vec0.rbegin(); rend() . Есть константные и неконстантные версии обратных итераторов: vector< int >::const reverse iterator r iter1 = vec1.rbegin(); Обратный итератор применяется так же, как прямой. Разница состоит в реализации операторов перехода к следующему и предыдущему элементам. Для прямого итератора оператор ++ дает доступ к следующему элементу контейнера, тогда как для обратного - к обратн итератор обходит вектор от конца к началу vector< type >::reverse iterator r iter; for ( r iter = vec0.rbegin(); r iter указает на последний элемент r iter != vec0.rend(); пока не достиг элемента перед перв r iter++ ) переходим к предгдущему элементу предыдущему. Например, для обхода вектора в обратном направлении следует написать: { /* ... */ } Инвертирование семантики операторов инкремента и декремента может внести путаницу, но зато позволяет программисту передавать алгоритму пару обратных итераторов вместо прямых. Так, для сортировки вектора в порядке убывания мы передаем алгоритму сортирует вектор в порядке возрастания sort( vec0.begin(), vec0.end() ); сортирует вектор в порядке убания sort() пару обратных итераторов: sort( vec0.rbegin(), vec0.rend() ); 12.4.3. Потоковые итераторы Стандартная библиотека предоставляет средства для работы потоковых итераторов чтения и записи совместно со стандартными контейнерами и обобщенными алгоритмами. Класс istream iterator поддерживает итераторные операции с классом istream или одним из производных от него, например ifstream для работы с потоком ввода из файла. Аналогично ostream iterator поддерживает итераторные операции с классом ostream или одним из производных от него, например ofstream для работы с потоком вывода в файл. Для использования любого из этих итераторов следует включить заголовочный файл 12.4.2. Обратные итераторы Операции begin() и end() возвращают соответственно итераторы, указывающие на первый элемент и на элемент, расположенный за последним. Можно также вернуть обратный итератор, обходящий контейнер от последнего элемента к первому. Во всех контейнерах для поддержки такой возможности используются операции rbegin() и #include <iterator> В следующей программе мы пользуемся потоковым итератором чтения для получения из стандартного ввода последовательности целых чисел в вектор, а затем применяем потоковый итератор записи в качестве целевого в обобщенном алгоритме #include <iostream> #include <iterator> #include <algorithm> #include <vector> #include <functional> * вход: * 23 109 45 89 6 34 12 90 34 23 56 23 8 89 23 * 109 90 89 56 45 34 23 12 8 6 int main() istream iterator< int > input( cin ); istream iterator< int > end of stream; vector<int> vec; copy ( input, end of stream, inserter( vec, vec.begin() )); sort( vec.begin(), vec.end(), greater<int>() ); ostream iterator< int > output( cout, ); unique copy( vec.begin(), vec.end(), output ); unique copy() : 12.4.4. Итератор istream iterator В общем виде объявление потокового итератора чтения istream iterator имеет форму: istream iterator<Type> identifier( istream& Примечание [O.A.3]: Нумера ция сносок сбита. 1. Если имеющийся у Вас компилятор пока не поддерживает параметр шаблонов по умолчанию, то конструктору istream iterator необходимо будет явно передать также и второй аргумент: тип difference type, способный хранить результат вычитания двух итераторов контейнера, куда помещаются элементы. Например, в разделе 12.2 при изучении программы, которая должна транслироваться компилятором, не поддерживающим параметры шаблонов по умолчанию, мы писали: typedef vector<string,allocator>::difference type diff type istream iterator< string, diff type > input set1( infile1 ), eos; istream iterator< string, diff type > input set2( infile2 );
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |