С++ - Сплит-строка по регулярному выражению
Я хочу разделить std::string
на regex
.
Я нашел некоторые решения в Stackoverflow, но большинство из них разделяет строку на одно пространство или использует внешние библиотеки, такие как boost.
Я не могу использовать boost.
Я хочу разделить строку по регулярному выражению - "\\s+"
.
Я использую эту версию g++ g++ (Debian 4.4.5-8) 4.4.5
, и я не могу ее обновить.
Ответы
Ответ 1
Вам не нужно использовать регулярные выражения, если вы просто хотите разбить строку на несколько пробелов. Написание собственной библиотеки регулярных выражений является излишним для чего-то простого.
Ответ, связанный с вашими комментариями, Разделить строку на С++?, можно легко изменить, чтобы он не включал никаких пустых элементов, если есть несколько пространств.
std::vector<std::string> &split(const std::string &s, char delim,std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
if (item.length() > 0) {
elems.push_back(item);
}
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, elems);
return elems;
}
Проверяя, что item.length() > 0
перед нажатием item
на вектор elems
вы больше не получите дополнительных элементов, если ваш вход содержит несколько разделителей (пробелы в вашем случае)
Ответ 2
std::regex rgx("\\s+");
std::sregex_token_iterator iter(string_to_split.begin(),
string_to_split.end(),
rgx,
-1);
std::sregex_token_iterator end;
for ( ; iter != end; ++iter)
std::cout << *iter << '\n';
-1
- это ключ здесь: при построении итератора итератор указывает на текст, предшествующий совпадению, и после каждого приращения итератор указывает на текст, следующий за предыдущим соответствием.
Если у вас нет С++ 11, то то же самое должно работать с TR1 или (возможно, с небольшой модификацией) с Boost.
Ответ 3
Чтобы расширить ответ от @Pete Becker, я приведу пример функции resplit, которая может использоваться для разделения текста с помощью regexp:
std::vector<std::string>
resplit(const std::string & s, std::string rgx_str = "\\s+") {
std::vector<std::string> elems;
std::regex rgx (rgx_str);
std::sregex_token_iterator iter(s.begin(), s.end(), rgx, -1);
std::sregex_token_iterator end;
while (iter != end) {
//std::cout << "S43:" << *iter << std::endl;
elems.push_back(*iter);
++iter;
}
return elems;
}
Это работает следующим образом:
string s1 = "first second third ";
vector<string> v22 = my::resplit(s1);
for (const auto & e: v22) {
cout <<"Token:" << e << endl;
}
//Token:first
//Token:second
//Token:third
string s222 = "first|second:third,forth";
vector<string> v222 = my::resplit(s222, "[|:,]");
for (const auto & e: v222) {
cout <<"Token:" << e << endl;
}
//Token:first
//Token:second
//Token:third
//Token:forth
Ответ 4
string s = "foo bar baz";
regex e("\\s+");
regex_token_iterator<string::iterator> i(s.begin(), s.end(), e, -1);
regex_token_iterator<string::iterator> end;
while (i != end)
cout << " [" << *i++ << "]";
печатает [foo] [bar] [baz]