Перейти к содержанию

Последнее обновление:2026-10-12

Шесть способов разделения строк в C++

Часто при разработке приходится разделять длинную строку по разделителю, чтобы получить нужные нам строки. Все говорят, что разделение строк в C++ не так уж удобно, поэтому сегодня обобщим 5 способов разделения строки.

Здесь есть варианты от C++11 до C++20, а также C-стиль.

Для удобства дальнейшего изложения сначала определим прототип функции:

  • Параметры: две строки, одна — исходная строка, другая — разделитель

  • Возвращаемое значение: массив строк

Примечание: ленивую версию с полным кодом можно получить в закрытом сообществе.

1. Разделение через find

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

nt start = 0;
int end = s.find(delim);
std::vector<std::string> result;
while (end != std::string::npos) {
  result.push_back(s.substr(start, end - start));
  start = end + delim.size();
  end = s.find(delim, start);
}

result.push_back(s.substr(start, end - start));
Можно ли ещё оптимизировать этот способ?

Ответ — да: чтобы код выглядел более элегантно, можно каждый раз удалять уже извлечённую подстроку спереди, а логика find остаётся прежней.

while (end != std::string::npos) {
  result.push_back(s.substr(0, end));
  s.erase(0, end + delim.size());
  end = s.find(delim);
}

2. Разделение через C++20 Ranges и Views

В C++20 мы можем с помощью std::ranges::views::split() создать представление с разделителем, а затем применить transform, преобразовав каждое подпредставление в std::string.

auto split_transform_view = s | std::ranges::views::split(delim) |
                              std::ranges::views::transform([](auto&& str) {
                                return std::string(str.begin(), str.end());
                              });
Разве не просто? Если кто-то не понял — ничего страшного, загляните в предыдущие статьи о C++20.

3. Разделение по регулярному выражению

Строим шаблон разделителя с помощью объекта std::regex, а затем с помощью std::sregex_token_iterator перебираем подстроки, разделённые шаблоном регулярного выражения; значение -1 означает извлечение несовпавших строк, то есть всего, кроме разделителей.

std::regex r(delim);
return {std::sregex_token_iterator(s.begin(), s.end(), r, -1),
        std::sregex_token_iterator()};

4. Разделение через istringstream

getline каждый раз принимает только один разделитель, поэтому после разделения нужно продолжать пропуск последующих разделителей.

std::istringstream ss(s);
while (std::getline(ss, token, *(it = delim.begin()))) {
    result.push_back(token);
    it++;

    while (it != delim.end() && ss.peek() == *(it)) {
        it++;
        ss.get();
    }
}

5. Разделение strtok в C-стиле

Используем strtok(), чтобы разбить строку на токены, а затем в цикле while последовательно их извлекаем.

token = strtok((char*)s.c_str(), delim.c_str());
while (token != NULL) {
  result.push_back(token);
  token = strtok(NULL, delim.c_str());
}
Это все распространённые способы. А какими пользуетесь вы? Ждём вас в комментариях; полную версию кода из этого раздела (для ленивых) можно получить в закрытом сообществе.

Похожие темы

Комментарии