So, a good answer is already given.
I want to show some alternative solutions
Splitting a string into tokens is a very old task. There are many many solutions available. All have different properties. Some are difficult to understand, some are hard to develop, some are more complex, slower or faster or more flexible or not.
Alternatives
- Handcrafted, like yours, maybe hard to develop and error prone. See your question . . .
- Using old style
std::strtok function. Maybe unsafe. Maybe should not be used any longer std::getline. Most used implementation. But actually a "misuse" and not so flexible - Using dedicated modern function, specifically developed for this purpose, most flexible and good fitting into the STL environment and algortithm landscape. But slower
Please see 4 examples in one piece of code.
#include <iostream> #include <fstream> #include <sstream> #include <string> #include <regex> #include <algorithm> #include <iterator> #include <cstring> #include <forward_list> #include <deque> using Container = std::vector<std::string>; std::regex delimiter{ "," }; int main() { // Some function to print the contents of an STL container auto print = [](const auto& container) -> void { std::copy(container.begin(), container.end(), std::ostream_iterator<std::decay<decltype(*container.begin())>::type>(std::cout, " ")); std::cout << '\n'; }; // Example 1: Handcrafted ------------------------------------------------------------------------- { // Our string that we want to split std::string stringToSplit{ "aaa,bbb,ccc,ddd" }; Container c{}; // Search for comma, then take the part and add to the result for (size_t i{ 0U }, startpos{ 0U }; i <= stringToSplit.size(); ++i) { // So, if there is a comma or the end of the string if ((stringToSplit[i] == ',') || (i == (stringToSplit.size()))) { // Copy substring c.push_back(stringToSplit.substr(startpos, i - startpos)); startpos = i + 1; } } print(c); } // Example 2: Using very old strtok function ---------------------------------------------------------- { // Our string that we want to split std::string stringToSplit{ "aaa,bbb,ccc,ddd" }; Container c{}; // Split string into parts in a simple for loop #pragma warning(suppress : 4996) for (char* token = std::strtok(const_cast<char*>(stringToSplit.data()), ","); token != nullptr; token = std::strtok(nullptr, ",")) { c.push_back(token); } print(c); } // Example 3: Very often used std::getline with additional istringstream ------------------------------------------------ { // Our string that we want to split std::string stringToSplit{ "aaa,bbb,ccc,ddd" }; Container c{}; // Put string in an std::istringstream std::istringstream iss{ stringToSplit }; // Extract string parts in simple for loop for (std::string part{}; std::getline(iss, part, ','); c.push_back(part)) ; print(c); } // Example 4: Most flexible iterator solution ------------------------------------------------ { // Our string that we want to split std::string stringToSplit{ "aaa,bbb,ccc,ddd" }; Container c(std::sregex_token_iterator(stringToSplit.begin(), stringToSplit.end(), delimiter, -1), {}); // // Everything done already with range constructor. No additional code needed. // print(c); // Works also with other containers in the same way std::forward_list<std::string> c2(std::sregex_token_iterator(stringToSplit.begin(), stringToSplit.end(), delimiter, -1), {}); print(c2); // And works with algorithms std::deque<std::string> c3{}; std::copy(std::sregex_token_iterator(stringToSplit.begin(), stringToSplit.end(), delimiter, -1), {}, std::back_inserter(c3)); print(c3); } return 0; }