Iterating and printing

M

mikehulluk

Ok,
Imagine I have a class

class C
{

};

ostream& operator<<(ostream& o, const C& c) { ...}

I have a collection of these objects, in an STL list or vector and
want to do 2 things:
1/ Print all these objects to cout
2/ Write all these objects to a long string


Now, I wanted to try and use for_each and avoid my usual code of

stringstream s;
for( collection<C>::iterator it = Collection.begin(); it !=
Collection.end(); it++)
{
cout << *it;
s << *it;
}
string res = s.str();


So I tried a couple of options:

void printC(ostream& o, const C& c) { o << c;}
for_each( Collection.begin(), Collection.end(),
bind1st( fun_ptr( printC), cout) );

which wouldn't work because of a problem of refs to refs,


so i started on the second problem and created a class

class P
{
public:
P() { //Setup code }
stringstream s;
string getString(){ return s.str();}
void operator()(const C& c) { s << c; }
};

and tried to pass this:
P p;
for_each( Collection.begin(), Collection.end(), p );

which fails because we can't copy P, because it contains a
stringstream which can't be copied.

So i currently have

class Q
{
string s;
void operator()(const C& c) { stringstream ss; ss << c; s+=
ss.str(); }
};

Q q;
for_each( Collection.begin(), Collection.end(), q );

which, correct me if i'm wrong, seems like a very crude way of doing
it!

This seems like a fairly common task!
Any thoughts on the matter would be greatly appreiciated!


Michael
 
V

Victor Bazarov

Ok,
Imagine I have a class

class C
{

};

ostream& operator<<(ostream& o, const C& c) { ...}

I have a collection of these objects, in an STL list or vector and
want to do 2 things:
1/ Print all these objects to cout
2/ Write all these objects to a long string


Now, I wanted to try and use for_each and avoid my usual code of
[..]
Any thoughts on the matter would be greatly appreiciated!

Have you tried using 'ostream_iterator'? It should work well with
both 'cout' and any stringstream you can create.

V
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Ok,
Imagine I have a class

class C
{

};

ostream& operator<<(ostream& o, const C& c) { ...}

I have a collection of these objects, in an STL list or vector and
want to do 2 things:
1/ Print all these objects to cout
2/ Write all these objects to a long string


Now, I wanted to try and use for_each and avoid my usual code of

Don't know about for_each but std::copy can be quite useful together
with ostream_iterator mentioned by Victor:

int main()
{
std::vector<int> vec;
for (int i = 0; i < 10; ++i)
vec.push_back(i);

std::stringstream ss;
std::copy(vec.begin(), vec.end(),
std::eek:stream_iterator<int>(ss, " "));
std::copy(vec.begin(), vec.end(),
std::eek:stream_iterator<int>(std::cout, " "));
std::cout << "\n" << ss.str() << "\n";
return 0;
}
 
M

mikehulluk

Ok,
Imagine I have a class
class C
{

ostream& operator<<(ostream& o, const C& c) { ...}
I have a collection of these objects, in an STL list or vector and
want to do 2 things:
1/ Print all these objects to cout
2/ Write all these objects to a long string
Now, I wanted to try and use for_each and avoid my usual code of
[..]
Any thoughts on the matter would be greatly appreiciated!

Have you tried using 'ostream_iterator'? It should work well with
both 'cout' and any stringstream you can create.

V

Thanks Victor, I will give that a go!
 
M

mikehulluk

Don't know about for_each but std::copy can be quite useful together
with ostream_iterator mentioned by Victor:

int main()
{
std::vector<int> vec;
for (int i = 0; i < 10; ++i)
vec.push_back(i);

std::stringstream ss;
std::copy(vec.begin(), vec.end(),
std::eek:stream_iterator<int>(ss, " "));
std::copy(vec.begin(), vec.end(),
std::eek:stream_iterator<int>(std::cout, " "));
std::cout << "\n" << ss.str() << "\n";
return 0;

}

Thanks Erik, I'll give it a try!
 
J

James Kanze

Imagine I have a class
class C
{

};
ostream& operator<<(ostream& o, const C& c) { ...}
I have a collection of these objects, in an STL list or vector and
want to do 2 things:
1/ Print all these objects to cout
2/ Write all these objects to a long string
Now, I wanted to try and use for_each and avoid my usual code of

Forget for_each. It doesn't buy you anything here. (You can
use it, but you end up writing more code than if you wrote the
loop manually.)
stringstream s;
for( collection<C>::iterator it = Collection.begin(); it !=
Collection.end(); it++)
{
cout << *it;
s << *it;}

You don't really want to output to both streams in the same
loop, do you? And doubtlessly, you'll need a separator or some
other formatting structure as well.

Typically, I'd encapsulate the container in a class of my own
anyway, and then add something like:

std::eek:stream&
operator<<( std::eek:stream& dest, ContainerC const& source )
{
dest << '[' ;
for ( ContainerC::iterator it = source.begin() ;
it != source.end() ;
++ it ) {
if ( it != source.begin() ) {
dest << ", " ;
}
dest << *it ;
}
dest << ']' ;
return dest ;
}

As you can see, there's a bit more to it than just iterating
over the values; handling the separator is particularly
bothersome; the std::eek:stream_iterator got it wrong, and for that
reason are practically useless.
This seems like a fairly common task!

It is, but since formatting is so specific, it tends to be
written out explicitly each time it's needed.
 

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
474,301
Messages
2,571,549
Members
48,295
Latest member
JayKillian
Top