Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
STL_2.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
512.51 Кб
Скачать

4.1. Входные итераторы

Определение категорий итераторов STL связано с рассмотрением требований конкретных алгоритмов. Как было сказано в главе 2, "Обзор компонентов STL", обобщенный алгоритм STL find может использоваться для поиска значений во множестве структур данных, включая массивы, векторы и списки. Он может использоваться даже для сканирования входного потока при помощи специальных итераторов, именуемых итераторами входных потоков, которые будут рассмотрены позже в данной главе. Алгоритм find имеет простое определение как шаблон функции:

template <typename InputIterator, typename T>

Inputlterator find(Inputlterator first,

Inputlterator last,

const T& value)

{

while (first != last && *first != value)

++first;

return first;

}

Вот выражения в коде, в которых участвуют объекты Inputlterator:

• first != last

• ++first

• *first

Чтобы алгоритм find работал корректно, эти выражения должны быть определены и иметь следующий смысл:

• выражение first != last должно возвращать true, если first не равно last,

в противном случае оно должно возвращать false;

• ++first должно выполнять инкремент first и возвращать новое значение итератора;

• *first должно возвращать значение, на которое указывает first.

Кроме того, чтобы алгоритм find работал эффективно, каждая из этих операций должна выполняться за константное время.

Эти требования почти в точности совпадают с требованиями, налагаемыми определением категории входных итераторов. Основные дополнительные требования, налагаемые определением категории: чтобы был определен оператор ==, выполняющий проверку на равенство, и чтобы был также определен постфиксный оператор ++ с тем же действием, что и префиксный оператор ++, но возвращающий значение итератора до увеличения (как и в случае встроенных типов указателей).

Этим требованиям, само собой, отвечают встроенные типы указателей. Заметим, однако, что встроенные типы указателей обладают рядом других свойств, которые определение входных итераторов не требует. В частности, от входных итераторов не требуется поддержка записи в указанную позицию при помощи выражения * first = .... Конкретный входной итератор, конечно, может поддерживать данную операцию, но она не является необходимой. (Как вы увидите в следующем разделе, к выходным итераторам предъявляется противоположное требование: они должны обеспечивать возможность записи посредством оператора operator*, но не обязаны обеспечивать чтение.)

Заметим, что термин "входной итератор" не означает тип. Он указывает семейство типов, каждый из которых удовлетворяет описанным ранее базовым требованиям. Чтобы убедиться, что требованиям ко входным итераторам удовлетворяют одновременно несколько разных типов, рассмотрим следующий пример.

В первой части этой программы мы применяем алгоритм find с обычными указателями, которые ведут себя как массивы C++. Во второй части find используется с итераторами списка, которые также удовлетворяют поставленным требованиям. Наконец, STL предоставляет специальные входные итераторы, которые называются итераторами istream и которые используются для чтения значений из входного потока. В последней части программы выполняется чтение из стандартного входного потока сin до тех пор, пока в нем не будет найден символ х или пока не будет достигнут конец потока. Затем выполняется инкремент

итератора для получения очередного непробельного символа и его вывод.

Пример 4.1. Демонстрация обобщенного алгоритма find со входными

итераторами массивов, списков и входных потоков

#include <iostream>

#include <cassert>

#include <algorithm>

#include <list>

#include <iterator>

using namespace std;

int main()

{

// Инициализация массива 10 целыми числами:

int a[10] = {12, 3, 25, 7, 11, 213, 7, 123, 29, -3l};

// Поиск в массиве первого элемента, равного 7:

int* ptr = find(&a[0], &a[10], 7);

assert (*ptr == 7 && *(ptr+1) == 11);

// Инициализация списка теми же числами, что и массива:

list<int> list1(&a[0], &a[10]);

// Поиск в списке первого элемента, равного 7:

list<int>::iterator i = find(list1.begin(), list1.end() ,7) ;

assert (*i == 7 && *(++i) == 11);

cout << "Введите некоторые символы, включая ‘x',\n"

<< "за которым следует как минимум один\n"

<< "непробельный символ: " << flush;

istream_iterator<char> in(cin);

istream_iterator<char> eos;

find(in, eos, 'x');

cout << "Первый непробельный символ, следующий за\n"

<< "первым 'х1 - ' “ << *(++in) << “ ‘.” << endl;

}

В случае итераторов массива и списка поддерживаются и другие операции, такие как сохранение значений в позиции, указываемой итератором. Однако в случае итераторов istream единственными поддерживаемыми операциями являются операции входных итераторов. Более подробно входные итераторы рассматриваются в разделе 4.8.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]