STL algorithm help

Discussion in 'C++' started by Dilip, May 4, 2006.

  1. Dilip

    Dilip Guest

    Hi

    I have a pretty simply task of splitting a std::string that has a comma
    separated list of names. I know the usual brute force method to do
    this (with basic_string::find_first_of and friends). However I am sure
    there is a way to do use std::copy along with ostream_iterator or
    istream_iterator. I tried various different combianations but I cannot
    quite figure out how to do it. Is there a way?

    I do know that...

    std::string str("name1,name2");
    vector<string> splitstrings;
    std::copy(<something goes here>, <anotehr iterator goes here>,
    splitstrings.begin());

    I tried a lot of embarassing things for the 1st 2 arguments of
    std::copy but couldnt quite get it to work the way I want it.
    I want to learn as much as possible about STL algorithms and am trying
    to restrict myself to them wherever possible instead of quickly
    reaching for the easiest method to do it.
     
    Dilip, May 4, 2006
    #1
    1. Advertising

  2. Dilip

    red floyd Guest

    Dilip wrote:
    > Hi
    >
    > I have a pretty simply task of splitting a std::string that has a comma
    > separated list of names. I know the usual brute force method to do
    > this (with basic_string::find_first_of and friends). However I am sure
    > there is a way to do use std::copy along with ostream_iterator or
    > istream_iterator. I tried various different combianations but I cannot
    > quite figure out how to do it. Is there a way?
    >
    >


    std::string s("comma,delimited,data");
    std::istringstream is(s);
    std::vector<string> v;
    std::string field;
    while (std::getline(is,field,','))
    v.push_back(field);
     
    red floyd, May 4, 2006
    #2
    1. Advertising

  3. Dilip wrote:
    > Hi
    >
    > I have a pretty simply task of splitting a std::string that has a comma
    > separated list of names. I know the usual brute force method to do
    > this (with basic_string::find_first_of and friends). However I am sure
    > there is a way to do use std::copy along with ostream_iterator or
    > istream_iterator. I tried various different combianations but I cannot
    > quite figure out how to do it. Is there a way?


    Boost.Tokenizer does a good job. See http://www.boost.org.


    Jonathan
     
    Jonathan Mcdougall, May 4, 2006
    #3
  4. Dilip

    Dilip Guest

    red floyd wrote:
    > Dilip wrote:
    > > Hi
    > >
    > > I have a pretty simply task of splitting a std::string that has a comma
    > > separated list of names. I know the usual brute force method to do
    > > this (with basic_string::find_first_of and friends). However I am sure
    > > there is a way to do use std::copy along with ostream_iterator or
    > > istream_iterator. I tried various different combianations but I cannot
    > > quite figure out how to do it. Is there a way?

    >
    > std::string s("comma,delimited,data");
    > std::istringstream is(s);
    > std::vector<string> v;
    > std::string field;
    > while (std::getline(is,field,','))
    > v.push_back(field);


    Floyd

    Thanks! I knew this method. Academically I would still love to know
    if its possible to use std::copy to do what I want.
    I cannot use Boost due to company policy issues.
     
    Dilip, May 4, 2006
    #4
  5. Dilip wrote:
    > red floyd wrote:
    > > Dilip wrote:
    > > > Hi
    > > >
    > > > I have a pretty simply task of splitting a std::string that has a comma
    > > > separated list of names. I know the usual brute force method to do
    > > > this (with basic_string::find_first_of and friends). However I am sure
    > > > there is a way to do use std::copy along with ostream_iterator or
    > > > istream_iterator. I tried various different combianations but I cannot
    > > > quite figure out how to do it. Is there a way?

    > >
    > > std::string s("comma,delimited,data");
    > > std::istringstream is(s);
    > > std::vector<string> v;
    > > std::string field;
    > > while (std::getline(is,field,','))
    > > v.push_back(field);

    >
    > Thanks! I knew this method. Academically I would still love to know
    > if its possible to use std::copy to do what I want.
    > I cannot use Boost due to company policy issues.


    Well using std::string's iterator, it's impossible. On top of my head,
    you could wrap up the iterator into a class of your own that implements
    operator++ (advances past the next separator) and operator* (returns a
    string from the current position to the next separator/end) and then

    std::copy(my_iter(s.begin()), my_iter(s.end()), std::back_insert(v));


    Jonathan
     
    Jonathan Mcdougall, May 4, 2006
    #5
  6. Dilip

    Dilip Guest

    Jonathan Mcdougall wrote:
    > Dilip wrote:
    > > red floyd wrote:
    > > Thanks! I knew this method. Academically I would still love to know
    > > if its possible to use std::copy to do what I want.
    > > I cannot use Boost due to company policy issues.

    >
    > Well using std::string's iterator, it's impossible. On top of my head,
    > you could wrap up the iterator into a class of your own that implements
    > operator++ (advances past the next separator) and operator* (returns a
    > string from the current position to the next separator/end) and then
    >
    > std::copy(my_iter(s.begin()), my_iter(s.end()), std::back_insert(v));


    Jonathan
    Thanks for the explanation. Its becomign clearer what is and what is
    not possible. I have a quick followup question. I gathered that I can
    do something like this using std::copy - that is, read a stream of
    input from cin (terminated by \n) and dump them into a vector like so:

    istream_iterator<int> readInput(cin);
    std::copy(readInput, istream_iterator<int>(), myvector.begin());

    cannot we use a similar analogy? an input string stream should be
    conceptually identical to a standard input stream, right? i did notice
    istream_iterator doesn't offer a way to specify a delimiter.
     
    Dilip, May 4, 2006
    #6
  7. Dilip

    Marcus Kwok Guest

    Dilip <> wrote:
    > Thanks for the explanation. Its becomign clearer what is and what is
    > not possible. I have a quick followup question. I gathered that I can
    > do something like this using std::copy - that is, read a stream of
    > input from cin (terminated by \n) and dump them into a vector like so:
    >
    > istream_iterator<int> readInput(cin);
    > std::copy(readInput, istream_iterator<int>(), myvector.begin());


    Almost:

    std::copy(readInput, istream_iterator<int>(), back_inserter(myvector));

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
     
    Marcus Kwok, May 4, 2006
    #7
  8. Dilip wrote:
    > Jonathan Mcdougall wrote:
    > > Dilip wrote:
    > > > red floyd wrote:
    > > > Thanks! I knew this method. Academically I would still love to know
    > > > if its possible to use std::copy to do what I want.
    > > > I cannot use Boost due to company policy issues.

    > >
    > > Well using std::string's iterator, it's impossible. On top of my head,
    > > you could wrap up the iterator into a class of your own that implements
    > > operator++ (advances past the next separator) and operator* (returns a
    > > string from the current position to the next separator/end) and then
    > >
    > > std::copy(my_iter(s.begin()), my_iter(s.end()), std::back_insert(v));

    >
    > Jonathan
    > Thanks for the explanation. Its becomign clearer what is and what is
    > not possible. I have a quick followup question. I gathered that I can
    > do something like this using std::copy - that is, read a stream of
    > input from cin (terminated by \n)


    by a whitespace, not necessarily \n.

    > and dump them into a vector like so:
    >
    > istream_iterator<int> readInput(cin);
    > std::copy(readInput, istream_iterator<int>(), myvector.begin());


    This should be

    std::istream_iterator<int> readInput(cin);
    std::copy(readInput, istream_iterator<int>(),
    std::back_inserter(myvector));

    > cannot we use a similar analogy?


    Yes, if your string is whitespace separated:

    std::string s = "aa bb cc";
    std::vector<std::string> v;
    std::istringstream iss(s);

    std::copy(
    std::istream_iterator<std::string>(iss),
    std::istream_iterator<std::string>(),
    std::back_inserter(v));

    No, if your string is something-else separated. You'll then have to
    either have a custom stream that stops on another separator or a custom
    iterator that does the job on a container.

    > an input string stream should be
    > conceptually identical to a standard input stream, right?


    Yes, a stream is a stream.

    > i did notice istream_iterator doesn't offer a way to specify a delimiter.


    The stream should provide this, not the iterator, which is merely a
    wrapper around operator>>. It is possible to specify a separator using
    member functions (such as istream::get()) or std::getline() for
    std::string.


    Jonathan
     
    Jonathan Mcdougall, May 4, 2006
    #8
  9. Dilip

    Tom Widmer Guest

    Dilip wrote:
    > Jonathan Mcdougall wrote:
    >
    >>Dilip wrote:
    >>
    >>>red floyd wrote:
    >>>Thanks! I knew this method. Academically I would still love to know
    >>>if its possible to use std::copy to do what I want.
    >>>I cannot use Boost due to company policy issues.

    >>
    >>Well using std::string's iterator, it's impossible. On top of my head,
    >>you could wrap up the iterator into a class of your own that implements
    >>operator++ (advances past the next separator) and operator* (returns a
    >>string from the current position to the next separator/end) and then
    >>
    >>std::copy(my_iter(s.begin()), my_iter(s.end()), std::back_insert(v));

    >
    >
    > Jonathan
    > Thanks for the explanation. Its becomign clearer what is and what is
    > not possible. I have a quick followup question. I gathered that I can
    > do something like this using std::copy - that is, read a stream of
    > input from cin (terminated by \n) and dump them into a vector like so:
    >
    > istream_iterator<int> readInput(cin);
    > std::copy(readInput, istream_iterator<int>(), myvector.begin());
    >
    > cannot we use a similar analogy? an input string stream should be
    > conceptually identical to a standard input stream, right? i did notice
    > istream_iterator doesn't offer a way to specify a delimiter.


    Actually, it does, though it is quite complicated. Have a look at this:

    http://groups.google.co.uk/group/mi..._frm/thread/711ee3e4cabab899/7b3c68d5bef58d39

    Tom
     
    Tom Widmer, May 5, 2006
    #9
  10. Dilip

    Dilip Guest

    Tom Widmer wrote:
    > Dilip wrote:
    > > Jonathan Mcdougall wrote:
    > >
    > >>
    > >>Well using std::string's iterator, it's impossible. On top of my head,
    > >>you could wrap up the iterator into a class of your own that implements
    > >>operator++ (advances past the next separator) and operator* (returns a
    > >>string from the current position to the next separator/end) and then
    > >>
    > >>std::copy(my_iter(s.begin()), my_iter(s.end()), std::back_insert(v));

    > >
    > >
    > > Jonathan
    > > Thanks for the explanation. Its becomign clearer what is and what is
    > > not possible. I have a quick followup question. I gathered that I can
    > > do something like this using std::copy - that is, read a stream of
    > > input from cin (terminated by \n) and dump them into a vector like so:
    > >
    > > istream_iterator<int> readInput(cin);
    > > std::copy(readInput, istream_iterator<int>(), myvector.begin());
    > >
    > > cannot we use a similar analogy? an input string stream should be
    > > conceptually identical to a standard input stream, right? i did notice
    > > istream_iterator doesn't offer a way to specify a delimiter.

    >
    > Actually, it does, though it is quite complicated. Have a look at this:
    >
    > http://groups.google.co.uk/group/mi..._frm/thread/711ee3e4cabab899/7b3c68d5bef58d39
    >

    Tom
    Thanks for the link. Its a little too much work for such a simple
    menial task. Atleast I learnt something new from that post.
    Thanks once again!
     
    Dilip, May 5, 2006
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ahmed Moustafa
    Replies:
    0
    Views:
    817
    Ahmed Moustafa
    Nov 15, 2003
  2. Wahoo
    Replies:
    5
    Views:
    578
    tom_usenet
    May 19, 2004
  3. Dennis
    Replies:
    1
    Views:
    2,626
    Dennis
    Jun 7, 2004
  4. Alexander Stippler
    Replies:
    5
    Views:
    7,554
    Alexander Stippler
    Jun 10, 2004
  5. Bapaiah Katepalli
    Replies:
    1
    Views:
    1,532
    Mike Treseler
    Jun 23, 2006
Loading...

Share This Page