Lots of pretty terrible answers here so I'll add mine (including test program):
#include <string>
#include <iostream>
#include <cstddef>
template<typename StringFunction>
void splitString(const std::string &str, char delimiter, StringFunction f) {
std::size_t from = 0;
for (std::size_t i = 0; i < str.size(); ++i) {
if (str[i] == delimiter) {
f(str, from, i);
from = i + 1;
}
}
if (from <= str.size())
f(str, from, str.size());
}
int main(int argc, char* argv[]) {
if (argc != 2)
return 1;
splitString(argv[1], ',', [](const std::string &s, std::size_t from, std::size_t to) {
std::cout << "`" << s.substr(from, to - from) << "`\n";
});
return 0;
}
Nice properties:
- No dependencies (e.g. boost)
- Not an insane one-liner
- Easy to understand (I hope)
- Handles spaces perfectly fine
- Doesn't allocate splits if you don't want to, e.g. you can process them with a lambda as shown.
- Doesn't add characters one at a time - should be fast.
- If using C++17 you could change it to use a
std::stringview
and then it won't do any allocations and should be extremely fast.
Some design choices you may wish to change:
- Empty entries are not ignored.
- An empty string will call f() once.
Example inputs and outputs:
"" -> {""}
"," -> {"", ""}
"1," -> {"1", ""}
"1" -> {"1"}
" " -> {" "}
"1, 2," -> {"1", " 2", ""}
" ,, " -> {" ", "", " "}