- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
8. Теперь у нас есть итератор, который будет возвращать все найденные ссылки и их описания. Мы предоставим его и итератор того же типа, созданный по умолчанию, функции print, реализованной нами ранее:
print(it, {});
}
9. Компиляция и запуск программы дадут следующий результат. Я запустил программу curl для домашней страницы ISO C++, которая просто загружает HTML-страницу из Интернета. Конечно, я мог и написать cat some_html_file.html | ./link_extraction. Использованное нами регулярное выражение довольно жестко определяет представление о том, как должны выглядеть ссылки в документе HTML. В качестве самостоятельной работы можете сделать его более обобщенным.
$ curl -s "https://isocpp.org/blog" | ./link_extraction
Sign In / Suggest an Article : https://isocpp.org/member/login
Register : https://isocpp.org/member/register
Get Started! : https://isocpp.org/get-started
Tour : https://isocpp.org/tour
C++ Super-FAQ : https://isocpp.org/faq
Blog : https://isocpp.org/blog
Forums : https://isocpp.org/forums
Standardization : https://isocpp.org/std
About : https://isocpp.org/about
Current ISO C++ status : https://isocpp.org/std/status
(...и многие другие...)
Как это работает
Регулярные выражения (или коротко regex) очень полезны. Они могут казаться очень сложными, но вам стоит изучить принципы их работы. Короткое регулярное выражение может избавить от необходимости писать множество строк кода, что пришлось бы сделать при выполнении проверки на соответствие вручную.
В данном примере мы сначала создали объект типа регулярных выражений. Мы передали его конструктору строку, которая описывает регулярное выражение. Самое простое регулярное выражение выглядит как ".", оно соответствует любому символу, поскольку точка — это специальный символ для регулярного выражения. Выражение "a" соответствует только символам 'a'. Выражение "ab*" означает «один символ а, а затем ноль или больше символов b» и т.д. Регулярные выражения — довольно обширная тема, более подробную информацию можно найти в «Википедии» и на других сайтах и в литературе.
Еще раз взглянем на регулярное выражение, соответствующее нашему представлению о ссылках HTML. Простая ссылка HTML может выглядеть как <a href="some_url.com/foo">A great link</a>. Нужно получить часть some_url.com/foo, а также A great link. Мы создали следующее регулярное выражение, которое содержит группы для соответствия подстрокам (рис. 7.2).
Полное совпадение всегда является группой 0. В данном случае это будет вся строка <a href ... </a>. Заключенная в кавычки часть href, которая содержит URL, — это группа 1. Скобки в регулярном выражении определяют такие группы. Их у нас две. Еще одна группа — фрагмент текста между тегами <a...> и </a>, содержащий описание ссылки.
Существует множество функций STL, которые принимают объекты регулярных выражений. Однако мы непосредственно использовали адаптер для итератора, работающего с токенами регулярного выражения. Он представляет собой высокоуровневую абстракцию, применяющую std::regex_search, чтобы автоматизировать работу по поиску совпадений. Мы создали его экземпляр следующим образом:
sregex_token_iterator it {begin(in), end(in), link_re, {1, 2}};
Части begin и end обозначают нашу входную строку, по которой итератор, работающий с токенами регулярного выражения, будет итерировать и искать все ссылки. link_re — это, конечно, сложное регулярное выражение, созданное нами для поиска ссылок. Часть {1, 2} — еще один непонятный фрагмент. Он дает итератору команду опускать полное совпадение и возвращать группу 1, затем инкрементировать итератор и возвращать группу 2, а позже, после очередной операции инкремента, находить следующее совпадение в строке. Это разумное поведение освобождает нас от необходимости писать ненужные строки кода.
Давайте рассмотрим еще один пример. Представим регулярное выражение "a(b*)(c*)". Оно будет соответствовать строкам, содержащим символ a, после которого идет ноль или больше символов b, а затем — ноль или больше символов c:
const string s {" abc abbccc "};
const regex re {"a(b*)(c*)"};
sregex_token_iterator it {begin(s), end(s), re, {1, 2}};
print( *it ); // выводит b
++it;
print( *it ); // выводит c
++it;
print( *it ); // выводит bb
++it;
print( *it ); // выводит ccc
Существует также класс std::regex_iterator, который генерирует подстроки, находящиеся между совпадениями с регулярными выражениями.
Удобный и красивый динамический вывод чисел на экран в зависимости от контекста
В предыдущем примере было показано, как отформатировать выходные данные с помощью потоков вывода. Во время решения данной задачи мы узнали следующее:
□ большая часть манипуляторов являются стойкими, поэтому нужно отменять их действие, чтобы не пересечься с другим несвязанным кодом, который также выводит данные на экран;
□ создавать длинные цепочки манипуляторов ввода/вывода, чтобы вывести несколько переменных с конкретным форматированием, может быть утомительно, а код получится не очень читабельным.
По этим причинам многие пользователи не любят потоки ввода/вывода и даже в С++ все еще применяют функцию print для форматирования строк.
Ниже мы увидим, как форматировать типы динамически, не прибегая к чрезмерно большому количеству манипуляторов ввода/вывода.
Как это делается
В этом примере мы реализуем класс format_guard, способный автоматически отменить любые настройки форматирования. Кроме того, напишем тип-оболочку, который может содержать любые значения, но при выводе будет применять особое форматирование, не загружая код лишними манипуляторами ввода/вывода.
1. Сначала включим некоторые заголовочные файлы и объявим об использовании пространства имен std:
#include <iostream>
#include <iomanip>
using namespace std;
2. Вспомогательный класс, очищающий состояние форматирования для потоков, называется format_guard. В его конструкторе сохраняются флаги форматирования, которые были заданы для std::cout в момент создания объекта. Его деструктор восстанавливает их состояние на момент вызова конструктора. Это, по сути, отменяет все настройки форматирования, примененные между вызовами данных методов.
class format_guard {
decltype(cout.flags()) f {cout.flags()};
public:
~format_guard() { cout.flags(f); }
};
3. Еще один небольшой вспомогательный класс называется scientific_type. Поскольку это шаблон класса, он может оборачивать любой тип, который будет представлять собой переменную-член. По сути, он ничего не делает.
template <typename T>
struct scientific_type {
T value;
explicit scientific_type(T val) : value{val} {}
};
4. Можно определить собственные настройки форматирования для любого типа, который ранее был обернут в scientific_type, поскольку в случае перегрузки оператора потока >> потоковая библиотека будет выполнять совершенно другой код при выводе подобных типов. Таким образом, можно выводить научные значения в научном представлении