Выбрать главу

vector int vec0;

const vector int vec1;

vector int ::reverse_iterator r_iter0 = vec0.rbegin();

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 для работы с потоком вывода в файл. Для использования любого из этих итераторов следует включить заголовочный файл

#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;

vectorint vec;

copy ( input, end_of_stream, inserter( vec, vec.begin() ));

sort( vec.begin(), vec.end(), greaterint() );

ostream_iterator int output( cout, " " );

unique_copy( vec.begin(), vec.end(), output );

}

unique_copy():

12.4.4. Итератор istream_iterator

В общем виде объявление потокового итератора чтения istream_iterator имеет форму

istream_iterator identifier( istream& );1.

Если имеющийся у Вас компилятор пока не поддерживает параметр шаблонов по умолчанию, то конструктору istream_iterator необходимо будет явно передать также и второй аргумент: тип difference_type, способный хранить результат вычитания двух итераторов контейнера, куда помещаются элементы. Например, в разделе 12.2 при изучении программы, которая должна транслироваться компилятором, не поддерживающим параметры шаблонов по умолчанию, мы писали:

typedef vector::difference_type diff_type

istream_iterator input_set1( infile1 ), eos;

istream_iterator input_set2( infile2 );

где Type – это любой встроенный или пользовательский тип класса, для которого определен оператор ввода. Аргументом конструктора может быть объект либо класса

#include iterator

#include fstream

#include string

#include complex

// прочитать последовательность объектов типа complex

// из стандартного ввода

istream_iterator complex is_complex( cin );

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

ifstream infile( "C++Primer" );

istream, например cin, либо производного от него класса с открытым типом наследования – ifstream:

istream_iterator string is_string( infile );

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