Стандартные контейнеры используют специальное значение «один после конца», указывающее на точку, где должно остановиться использование алгоритма. Так как итератор входного потока не имеет в памяти последнего элемента, он для создания логической конечной точки, представляющей точку остановки использования алгоритма, использует конструктор без аргументов.
Последней частью методики использования istream_iterator
vector
с двумя итераторами, то его конструктор скопирует в контейнер все элементы диапазона, определяемого итераторами. Если передать только что созданные итераторы start
и end
, то это будет выглядеть так.vector
Именно здесь происходит чтение значений из потока. При создании v
start
и перебирает все значения, пока не достигнет end
. Каждый раз, когда v
читает из *start
, происходит нечто эквивалентное такому вызову cin
.cin >> v[i]; // v - это vector
Другими словами, следующее значение, извлекаемое из cin
string
и вставляется в vector
.cin
Итераторы выходных потоков ведут себя аналогично итераторам потоков ввода. В примере 7.11 я копирую значения из своего vector
cout
, создав для этого ostream_iterator
, который указывает на cout
, следующим образом.copy(v.begin(), v.end(), ostream_iterator
Аргумент шаблона ostream_iterator
string
. Первый аргумент конструктора ostream_iterator
— это поток, в который будет производиться запись (и который может быть любым потоком вывода, включая ofstream
и ostringstream
), а второй это используемый разделитель. Это дает удобный способ выводить диапазон значений на стандартный вывод, что я часто делаю при отладке.Если требуется дополнительное управление внешним видом вывода, например вывод последовательности в квадратных или фигурных скобках или отсутствие последнего разделителя в конце последовательности, то это потребует всего нескольких дополнительных строк кода. Пример 7.12 показывает тело printContainer
printRange
, первая из которых используется в примерах этой главы.#include
#include
#include
#include
#include
using namespace std;
template
void printContainer(const C& c, char delim = ',', ostream& out = cout) {
printRange(c.begin(), c.end(), delim, out);
}
template
void printRange(Fwd first, Fwd last, char delim = ',', ostream& out = cout) {
out << "{";
while (first != last) {
out << *first;
if (++first != last)
out << delim << ' ';
}
out << "}" << endl;
}
int main() {
cout << "Введите набор строк: ";
istream_iterator
istream_iterator
vector
printContainer(v);
printRange(v.begin(), v.end(), ';', cout);
}
Функция printRange
printContainer
более удобна для печати целого контейнера. Имеется множество других способов сделать это. В голову также приходит определение версии operator<<
, которая бы работала с выходным потоком и контейнером, и использование стандартного алгоритма for_each
с собственным функтором для записи элементов в поток.Глава 8
Классы
8.0. Введение