- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
Подсчитываем все слова в файле
Предположим, мы считали текстовый файл и хотим определить количество слов в тексте. Словом, мы называем диапазон символов, расположенный между пробелами. Как же решить эту задачу?
Например, можно подсчитать количество пробелов, поскольку между словами должны быть пробелы. В предложении "John has a funny little dog." пять символов пробела, поэтому можно сказать, что оно состоит из шести слов.
Но как быть с предложением, содержащим разные виды пробелов, например: "John has t anfunny little dog."? В нем содержится слишком много ненужных пробелов и не только. Из других примеров данной книги вы уже знаете, как удалить эти лишние пробелы. Так что сначала можно было бы предварительно обработать строку, преобразовав ее в обычное предложение, а затем применить стратегию подсчета пробелов. Это выполнимо, но существует гораздо более простой способ. Почему бы не воспользоваться теми возможностями, которые предоставляет STL?
Помимо нахождения элегантного решения этой проблемы, мы позволим пользователю решать, для каких именно входных данных считать количество слов — для данных из стандартного потока ввода или из текстового файла.
Как это делается
В этом примере мы напишем короткую функцию, которая считает количество слов из входного буфера и позволяет пользователю выбирать, откуда именно во входном буфере появятся данные.
1. Включим все необходимые заголовочные файлы и объявим об использовании пространства имен std:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
using namespace std;
2. Функция wordcount принимает поток ввода, например cin. Она создает итератор std::input_iterator, который токенизирует строки потока, а затем передает их в std::distance. Параметр distance принимает в качестве аргументов два итератора и пытается определить, сколько именно операций инкремента нужно выполнить, чтобы переместиться с одной позиции итератора в другую. Для итераторов с произвольным доступом это делается легко, поскольку они реализуют операцию математической разности (operator-). Такие итераторы можно вычитать друг из друга, как и другие указатели. Итератор istream_iterator, однако, является однонаправленным, и его нужно сдвигать вперед до тех пор, пока он не станет равен итератору end. В конечном счете количество шагов будет равно количеству слов.
template <typename T>
size_t wordcount(T &is)
{
return distance(istream_iterator<string>{is}, {});
}
3. В нашей функции main мы позволяем пользователю выбрать, откуда придет поток ввода — из std::cin или из файла:
int main(int argc, char **argv)
{
size_t wc;
4. Если пользователь запустит программу в оболочке и укажет имя файла (например, $ ./count_all_words some_textfile.txt), то мы сможем получить его из параметра командной строки argv и открыть, чтобы передать новый поток ввода в функцию wordcount:
if (argc == 2) {
ifstream ifs {argv[1]};
wc = wordcount(ifs);
5. В случае запуска пользователем программы без параметров мы предполагаем, что входные данные появятся из стандартного потока ввода:
} else {
wc = wordcount(cin);
}
6. На этом все, просто выведем количество слов, сохраненное в переменной wc:
cout << "There are " << wc << " wordsn";
};
7. Скомпилируем и запустим программу. Сначала передадим данные из стандартного потока ввода. Можно либо выполнить вызов echo, передав туда несколько слов, либо запустить программу и ввести несколько слов с клавиатуры. Во втором случае можно прервать ввод нажатием комбинации клавиш Ctrl+D. Так выглядит вызов echo:
$ echo "foo bar baz" | ./count_all_words
There are 3 words
8. Если запустить программу и передать ей в качестве входного файла ее файл с исходным кодом, то она подсчитает количество слов, которые содержатся в нем:
$ ./count_all_words count_all_words.cpp
There are 61 words
Как это работает
Здесь особо нечего добавить, большую часть программы мы уже объяснили при реализации, поскольку сама программа очень короткая. Единственный факт, который можно немного пояснить: std::cin и std::ifstream взаимозаменяемы. cin имеет тип std::istream, а std::ifstream наследует от std::istream. Взгляните на диаграмму наследования, приведенную в начале этой главы (см. рис. 7.1). Таким образом, они полностью взаимозаменяемы, даже во время работы программы.
Поддерживайте модульность кода путем использования абстракций потока. Это позволит отвязать фрагменты исходного кода друг от друга и облегчит тестирование исходного кода, поскольку можно внедрить любой другой соответствующий тип потока.
Форматируем ваши выходные данные с помощью манипуляторов потока ввода-вывода
Во многих случаях недостаточно просто вывести строки и числа. Иногда числа нужно вывести в десятичной системе счисления, иногда — в шестнадцатеричной, а иногда — в восьмеричной. В одних ситуациях перед шестнадцатеричными числами префикс "0x" нужен, а в других — нет.
При выводе чисел с плавающей точкой существует множество моментов, на которые можно повлиять. Нужно ли всегда выводить их с одинаковой точностью? Надо ли выводить их вообще? Или, может быть, требуется научное представление?
Помимо представления и системы счисления нужно также представить пользователю выходные данные в «аккуратном» виде. Некоторые выходные данные можно поместить, например, в таблицы, чтобы сделать их максимально читабельными.
Все это можно сделать с помощью потоков вывода. Некоторые из этих настроек важны и при преобразовании входных значений. В данном примере мы познакомимся с так называемыми манипуляторами ввода-вывода. Часть их могут показаться сложными, так что рассмотрим их подробнее.
Как это делается
В этом примере мы выведем на экран числа, используя совершенно разные настройки форматов, чтобы ознакомиться с манипуляторами ввода-вывода.
1. Сначала включим все необходимые заголовочные файлы и объявим об использовании пространства имен std:
#include <iostream>
#include <iomanip>
#include <locale>
using namespace std;
2. Далее определим вспомогательную функцию, выводящую на экран целое число в разных стилях. Она принимает ширину отступа и символ-заполнитель, которым по умолчанию является ' ':
void print_aligned_demo(int val,
size_t width,
char fill_char = ' ')
{
3. С помощью setw можно задать минимальное количество символов, которое нужно вывести. Например, при вводе числа 123 с шириной 6 получим "