0

In C++, without using any boost routines, we know how to:

  • split a string by a single char value or multiple char values

  • split a string by a single string value:

    void ParseStringByStringSeparator(string s, const string separator, vector<string>& result)
    {
        result.clear();
        size_t pos = 0;
        string token;
    
        while ((pos = s.find(separator)) != string::npos) {
            token = s.substr(0, pos);
            result.push_back(token);
            s.erase(0, pos + separator.length());
        }
        result.push_back(s);
    }
    

But how to split a string by multiple string values?

For example, If I have the following string value "Hello I am a String" and my separators are " " and "am" then I would like to obtain the following vector<string> value:

{"Hello","I","a","String"}

Any hint?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
baru
  • 401
  • 3
  • 9
  • 29
  • 2
    Split string using first delimiter, then split result using second delimiter. – ikleschenkov Jul 26 '17 at 16:06
  • 2
    Do a find and replace of all the other delimiters into the first one and the split using the first delimiter? – NathanOliver Jul 26 '17 at 16:08
  • That would work, but it could fail if the first delimiter was not a single character - because as the words are replaced it could inadvertently create another delimiter in the string. – CiscoIPPhone Jul 26 '17 at 16:18
  • The more I think about the more I think ikleschenkov is correct. Split the string using the first delimiter, then split each sub string by the next one and repeat that for each next one. – NathanOliver Jul 26 '17 at 16:23
  • 1
    What to do if a delimiter contains other delimiters? largest wins? – Galik Jul 26 '17 at 16:36

1 Answers1

0

This function do what you want to do. It basically iterate on the vector of delimiters, applying your function for each one :

vector<string> SplitStringMultipleStrParameters(string s,const vector<string>& separators) {

    //The result to be returned
    vector<string> result = { s };

    //Iterate on the list of separators, so for each separators
    for (const auto& sep : separators) {
        //toReplaceBy will be the next vector of strings where it will iterate
        vector<string> toReplaceBy, tempRes;

        //For each strings, we will split on "sep", the separator
        for (auto&a : result) {
            //Because of the result vector being cleared every time your function get called
            //It get in a temp vector that we will concatenate after
            ParseStringByStringSeparator(a, sep, tempRes);
            //Concatenation of theses vectors
            toReplaceBy.insert(toReplaceBy.end(), tempRes.begin(), tempRes.end());
        }

        //Erasing all strings that are empty. C++11 code here required because of the lambda
        toReplaceBy.erase(std::remove_if(toReplaceBy.begin(), toReplaceBy.end(),
            [](const std::string& i) {
            return i == "";
        }), toReplaceBy.end());

        //The vector containing strings to be splited is replaced by the split result on this iteration
        result = toReplaceBy;
        //And we will split those results using the next separator, if there's more separator to iterate on
    }
    return result;
}

Code to test :

string test = "Hello I am a string";

auto r = SplitStringMultipleStrParameters(test, { " ", "am" });

for (auto& a : r) {
    std::cout << a << '\n';
}

It needs to be compiled with a C++11 compiler, and need to include the <algorithm> header.

If your compiler does not compile C++11 code, here is the function :

vector<string> SplitStringMultipleStrParameters(string s,const vector<string>& separators) {
    vector<string> result = { s };
    for (const auto& sep : separators) {
        vector<string> toReplaceBy, tempRes;
        for (auto&a : result) {
            ParseStringByStringSeparator(a, sep, tempRes);
            toReplaceBy.insert(toReplaceBy.end(), tempRes.begin(), tempRes.end());
        }
        auto it = toReplaceBy.begin();
        while (it != toReplaceBy.end()) {
            if ((*it) == "")
                it = toReplaceBy.erase(it);
            else
                ++it;
        }
        result = toReplaceBy;
    }
    return result;
}
HatsuPointerKun
  • 637
  • 1
  • 5
  • 14