Вы часто будете слышать выражения “копировать в поток вывода” или “копировать из потока ввода”. Это удобный и полезный способ описания некоторых видов ввода-вывода. Для выполнения этой операции действительно использует алгоритм copy().

Напомним свойства последовательностей.

• Последовательность имеет начало и конец.

• Переход на следующий элемент последовательности осуществляется с помощью оператора ++.

• Значение элемента последовательности можно найти с помощью оператора *.

Потоки ввода и вывода можно легко описать точно так же. Рассмотрим пример.

ostream_iterator oo(cout); // связываем поток *oo с потоком

                                   // cout для записи

*oo = "Hello, ";                   // т.е. cout << "Hello, "

++oo;                              // "готов к выводу следующего

                                   // элемента"

*oo = "World!\n";                  // т.е. cout << "World!\n"

В стандартной библиотеке есть тип ostream_iterator, предназначенный для работы с потоком вывода; ostream_iterator — это итератор, который можно использовать для записи значений типа T.

В стандартной библиотеке есть также тип istream_iterator для чтения значений типа T.

istream_iterator ii(cin);  // чтение *ii — это чтение строки

                                   // из cin

string s1 = *ii;                   // т.е. cin>>s1

++ii;                              // "готов к вводу следующего

                                   // элемента"

string s2 = *ii; // т.е. cin>>s2

Используя итераторы ostream_iterator и istream_iterator, можно вводить и выводить данные с помощью алгоритма copy(). Например, словарь, сделанный наспех, можно сформировать следующим образом:

int main()

{

  string from, to;

  cin >> from >> to;         // вводим имена исходного

                             // и целевого файлов

  ifstream is(from.c_str()); // открываем поток ввода

  ofstream os(to.c_str());   // открываем поток вывода

  istream_iterator ii(is); // создаем итератор ввода

                                   // из потока

  istream_iterator eos;    // сигнальная метка ввода

  ostream_iterator oo(os,"\n"); // создаем итератор

                                        // вывода в поток

  vector b(ii,eos);             // b — вектор, который

                                        // инициализируется

                                        // данными из потока ввода

  sort(b.begin(),b.end());              // сортировка буфера

  copy(b.begin(),b.end(),oo);           // буфер копирования для вывода

}

Итератор eos — это сигнальная метка, означающая “конец ввода.” Когда поток istream достигает конца ввода (который часто называется eof), его итератор istream_iterator становится равным итератору istream_iterator, который задается по умолчанию и называется eos.

  Обратите внимание на то, что мы инициализируем объект класса vector парой итераторов. Пара итераторов (a,b), инициализирующая контейнер, означает следующее: “Считать последовательность [a:b] в контейнер”. Естественно, для этого мы использовали пару итераторов (ii,eos) — начало и конец ввода. Это позволяет нам не использовать явно оператор >> и функцию push_back(). Мы настоятельно не рекомендуем использовать альтернативный вариант.

vector b(max_size); // не пытайтесь угадать объем входных

                            // данных

copy(ii,eos,b.begin());

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

ПОПРОБУЙТЕ

Приведите программу в рабочее состояние и протестируйте ее на небольшом файле, скажем, содержащем несколько сотен слов. Затем испытайте “настоятельно не рекомендованную версию”, в которой объем входных данных угадывается, и посмотрите, что произойдет при переполнении буфера ввода b. Обратите внимание на то, что наихудшим сценарием является тот, в котором вы не замечаете ничего плохого и передаете программу пользователям.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже