- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Следует заметить, что при присвоении итератору out_iter можно пропустить обращение к значению и инкремент. Таким образом, этот цикл можно переписать так:
for (auto е : vec)
out_iter = е; // это присвоение запишет элемент в cout
cout << endl;
Операторы * и ++ ничего не делают с итератором ostream_iterator, поэтому их пропуск никак не влияет на программу. Но предпочтительней писать цикл как в первом варианте. Он использует итератор единообразно с тем, как используются итераторы других типов. Этот цикл можно легко изменить так, чтобы он выполнялся итераторами других типов. Кроме того, поведение этого цикла понятней читателям нашего кода.
Чтобы не сочинять цикл самостоятельно, можно легко ввести элементы в вектор vec при помощи алгоритма copy():
copy(vec.begin(), vec.end(), out_iter);
cout << endl;
Использование потоковых итераторов с типами классаИтератор istream_iterator можно создать для любого типа, у которого есть оператор ввода (>>). Точно так же итератор ostream_iterator можно определить для любого типа, обладающего оператором вывода (<<). Поскольку у класса Sales_item есть оба оператора (ввода и вывода), итераторы ввода-вывода вполне можно использовать, чтобы переписать программу книжного магазина из раздела 1.6:
istream_iterator<Sales_item> item_iter(cin), eof;
ostream_iterator<Sales_item> out_iter(cout, "n");
// сохранить первую транзакцию в sum и читать следующую запись
Sales_item sum = *item_iter++;
while (item_iter != eof) {
// если текущая транзакция (хранимая в item_iter) имеет тот же ISBN
if (item_iter->isbn() == sum.isbn())
sum += *item_iter++; // добавить ее к sum и читать следующую
// транзакцию
else {
out_iter = sum; // вывести текущую сумму
sum = *item_iter++; // читать следующую транзакцию
}
}
out_iter = sum; // не забыть вывести последний набор записей
Эта программа использует итератор item_iter для чтения транзакций Sales_item из потока cin. Она использует итератор out_iter для записи полученной суммы в поток cout, сопровождая каждый вывод символом новой строки. Определив итераторы, используем итератор item_iter для инициализации переменной sum значением первой транзакции:
// сохранить первую транзакцию в sum и читать следующую запись
Sales_item sum = *item_iter++;
Выражение осуществляет обращение к значению результата постфиксного инкремента итератора item_iter. Затем оно читает следующую транзакцию и инициализирует переменную sum значением, предварительно сохраненным в item_iter.
Цикл while выполняется до тех пор, пока поток cin не встретит конец файла. В цикле while осуществляется проверка, не относится ли содержимое переменной sum и только что прочитанная запись к той же книге. Если это так, то только что прочитанный объект класса Sales_item добавляется в переменную sum. Если ISBN отличаются, переменная sum присваивается итератору out_iter, который выводит текущее значение переменной sum, сопровождаемое символом новой строки. После вывода суммы для предыдущей книги переменной sum присваивается копия последней прочитанной транзакции и осуществляется инкремент итератора для чтения следующей транзакции. Цикл продолжается до конца файла или ошибки чтения. Перед завершением следует вывести значения по последней книге во вводе.
Упражнения раздела 10.4.2Упражнение 10.29. Напишите программу, использующую потоковые итераторы для чтения текстового файла в вектор строк.
Упражнение 10.30. Используйте потоковые итераторы, а также функции sort() и copy() для чтения последовательности целых чисел со стандартного устройства ввода, их сортировки и последующего вывода на стандартное устройство вывода.
Упражнение 10.31. Измените программу из предыдущего упражнения так, чтобы она выводила только уникальные элементы. Программа должна использовать алгоритм unique_copy() (см. раздел 10.4.1).
Упражнение 10.32. Перепишите программу книжного магазина из раздела 1.6. Используйте вектор для хранения транзакции и различные алгоритмы для обработки. Используйте алгоритм sort() с собственной функцией compareIsbn() из раздела 10.3.1 для упорядочивания транзакций, а затем используйте алгоритмы find() и accumulate() для вычисления суммы.
Упражнение 10.33. Напишите программу, получающую имена входного и двух выходных файлов. Входной файл должен содержать целые числа. Используя итератор istream_iterator, прочитайте входной файл. Используя итератор ostream_iterator, запишите нечетные числа в первый выходной файл. За каждым значением должен следовать пробел. Во второй файл запишите четные числа. Каждое из этих значений должно быть помещено в отдельную строку.
10.4.3. Реверсивные итераторы
Реверсивный итератор (reverse iterator) перебирает контейнер в обратном направлении, т.е. от последнего элемента к первому. Реверсивный итератор инвертирует смысл инкремента (и декремента): оператор ++it переводит реверсивный итератор на предыдущий элемент, а оператор --it — на следующий.
Реверсивные итераторы есть у всех контейнеров, кроме forward_list. Для получения реверсивного итератора используют функции-члены rbegin(), rend(), crbegin() и crend(). Они возвращают реверсивные итераторы на последний элемент в контейнере и на "следующий" (т.е. предыдущий) перед началом контейнера. Подобно обычным итераторам, существуют константные и неконстантные реверсивные итераторы.
Взаимное положение этих четырех итераторов на гипотетическом векторе vec представлено на рис. 10.1.
Рис. 10.1. Взаимное положение итераторов, возвращаемых функциями begin()/cend() и rbegin()/crend()
Рассмотрим, например, следующий цикл, выводящий элементы вектора vec в обратном порядке:
vector<int> vec = {0,1,2,3,4,5,6,7,8,9};
// реверсивный итератор вектора (от конца к началу)
for (auto r_iter = vec.crbegin(); // связывает r_iter с последним
// элементом
r_iter != vec.crend(); // crend ссылается на 1 элемент
// перед 1-м
++r_iter) // декремент итератора на один элемент
cout << *r_iter << endl; // выводит 9, 8, 7, ... 0
Хотя смысл оператора декремента реверсивного итератора может показаться неправильным, этот оператор позволяет применять для обработки контейнера стандартные алгоритмы. Например, передав функции sort() два реверсивных итератора, вектор можно отсортировать в порядке убывания.
sort(vec.begin(), vec.end()); // сортирует вектор vec
// в "нормальном" порядке
// обратная сортировка: самый маленький элемент располагается
// в конце вектора vec
sort(vec.rbegin(), vec.rend());
Реверсивным итераторам необходим оператор декрементаНет ничего удивительного в том, что реверсивный итератор можно создать только из такого класса итератора, для которого определены операторы -- и ++. В конце концов, задача реверсивного итератора заключается в переборе последовательности назад. Кроме контейнера forward_list, итераторы всех стандартных контейнеров поддерживают как инкремент, так и декремент. Однако потоковые итераторы к ним не относятся, поскольку невозможно перемещать поток в обратном направлении. Следовательно, создать из потокового итератора реверсивный итератор невозможно.
Отношения между реверсивными и другими итераторамиПредположим, что существует объект line класса string(строка), содержащий разделяемый запятыми список слов. Используя функцию find(), можно отобразить, например, первое слово строки line:
// найти первый элемент в списке, разделенном запятыми
auto comma = find(line.cbegin(), line.cend(), ',');
cout << string(line.cbegin(), comma) << endl;
Если в строке line есть запятая, итератор comma будет указывать на нее, в противном случае он будет равен итератору, возвращаемому функцией line.cend(). При выводе содержимого строки от позиции line.cbegin() до позиции comma будут отображены символы от начала до запятой или вся строка, если запятых в ней нет.

