2

I would like to be able to split a string into two parts, left and right, at the first occurance of separator. For example, with # as separator left#right#more would result in left and right#more.

I have an method to do it:

void misc::split(const string &input, string &left, string &right, char separator)
{
    int index = input.find(separator);
    if (index == string::npos)
    {
        left = input;
        right.erase();
    }
    else
    {
        right = input.substr(index + 1);
        left = input.substr(0, index);
    }
}

Now I have started using Boost and would like to compress this rather lengthy code to something more elegant. I know about boost::split(), but that gives me three parts in the initial example (left, right and more).

Any suggestions?

Anders
  • 8,307
  • 9
  • 56
  • 88
  • You may be instered in this [proposal](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3510.html) and [this](http://stackoverflow.com/questions/5734304/c-boost-split-string). – Richard Dally Aug 28 '15 at 12:20

1 Answers1

5

I predict it's not going to be significantly better, because if the Intrinsic Complexity.

Nevertheless, here is a sample based on spirit:

static void split(const std::string &input, std::string &left, std::string &right, char separator)
{
    using namespace boost::spirit::qi;

    parse(input.begin(), input.end(), *~char_(separator) >> separator >> *char_, left, right);
}

With full test:

Live On Coliru

#include <boost/spirit/include/qi.hpp>

struct misc {
    static void split(const std::string &input, std::string &left, std::string &right, char separator)
    {
        using namespace boost::spirit::qi;

        parse(input.begin(), input.end(), *~char_(separator) >> separator >> *char_, left, right);
    }
};

int main() {
    for (std::string s : {
            "",
            "a",
            "a;",
            "a;b",
            ";b",
            ";",
            "a;b;",
            ";;" })
    {
        std::string l,r;
        misc::split(s,l,r,';');
        std::cout << "'" << s << "'\t-> l:'" << l << "'\tr:'" << r << "'\n";
    }
}

Prints:

''  -> l:'' r:''
'a' -> l:'a'    r:''
'a;'    -> l:'a'    r:''
'a;b'   -> l:'a'    r:'b'
';b'    -> l:'' r:'b'
';' -> l:'' r:''
'a;b;'  -> l:'a'    r:'b;'
';;'    -> l:'' r:';'
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks for the tip! Not sure I understand how it works, but that just mean I have some fun reading up to do. :-) At least I can tell that it (a) works, and (b) is fewer lines of code. – Anders Aug 28 '15 at 12:20
  • Yeah. Spirit is not something to "grok at sight". It's conceptually simple though. You should get there reading just the tutorial introduction. Indeed, I started with "I predict it's not going to be significantly better" for a reason. I'd personally write pretty much what you had. – sehe Aug 28 '15 at 12:22