Skip to content

/commands/cpp/split-string-by-delimiter

c++ split a string by delimiter (getline, find, std::views::split)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
C++
versions
C++98+ (getline), C++20 (views::split), C++23 (ranges::to)
os
any

The portable way to split a string by a single-character delimiter in C++ is a std::getline loop over an std::istringstream: while (std::getline(iss, token, ',')) parts.push_back(token);. For a delimiter of several characters, loop with find and substr. C++20 adds std::views::split, which splits lazily without copying.

Three ways

The example uses Clang 20 from the ziglang package on PyPI (with libc++), run through uv; cxx stands for it. On your machine, write g++ or clang++:

bash
cxx() { uv run -q --no-project --python 3.13 --with ziglang==0.15.1 python -m ziglang c++ -fno-color-diagnostics "$@"; }
cat > split.cpp <<'EOF'
#include <iostream>
#include <ranges>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>

std::vector<std::string> split_getline(const std::string& s, char delim) {
    std::vector<std::string> out;
    std::istringstream iss(s);
    for (std::string token; std::getline(iss, token, delim);) out.push_back(token);
    return out;
}

std::vector<std::string> split_find(const std::string& s, const std::string& delim) {
    std::vector<std::string> out;
    std::size_t start = 0, pos;
    while ((pos = s.find(delim, start)) != std::string::npos) {
        out.push_back(s.substr(start, pos - start));
        start = pos + delim.size();
    }
    out.push_back(s.substr(start));
    return out;
}

void print(const char* label, const std::vector<std::string>& v) {
    std::cout << label << " (" << v.size() << "):";
    for (const auto& t : v) std::cout << " [" << t << "]";
    std::cout << '\n';
}

int main() {
    print("getline ','", split_getline("a,b,,c,", ','));
    print("find \", \"", split_find("red, green, blue", ", "));
    print("find ','  ", split_find("a,b,,c,", ","));

    std::cout << "views::split:";
    for (auto part : std::string_view("x-y-z") | std::views::split('-'))
        std::cout << " [" << std::string_view(part.begin(), part.end()) << "]";
    std::cout << '\n';

    std::istringstream words("  split   on\twhitespace ");
    std::cout << "operator>>:";
    for (std::string w; words >> w;) std::cout << " [" << w << "]";
    std::cout << '\n';
}
EOF
cxx -std=c++20 -Wall -Wextra split.cpp -o split && ./split

Output

getline ',' (4): [a] [b] [] [c]
find ", " (3): [red] [green] [blue]
find ','   (5): [a] [b] [] [c] []
views::split: [x] [y] [z]
operator>>: [split] [on] [whitespace]

Note the different handling of empty fields: the getline loop keeps the empty field between two commas but drops the empty one after a trailing comma, while the find loop keeps both. Pick the version that matches your format (CSV-like data usually needs the find behaviour).

Methods compared

MethodStandardNotes
getline(iss, token, delim) loopC++98Single-character delimiter; no token after a trailing delimiter
find + substr loopC++98Any delimiter string; keeps every empty field
std::views::split(delim)C++20Lazy view, no copies; convert each part to string_view or string
views::split | ranges::to<std::vector<std::string>>()C++23Collect the pieces in one expression
iss >> word loopC++98Splits on any whitespace, never yields empty tokens
std::regex / sregex_token_iteratorC++11Regular-expression delimiters; much slower

Pitfalls

  • Missing headers. std::istringstream needs <sstream> and std::views needs <ranges>; without them the compiler reports no member named ... in namespace std.
  • Standard too old. std::views::split requires -std=c++20 and a recent standard library (GCC 12+, Clang 16+ with libc++ for the fixed C++20 semantics).
  • Dangling string_view. Views returned from views::split point into the original string; keep it alive while you use them.
  • Windows line endings. Splitting lines read from a CRLF file leaves a \r at the end of the last field; strip it.

Confirm it worked

Print each token between brackets, as in the example, so empty tokens and stray spaces are visible, and test a string with a leading, a doubled and a trailing delimiter.

FAQ

Does C++ have a built-in split function?

Not one that returns a vector of strings. C++20 adds std::views::split, a lazy view over the pieces; together with C++23 std::ranges::to you can collect them into a container. Before that, a getline loop or find/substr is the usual way.

How do I split on any whitespace?

Read words with operator>> from an std::istringstream: while (iss >> word). It skips spaces, tabs and newlines and never produces empty tokens.

How do I split by a multi-character delimiter such as ", "?

getline only takes a single character. Use the find/substr loop with the delimiter string and advance by its length, or std::views::split with a string_view delimiter (C++20).

Sources