Разделение строки на фрагменты по шаблону

Разделить строку на фрагменты по шаблону регулярного выражения, а также найти все совпадения с шаблоном позволяет класс regex_token_iterator:

template<typename _Bi_iter,
   typename _Ch_type = typename iterator_traits<_Bi_iter>::value_type,
   typename _Rx_traits = regex_traits<_Ch_type> >
   class regex_token_iterator

Псевдонимы:

typedef regex_token_iterator<const char*> cregex_token_iterator;
typedef regex_token_iterator<const wchar_t*> wcregex_token_iterator;
typedef regex_token_iterator<string::const_iterator>
        sregex_token_iterator;
typedef regex_token_iterator<wstring::const_iterator>
        wsregex_token_iterator;

Основные конструкторы класса regex_token_iterator:

regex_token_iterator();
regex_token_iterator(_Bi_iter first, _Bi_iter last,
                     const regex_type &re, int submatch=0,
                     match_flag_type flags=match_default);
template<std::size_t _Nm>
   regex_token_iterator(_Bi_iter first, _Bi_iter last,
                        const regex_type &re,
                        const int (&submatches)[_Nm],
                        match_flag_type flags=match_default);
regex_token_iterator(_Bi_iter first, _Bi_iter last,
                     const regex_type &re,
                     const std::vector<int> &submatches,
                     match_flag_type flags=match_default);
regex_token_iterator(_Bi_iter first, _Bi_iter last,
                     const regex_type &re,
                     initializer_list<int> submatches,
                     match_flag_type flags=match_default);

Первый конструктор создает объект, указывающий на конец последовательности. Параметры остальных конструкторов совпадают с одноименными параметрами функции regex_search(). При разыменовании итератора с помощью оператора * или -> доступен объект класса sub_match. При увеличении на единицу с помощью оператора ++ возвращается следующий фрагмент. Если ничего не найдено, то возвращается объект, созданный с помощью первого конструктора. Для сравнения двух объектов класса regex_token_iterator можно использовать операторы == и !=.

Если параметр submatch не задан или указано значение 0, то при разыменовании итератора будет доступен фрагмент полностью совпадающий с шаблоном регулярного выражения. Получим все числа из строки:

std::regex rgx("([0-9])([0-9]+)");
std::string str("s14 t25 n36k");
std::sregex_token_iterator istart(str.begin(), str.end(), rgx);
std::sregex_token_iterator iend;
while (istart != iend) {
   std::cout << istart->str() << '+';
   // std::cout << (*istart).str() << '+';
   ++istart;
} // 14+25+36+

Если в параметре submatch указано число больше 0, то оно задает индекс группы внутри шаблона. При разыменовании итератора будет доступен фрагмент совпадающий с группой, имеющей указанный индекс. Получим только первые цифры из всех чисел внутри строки:

std::regex rgx("([0-9])([0-9]+)");
std::string str("s14 t25 n36k");
std::sregex_token_iterator istart(str.begin(), str.end(), rgx, 1);
std::sregex_token_iterator iend;
while (istart != iend) {
   std::cout << istart->str() << '+';
   ++istart;
} // 1+2+3+

Если мы укажем число 2, то получим значение второй группы внутри шаблона:

4+5+6+

Параметр submatches позволяет указать несколько чисел в виде обычного массива, динамического массива или списка инициализации. Получим все совпадения:

std::regex rgx("([0-9])([0-9]+)");
std::string str("s14 t25 n36k");
int submatches[] = {0, 1, 2};
// #include <vector>
/*std::vector<int> submatches;
submatches.push_back(0);
submatches.push_back(1);
submatches.push_back(2);*/
// std::initializer_list<int> submatches = {0, 1, 2};
std::sregex_token_iterator istart(str.begin(), str.end(), rgx,
                           submatches);
std::sregex_token_iterator iend;
while (istart != iend) {
   std::cout << istart->str() << '+';
   ++istart;
} // 14+1+4+25+2+5+36+3+6+

Если в параметре submatch указано значение -1, то строка разделяется на фрагменты по шаблону регулярного выражения (листинг 10.3). Если соответствие шаблону не найдено в строке, то результатом будет исходная строка.

Листинг 10.3. Разделение строки на фрагменты по шаблону

#include <iostream>
#include <string>
#include <regex>
#include <vector>

int main() {
   std::vector<std::string> results;
   std::regex rgx("[\\s,.]+");
   std::string str("word1, word2\nword3\r\nword4.word5");
   std::sregex_token_iterator istart(str.begin(), str.end(), rgx, -1);
   std::sregex_token_iterator iend;
   while (istart != iend) {
      results.push_back(istart->str());
      ++istart;
   }
   for (std::string &s : results) {
      std::cout << s << ' ';
   }
   std::cout << std::endl;
   return 0;
}

Результат:

word1 word2 word3 word4 word5

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов