STL algorithm help

D

Dilip

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.
 
R

red floyd

Dilip said:
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);
 
J

Jonathan Mcdougall

Dilip said:
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
 
D

Dilip

red said:
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.
 
J

Jonathan Mcdougall

Dilip said:
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
 
D

Dilip

Jonathan said:
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.
 
M

Marcus Kwok

Dilip said:
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));
 
J

Jonathan Mcdougall

Dilip said:
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);
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
 
T

Tom Widmer

Dilip said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top