Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   C++ (http://www.programmingforums.org/forum15.html)
-   -   "split" function (http://www.programmingforums.org/showthread.php?t=5037)

uman Jul 23rd, 2005 1:46 AM

"split" function
 
Is there a C++ or C standard library function that splits an std::string (or char*) into words, based on a certain delimiter? What I'm looking for is something like this:

at the beginning, line == "the big blue dog ate food."
words is an array of std::strings

whatever_function(line,words,' ');

at the end, words should equal {"the","big","blue","dog","ate","food"}

InfoGeek Jul 23rd, 2005 4:13 AM

strtok can work for you.

Ancient Dragon Jul 23rd, 2005 6:46 AM

:

int main(int argc, char* argv[])
{
        string str = "the big blue dog ate food.";
        int pos;
        while((pos = str.find(' ')) > 0)
        {
                string sub = str.substr(0,pos);
                str = str.substr(pos+1);
                cout << sub << endl;
        }
       
        return 0;
}


Cerulean Jul 23rd, 2005 6:50 AM

No, not to my knowledge. Unfortunately strtok only works with single character delimiters and it takes a const char pointer argument instead of a std::string. The less const char pointers I see in my code, the happier I tend to be :P. You can also use std::getline to do this, but again that takes a single char as a delimiter.
Here's the simple function I wrote to do this.
:

// Returns a std::vector of the split strings
#include <vector>
#include <string>

std::vector<std::string> split(std::string str, std::string delimiter) {
    int i = 0;
    std::vector<std::string> stringvector;
    while(str.find(delimiter, i) != std::string::npos) {
        i = str.find(delimiter, i);
        stringvector.push_back(str.substr(0, i));
        str = str.substr(i + delimiter.size(), str.length() - (i + delimiter.size()));
        i += delimiter.size();
    }
    return stringvector;
}

Example usage:
:

int main() {
    std::string s = "This|||is|||fun|||isn't|||it";
    std::cout << split(s, "|||")[0] << "\n"; // prints 'This'
    return 0;
}


DaWei Jul 23rd, 2005 7:27 AM

Strtok takes multiple delimiters, but it is intended for use with arrays of char, not std strings. Furthermore, it alters the original, so even where one can use it, one may need to copy the original first. When PHP nabbed it as a utility, they burned off some of the warts.

uman Jul 23rd, 2005 2:17 PM

ok

getline + istringstream seems to be what I'm looking for.

Thanks all!

Shapeless Jul 23rd, 2005 7:21 PM

I would say boost/algorithm/string/split.hpp is what u need. its still no standart functions , but a lot of the boost libs will become standart in the 0x10 c++ standart and i m pretty sure that the string-algo lib will...
btw boost is so powerfull u should have a look or even learn to handle some parts.

like boost::split
the function gets a sequence,a collection and a prdicate, and an so called token compress mode type, but u dont need that one.
so for your purposes it would look like this

:

template<typename SequenceSequenceT, typename CollectionT,
            typename PredicateT>
      SequenceSequenceT &
      split(SequenceSequenceT &, CollectionT &, PredicateT,
            token_compress_mode_type = token_compress_off);

or shorter:
:

      split(SequenceSequenceT &, CollectionT &, PredicateT);
where for example the collections is a std::string and the sequence is a std::vector<std::string>
id just wrote this little testmain. i think its exactly what you ask for:
:

#include<iostream>
#include<string>
#include<vector>
#include<boost/algorithm/string.hpp>

#include<algorithm>//test output
#include<iterator>// test output


int main() {
        std::string line("hallo-this-is-a-string");
        std::vector<std::string> result;
        boost::split(result,line,boost::is_any_of("-"));
                      // puts the result of a split of line into the
                      // result container without things that match to the prediate
                      //"-" or in your case " "

        if(!result.empty())
                std::copy(result.begin(),result.end(),std::ostream_iterator<std::string>(std::cout,"\n"));
        return 0;
}

so here is the compare:
:

your wish:
function(container,string,delim);
solution:
split(container,string,predicate); where predicate is the delim...

as you can see its exactly the same u ask for. but since it is a template u
can use it on every containers convertable to each other.

DaWei Jul 23rd, 2005 9:12 PM

Quote:

I would say boost/algorithm/string/split.hpp is what u need. its still no standart functions , but a lot of the boost libs will become standart in the 0x10 c++ standart and i m pretty sure that the string-algo lib will...
Get real.

Ancient Dragon Jul 23rd, 2005 9:26 PM

The problem posted by OP is so simple -- Forget about using all those other complex templates that do nothing more than make the solution to the problem more complicated. You guys are making such a complicated solution out of something that is very trivel. :eek:

stevengs Jul 24th, 2005 6:04 AM

Quote:

Originally Posted by Ancient Dragon
The problem posted by OP is so simple -- Forget about using all those other complex templates that do nothing more than make the solution to the problem more complicated. You guys are making such a complicated solution out of something that is very trivel. :eek:

Yeah, I think I would go with std::string methods too.


All times are GMT -5. The time now is 4:27 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC