Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

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


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


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. Обратите внимание на то, что наихудшим сценарием является тот, в котором вы не замечаете ничего плохого и передаете программу пользователям.


В нашей маленькой программе мы считываем слова, а затем упорядочиваем их. Пока все, что мы делаем, кажется очевидным, но почему мы записываем слова в “неправильные” ячейки, так что потом вынуждены их сортировать? Кроме того, что еще хуже, оказывается, что мы записываем слова и выводим их на печать столько раз, сколько они появляются в потоке ввода.

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