Сопоставление регулярных выражений несколько раз в одном std::string

#c #regex

#c #регулярное выражение

Вопрос:

С сегодняшнего появления кода у нас были входные данные, которые могли быть списком из нескольких пакетов.

"3 drab lime bags, 1 drab plum bag, 2 vibrant tomato bags, 1 plaid blue bag."; Например, в моем вводе была строка, подобная.

Что я сделал, чтобы решить эту проблему: разделите его среди ',' , а затем примените std::regex bag_regex("([0-9] ) (\w \w ) bag"); к каждой из этих подстрок.

Теперь я попробовал, смогу ли я сделать это, возможно, за один присест или что-то в этом роде, и попытался использовать https://en.cppreference.com/w/cpp/regex/regex_token_iterator вместо этого.

Пример кода:

 std::string test = "3 drab lime bags, 1 drab plum bag, 2 vibrant tomato bags, 1 plaid blue bag.";
std::regex bag_regex_it("[0-9]  \w  \w ");
    
std::copy(std::sregex_token_iterator(test.begin(), test.end(), bag_regex_it, -1),
    std::sregex_token_iterator(),
    std::ostream_iterator<std::string>(std::cout, "n"));
 

Что я на самом деле получаю в своем выводе:

  bags,
 bag,
 bags,
 bag.
 

Есть ли какой-либо способ получить его уже в группах (количество номеров и описание цвета)? Я предполагаю, что правильное использование лямбда-выражения помогло бы здесь, но я понятия не имею, как это сделать. Идеальным результатом было std::vector бы std::pair<int, std::string> , например, содержащее проанализированную информацию, но этот код мне недоступен.

Комментарии:

1. Удалите -1 аргумент в конце std::sregex_token_iterator(test.begin(), test.end(), bag_regex_it, -1), . -1 означает, что вам нужно получить все те части строки, которые НЕ совпадают , см. ideone.com/mxd8Z1

Ответ №1:

Вы можете использовать последний параметр в regex_token_iterator качестве массива подгрупп (учитывая 2 группы (количество и цвет), которые вы хотите).

Следующий фрагмент не выполняет никакой проверки ошибок и предполагает, что введенная вами строка является допустимой:

 using Pair = std::pair<int, std::string>;
Pair p;
const int subgroups[] = {1,2};
std::vector < Pair> results; // Your desired result
std::regex_token_iterator<std::string::iterator> c
       { test.begin(), test.end(), regex_it, subgroups };
std::regex_token_iterator<std::string::iterator> rend;

while (c!=rend) {
    // Do some sort of error handling here    
    p.first = std::stoi(*c  );
    p.second = *c  ;
    results.push_back(p);                      
}

std::cout << results.size(); // 4
 

Demo here