, указывающего на начало потокового ввода. Это делается вот так.
istream_iterator<string> start(cin);
В результате создается итератор с именем
start
, который указывает на первый элемент входной последовательности, точно так же, как
vec.begin
(
vec
— это
vector
) возвращает итератор, который указывает на первый элемент в векторе. Аргумент шаблона
string
говорит
istream_iterator
, что элементы в этой последовательности имеют тип
string
. Аргумент конструктора
cin
— это входной поток, из которого производится чтение. Однако это абстракция, так как первого элемента не существует, поскольку из
cin
еще ничего прочитано не было. Это произойдет несколько позже.
Вторая часть итератора входного потока — это маркер конца, который создается вот так.
istream_iterator<string> end;
Стандартные контейнеры используют специальное значение «один после конца», указывающее на точку, где должно остановиться использование алгоритма. Так как итератор входного потока не имеет в памяти последнего элемента, он для создания логической конечной точки, представляющей точку остановки использования алгоритма, использует конструктор без аргументов.
Последней частью методики использования
istream_iterator
является его использование для извлечения значений. Удобным способом вытащить в контейнер все значения, введенные в поток, является использование конструктора диапазона контейнера. Например, если создать
vector
с двумя итераторами, то его конструктор скопирует в контейнер все элементы диапазона, определяемого итераторами. Если передать только что созданные итераторы
start
и
end
, то это будет выглядеть так.
vector<string> v(start, end);
Именно здесь происходит чтение значений из потока. При создании
v
он начинает со
start
и перебирает все значения, пока не достигнет
end
. Каждый раз, когда
v
читает из
*start
, происходит нечто эквивалентное такому вызову
cin
.
cin >> v[i]; // v - это vector<string>
Другими словами, следующее значение, извлекаемое из
cin
, преобразуется в
string
и вставляется в
vector
.
При использовании
cin
как входного потока маркер конца файла, который отмечает конец потока, определяется используемой платформой. В Windows для завершения входного потока требуется нажать на Enter, Ctrl-Z, Enter. Чтобы увидеть, что требуется сделать на вашей платформе, проведите эксперименты, но велика вероятность, что будут использоваться эти же клавиши.
Итераторы выходных потоков ведут себя аналогично итераторам потоков ввода. В примере 7.11 я копирую значения из своего
говорит, что записываемые элементы будут иметь тип
string
. Первый аргумент конструктора
ostream_iterator
— это поток, в который будет производиться запись (и который может быть любым потоком вывода, включая
ofstream
и
ostringstream
), а второй это используемый разделитель. Это дает удобный способ выводить диапазон значений на стандартный вывод, что я часто делаю при отладке.
Если требуется дополнительное управление внешним видом вывода, например вывод последовательности в квадратных или фигурных скобках или отсутствие последнего разделителя в конце последовательности, то это потребует всего нескольких дополнительных строк кода. Пример 7.12 показывает тело
printContainer
и
printRange
, первая из которых используется в примерах этой главы.