Split a String by Delimiter
C++ does not ship with a one-call `split` function, so this snippet shows three idiomatic alternatives: a `std::stringstream` plus `std::getline` walk for single-character delimiters, a `find`/`substr` loop for multi-character delimiters, and a regex-based split for full pattern flexibility. Pick stringstream for whitespace, find/substr for fixed strings, and regex only when the rules are genuinely complex.
777 views
16
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
std::vector<std::string> splitChar(const std::string& s, char sep) {
std::vector<std::string> out;
std::stringstream ss(s);
std::string token;
while (std::getline(ss, token, sep)) {
out.push_back(token);
}
return out;
}
int main() {
auto parts = splitChar("alpha,beta,gamma,,delta", ',');
std::cout << "parts size=" << parts.size() << "\n";
for (const auto& p : parts) std::cout << "[" << p << "]\n";
return 0;
}std::getline(stream, out, delim) reads up to (and discards) the next occurrence of delim, leaving the rest of the stream for the next call. The pattern is identical to reading lines with std::getline(cin, line) (where the delimiter defaults to \n). It correctly preserves empty tokens between consecutive delimiters, which strtok does not. Use this for CSV without quoting, simple : PATH-style splits, or any single-character separator.
#include <iostream>
#include <vector>
#include <string>
#include <cstddef>
std::vector<std::string> splitStr(const std::string& s, const std::string& sep) {
std::vector<std::string> out;
std::size_t start = 0;
std::size_t pos;
while ((pos = s.find(sep, start)) != std::string::npos) {
out.push_back(s.substr(start, pos - start));
start = pos + sep.size();
}
out.push_back(s.substr(start));
return out;
}
void demoStr() {
auto parts = splitStr("foo::bar::baz::qux", "::");
for (const auto& p : parts) std::cout << "[" << p << "]\n";
}
int main() {
demoStr();
return 0;
}stringstream only handles single-char delimiters; for multi-char separators like "::" or "-->" you walk the string with find and slice with substr. Track start and the next match; emit the segment, advance past the delimiter, repeat. Always remember to push the final segment after the loop, otherwise the last token is lost. This is O(n) total and avoids any allocation beyond the output vector and the substring copies.
#include <iostream>
#include <vector>
#include <string>
#include <regex>
std::vector<std::string> splitRegex(const std::string& s, const std::regex& re) {
std::vector<std::string> out;
auto begin = std::sregex_token_iterator(s.begin(), s.end(), re, -1);
auto end = std::sregex_token_iterator();
for (auto it = begin; it != end; ++it) out.push_back(*it);
return out;
}
void demoRegex() {
// Split on any run of whitespace OR commas.
std::regex sep("[\\s,]+");
auto parts = splitRegex(" alpha , beta\tgamma\n delta", sep);
for (const auto& p : parts) std::cout << "[" << p << "]\n";
}
int main() {
demoRegex();
return 0;
}std::sregex_token_iterator with the trailing -1 parameter yields the SEGMENTS between matches of the regex, exactly what split does. Use it for patterns like "any whitespace, comma, or both" that simple delimiters cannot express. The regex engine is much heavier than find, so do not reach for it unless the rules genuinely warrant it. Always pre-compile the regex into a std::regex object at namespace scope or pass it in as a parameter (as shown), never inline std::regex("...") inside a hot loop.
