1

There are a few examples about this question. However most of the answers are not what I am looking for.

I am looking for a way to implement an efficient and easy function rather than using boost or any other non STL libraries. If you ask me why, in most coding competitions and interviews, you are not allowed to use them.

Here is the closest that I can approach:

vector<string> SplitString(const char *str, char c)
{
    vector<string> result;
    do {
        const char *begin = str;
        while(*str != c && *str) {
            str++;
        }
        result.push_back(string(begin, str));
    } while (0 != *str++);
    return result;
}

int main() {

    string mainString = "This is a sentence. Another sentence. The third sentence. This is the last sentence.";
    vector<string> sentences;
    sentences = SplitString(mainString.c_str(), '.');
    while (!sentences.empty()) {
        cout << sentences.back() << endl;
        sentences.pop_back();
    }
    return 0;
}

Now the problem with this is, it can only have a char delimiter not string. I have thought of implementing a few ways but they seemed way too complex. The easiest one that I thought was, convert delimiter to char array use c as the first char of the delimiter char array after this:

while(*str != c && *str) {
    str++;
}
const char *beginDelim = *cArr;
while(1) {
    if (*str == *cArr && *str && *cArr) {
       str++;
       cArr++;
    }
    else if (!*cArr) {
        break;
    }
    else if (*cArr) {
        cArr = beginDelim;
    }
}

And the code continues from result.push_back() part.

So I was wondering if are there any way to implement an efficient and easy function for splitting a string with a string delimiter?

Sarp Kaya
  • 3,686
  • 21
  • 64
  • 103
  • So you want a string as a delimiter? – Aravind Jul 12 '13 at 15:28
  • Sorry, the question was a bit unclear, edited the last sentence. – Sarp Kaya Jul 12 '13 at 15:30
  • Yes, there are many ways. What have you tried so far? – PlasmaHH Jul 12 '13 at 15:32
  • http://stackoverflow.com/q/236129/2436175, in particular http://stackoverflow.com/a/237280/2436175 – Antonio Jul 12 '13 at 15:33
  • why don't you just use string::find()? also you are talking about efficiency, but you are copying your substrings to a vector of string - why not a struct containing original string and vector of indices? – aryan Jul 12 '13 at 15:34
  • @Antonio, as ABCD commented in that answer that you have given, does not store the result in a data structure, therefore it is not what I am looking for – Sarp Kaya Jul 12 '13 at 15:35
  • @SarpKaya Are you sure? There is a second part of the function, in which he puts stuff in a vector – Antonio Jul 12 '13 at 15:38
  • @Antonio, the second part does not include any delimiter. So the solution is either including delimiter but not storing results or storing results but excluding delimiter. – Sarp Kaya Jul 12 '13 at 15:41
  • @SarpKaya So what about this http://stackoverflow.com/a/236803/2436175 – Antonio Jul 12 '13 at 15:49
  • @Antonio, it is not any better than mine as it uses a char as a delimiter. In fact it is worse because it is harder to implement. – Sarp Kaya Jul 12 '13 at 15:52
  • see the [Boyer-Moore algorithm](http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm) for the fast way to find those substrings, pushing the bits before and after onto a vector is.. already shown – gbjbaanb Mar 28 '14 at 17:54

5 Answers5

0

Generally speaking, a string is a char pointer. So you should search for the first character in the delimeter, then check the very next character. Also in looking at your code I am not sure that while (0 != *str++) is doing what you think it is. I think you mean for it to be null terminated.

Kizl
  • 63
  • 2
  • 8
0

something like this should do it:

vector<string> SplitString(const char* str,const char* d) {
  vector<string> result;
  size_t len = strlen(d);
  const char* start = str;
  while ( str = strstr(start,d) ) {
    result.push_back(string(start,len));
    start = str + len;
  }
  result.push_back(start);
  return result;
}
Tiemo Jung
  • 136
  • 1
  • 5
  • warning: suggest parentheses around assignment used as truth value for this line " while ( str = strstr(start,d) ) {" – Sarp Kaya Jul 13 '13 at 02:53
0

How's this:

#include <vector>
#include <algorithm>
#include <string>

using namespace std;

vector<string> SplitString(const string &str, const string &delim)
{
    vector<string> ret;
    string::const_iterator prev = str.begin();

    for (string::const_iterator i = str.begin(); i < str.end() - delim.length()+1; ++i)
    {
        if (equal(delim.begin(), delim.end(), i)) {
            ret.push_back(string(prev,i));
            i += delim.length()-1;
            prev = i+1;
        }
    }

    ret.push_back(string(prev,str.end()));

    return ret;
}
JoshG79
  • 1,685
  • 11
  • 14
0
#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector<string> SplitString(string str, const string &delim) {
    vector<string> result;
    size_t found;
    while((found = str.find(delim)) != string::npos) {
        result.push_back(str.substr(0, found));
        str = str.substr(found + delim.size());
    }
    return result;
}

int main() {
    string mainString = "This is a sentence. Another sentence. The third sentence. This is the last sentence.";
    vector<string> sentences;

    sentences = SplitString(mainString, ".");

    for(auto& sentence : sentences) {
        cout << sentence << endl;   
    }
    return 0;
}
nOvoid
  • 109
  • 1
  • 9
  • Note: if the input string does not end with the specified delimiter, this code will not push the final substring into the vector. Once `str.find(delim)` returns `string::npos`, `str` should be pushed as-is if it is not an empty string. – Remy Lebeau Aug 25 '21 at 17:56
0
vector<string>split(string str, const char d){
    string temp;
    vector<string>vct;
    for(int i = 0; str[i] != '\0'; i++){
        if(str[i] != d){
            temp += str[i];
        }else if(!empty(temp)){
                vct.push_back(temp), temp.clear();
        }
    }
    vct.push_back(temp);
    return vct;
}

Takes two arguments

  • const char d as delimiter.
  • string str as string to be splitted.

stores splitted string in a vector and returns it. Although, I'm not sure about efficiency of this code. :)

Vinay_GB
  • 1
  • 1
  • 3