Класс std::string
std::basic_string
, и данная конструкция разворачивается к виду std::basic_string, std::allocator>
. О’кей, что означает это длинное описание типа? Идея заключается вот в чем: можно создать строку, которая работает не только с однобайтовыми элементами типа char
, но и с другими, более крупными типами. Это позволяет создавать строковые типы, способные работать с более широкими диапазонами символов, нежели типичный диапазон символов американской таблицы ASCII. Нам сейчас не нужно обращать на это внимание.Класс char_traits
basic_string
для корректной работы. Класс char_traits
умеет сравнивать, искать и копировать символы и строки.Класс allocator
Если мы хотим, чтобы строковый класс вел себя иначе, то можем попробовать повторно использовать по максимуму все возможности, предоставляемые классами basic_string
char_traits
. Именно это и произошло. Мы реализовали два подкласса char_traits
, которые называются case_insentitive
и lower_caser
, и сконфигурировали с их помощью два совершенно новых строковых типа, применяя их в качестве замены стандартному типу char_traits
. basic_string
std::char_traits
и взгляните на другие его функции, которые можно переопределить.Токенизация входных данных с помощью библиотеки для работы с регулярными выражениями
При преобразовании строк сложными способами или разбиении их на фрагменты могут помочь
Если вы еще не знакомы с регулярными выражениями, то можете, например, прочесть о них в «Википедии». Это определенно расширит ваш кругозор, так как нетрудно заметить, насколько эти выражения полезны при анализе любых текстов. С их помощью можно, например, проверить корректность адреса электронной почты или IP-адреса, найти и извлечь подстроки из больших строк согласно сложному шаблону и т.д.
В этом примере мы извлечем все ссылки из HTML-документа и выведем их на экран пользователя. Код решения данной задачи будет очень коротким, поскольку язык С++ STL поддерживает регулярные выражения, начиная с версии С++11.
Как это делается
В примере мы определим регулярное выражение, которое обнаруживает ссылки, и применим его к файлу HTML, чтобы аккуратно вывести все ссылки, найденные в этом файле.
1. Сначала включим все необходимые заголовочные файлы и объявим об использовании пространства имен std
#include
#include
#include
#include
#include
using namespace std;
2. Позднее сгенерируем итерабельный диапазон данных, который состоит из строк. Эти строки всегда будут составлять пары из ссылки и ее описания. Так что напишем небольшую вспомогательную функцию, аккуратно выводящую их на экран:
template
void print(InputIt it, InputIt end_it)
{
while (it != end_it) {
3. На каждом шаге цикла дважды инкрементируем итератор и берем копии ссылки и ее описания, которые он содержит. Между двумя операциями разыменования итератора добавляем еще один охранный блок if
const string link {*it++};
if (it == end_it) { break; }
const string desc {*it++};
4. Теперь выведем на экран ссылки и их описания в аккуратном виде:
cout << left << setw(28) << desc
<< " : " << link << '\n';
}
}
5. В функции main
noskipws
. Этот модификатор деактивизирует пропуск пробелов и токенизацию:int main()
{
cin >> noskipws;
const std::string in {istream_iterator
6. Теперь следует определить регулярное выражение, которое описывает, как с нашей точки зрения должна выглядеть ссылка HTML. Скобки ()
const regex link_re {