Get splitter function to work

This topic is 4738 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Here is a function I wrote to take a string and split it into a vector<string> where each element is a word of the string - as in the returned elements of the input "this is the sample string! w007!" would be this is the sample string! w007! You can compile and see what the error is. For some reason, it doesn't always detect whitespace and reads through to several characters more than it should.
vector<string> GetWords(string words)
{
unsigned i=0;
unsigned start=0, length=0;
vector<string> ret;
while (i<words.length())
{
if (words!=' ')
{
//Found start of a new word...

start = i;
length = 0;

while (words[length]!=' ' && i+end<words.length())
++end;
++end;
ret.push_back(words.substr(start, length));
i+=length;
cout << "i: " << i << "\n";
start = length;
pause();
continue;
}
++i;
}
return ret;
}



Share on other sites
Your search for the next space after a word is borked.
It should probably be

while ( ( end < words.length() )
&& ( words[end] != ' ' ) )

The fatal condition first (wouldn't want to check a char beyond the string), and "end" as index to actually check the increasing char pos.

That's all i could see without compiling and testing.

Share on other sites
You could just use strtok()

ace

Share on other sites

1. Returning a vector is a bad idea. It's better to make it a void function which takes a non-const reference to a vector in which to place the arguments.

2. What's wrong with std::string::find_first_of()? I think it would simplify the code here greatly.

Here's how I just implemented this function. It worked in my C++ compiler.
#include <vector>#include <string>#include <iostream>using namespace std;void GetWords(string words, vector<string>& output){    output.erase(output.begin(), output.end()); //Clear the vector    //Possibly call output.reserve(blah) based on count() of spaces in the string, if the string is big, to avoid pointless reallocations    //(outside the scope of this answer ;)    string::size_type i = words.find_first_not_of(" "), j;    while(true){        j = words.find_first_of(" ", i);        if(j != string::npos){             output.push_back(words.substr(i, j-i));             i = words.find_first_not_of(" ", j + 1);             if(i == string::npos) return; //No more to be done here. Move along.        }else{             output.push_back(words.substr(i, string::npos));             return;        }    }}int main(){    vector<string> words;    GetWords(string("   Hello,    World,I am  testing my function for a reply tbh!!1one  "), words);    vector<string>::iterator i, e = words.end();     for(i = words.begin(); i != e; ++i){        cout << "Word: \"" << *i << "\"" << endl;    }}

It has a few benefits that I can think of:

• You could also use " \t\n" instead of " " to allow tabs and linefeeds to be counted as whitespace
• It handles leading and trailing whitespace properly

[EDIT]: Desertcube's solution is better. It does indeed work. [grin].

[Edited by - MrEvil on March 4, 2005 6:20:42 AM]

Share on other sites
I'm pretty confident that a stringstream object can do this for you. I'm not in front of a compiler at the moment, but try this:
#include <string>#include <sstream>#include <vector>std::vector<std::string> GetWords(const std::string & words){    std::vector<std::string> output;    std::stringstream buffer(words); //Create stringstream and initialise it with the contents of words    std::string word; //stores the exctracted single word    while (buffer >> word) //while there is input left to extract        output.push_back(word); //add word to the vector    return output;}

Think that should work, not 100% sure though!