- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
Мы не использовали следующие манипуляторы, поскольку они никак не связаны с форматированием, но для полноты картины рассмотрим и их (табл. 7.2).
Среди перечисленных модификаторов стойкими являются только skipws/noskipws и unitbuf/nounitbuf.
Инициализируем сложные объекты из файла вывода
Считывать отдельные числа и слова довольно просто, поскольку оператор >> имеет перегруженные версии для всех этих типов, а потоки ввода удобным образом отбрасывают все промежуточные пробелы.
Но что, если перед нами более сложная структура и нужно прочесть ее из потока ввода или же требуется считать строки, состоящие более чем из одного слова (по умолчанию они будут разбиты на отдельные слова из-за того, что пробелы опускаются)?
Для любого типа можно предоставить еще одну перегруженную версию оператора потока ввода >>, и сейчас мы увидим воплощение этого на практике.
Как это делается
В этом примере мы определим пользовательскую структуру данных и предоставим возможности для чтения ее объектов из потоков ввода.
1. Включим некоторые заголовочные файлы и объявим об использовании пространства имен std для удобства:
#include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
2. В качестве примера сложного объекта определим структуру city. Она будет иметь название, количество населения и географические координаты:
struct city {
string name;
size_t population;
double latitude;
double longitude;
};
3. Чтобы считать объект такой структуры из последовательного потока ввода, следует перегрузить оператор потоковой функции >>. В этом операторе сначала опустим все пробелы, стоящие перед текстом, с помощью ws, поскольку пробелы не должны засорять название города. Затем считаем целую строку текста. Это подразумевает, что входной файл будет включать строку, в которой записано только название города. Затем, после символа новой строки, будет следовать список чисел, разделенный запятой, в котором содержится информация о численности населения, а также географическая широта и долгота:
istream& operator>>(istream &is, city &c)
{
is >> ws; getline(is, c.name);
is >> c.population
>> c.latitude
>> c.longitude; return is;
}
4. В нашей функции main создаем вектор, в котором может содержаться целый диапазон элементов типа city. Заполним его с помощью std::copy. Входными данными для вызова copy является диапазон istream_iterator. Передавая ему тип структуры city в качестве параметра шаблона, мы будем использовать перегруженную функцию >>, реализованную только что:
int main()
{
vector<city> l;
copy(istream_iterator<city>{cin}, {},
back_inserter(l));
5. Чтобы увидеть, прошло ли преобразование правильно, выведем на экран содержимое списка. Форматирование ввода/вывода, left << setw(15) <<, приводит к тому, что название города заполняется пробелами, поэтому выходные данные представлены в приятной и удобочитаемой форме:
for (const auto &[name, pop, lat, lon] : l) {
cout << left << setw(15) << name
<< " population=" << pop
<< " lat=" << lat
<< " lon=" << lon << 'n';
}
}
6. Текстовый файл, из которого наша программа будет считывать данные, выглядит следующим образом. В нем содержится информация о четырех городах: их названия, количество населения и географические координаты:
Braunschweig
250000 52.268874 10.526770
Berlin
4000000 52.520007 13.404954
New York City
8406000 40.712784 -74.005941
Mexico City
8851000 19.432608 -99.133208
7. Компиляция и запуск программы дадут следующий результат, он соответствует нашим ожиданиям. Попробуйте изменить входной файл, добавляя ненужные пробелы перед названием городов, чтобы увидеть, как они будут отфильтрованы:
$ cat cities.txt | ./initialize_complex_objects
Braunschweig population=250000 lat=52.2689 lon=10.5268
Berlin population=4000000 lat=52.52 lon=13.405
New York City population=8406000 lat=40.7128 lon=-74.0059
Mexico City population=8851000 lat=19.4326 lon=-99.1332
Как это работает
Мы снова рассмотрели короткий пример. В нем мы лишь создали новую структуру city, а затем перегрузили оператор >> итератора std::istream для данного типа. Это позволило десериализовать элементы типа city, полученные из стандартного потока ввода, с помощью istream_iterator<city>.
Открытым может оставаться вопрос, связанный с проверкой на ошибки. Поэтому снова рассмотрим реализацию оператора >>:
istream& operator>>(istream &is, city &c)
{
is >> ws;
getline(is, c.name);
is >> c.population >> c.latitude >> c.longitude;
return is;
}
Мы считываем множество разных элементов. Что произойдет, если один из них даст сбой, а следующий за ним — нет? Означает ли это потенциальное считывание всех следующих элементов со «смещением» в потоке токенов? Нет, этого не произойдет. Если хотя бы один элемент потока ввода не сможет быть преобразован, то объект потока ввода входит в ошибочное состояние и отказывается выполнять дальнейшие преобразования. Это значит, что если, например, c.population или c.latitude не могут быть преобразованы, то остальные операнды >> будут просто отброшены и мы покинем область действия функции оператора с наполовину заполненным объектом.
На вызывающей стороне мы получим оповещение об этом при написании конструкции if (input_stream >> city_object). Такое потоковое выражение неявно преобразуется в булево значение, когда используется как условное выражение. Оно возвращает значение false, если объект потока ввода находится в ошибочном состоянии. Зная это, можно сбросить поток и выполнить подходящие операции.
В данном примере мы не писали подобных условий if сами, поскольку позволили выполнить десериализацию итератору std::istream_iterator<city>. Реализация перегруженной версии оператора ++ для этого итератора также выполняет проверку ошибок во время преобразования. При генерации ошибок преобразование будет приостановлено. В этом состоянии проверка будет возвращать значение true при сравнении с конечным итератором, что заставляет алгоритм copy завершить работу. Таким образом, мы в безопасности.
Заполняем контейнеры с применением итераторов std::istream
В предыдущем примере вы узнали, как