ostream_iterator annoyance

W

Wiseguy

consider the following:

ostream_iterator<int> i(cout,"");
cout << setw(3);
copy(int_list.begin(),int_list.end(),i);

the problem is that the field width restriction is only active for the first
element of int_list. after the first element is copied to cout the stream
setw(3) no longer has any affect.

why? and how to use stream_iterators that don't modify the state of setw()?


ostream iterators are of no use to me unless they can be used to
enforce more complicated text formatting than the
ostream_iterator(ostream&,string) constructor provides for.
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Wiseguy said:
ostream iterators are of no use to me unless they can be used to
enforce more complicated text formatting than the
ostream_iterator(ostream&,string) constructor provides for.

You can, for example, write a function that takes an int and returns an
object of a class that has an operator << that outputs the int with the
formatting required, and use std::transform with that function.

(Untested code)

class Format {
int num;
public:
Format (n) : num (n) { }
int get () const { return num; }
};

ostream & operator << (ostream & os, const Format & f)
{
os << setw (3) << f.get ();
}

Format make_format (int n)
{
return Format (n);
}

....

ostream_iterator <Format> i (cout,"");
transform (int_list.begin (), int_list.end (), i, make_format);
 
C

Chris \( Val \)

| consider the following:
|
| ostream_iterator<int> i(cout,"");
| cout << setw(3);
| copy(int_list.begin(),int_list.end(),i);
|
| the problem is that the field width restriction is only active for the first
| element of int_list. after the first element is copied to cout the stream
| setw(3) no longer has any affect.
|
| why? and how to use stream_iterators that don't modify the state of setw()?
|
|
| ostream iterators are of no use to me unless they can be used to
| enforce more complicated text formatting than the
| ostream_iterator(ostream&,string) constructor provides for.

If you only want a fixed width for each element, then you can
easily set the width of the string:

std::eek:stream_iterator<int> i( std::cout, " " );

Better yet, you might obtain it dynamically:

std::string Width( 4, ' ' );
std::eek:stream_iterator<int> i( std::cout, Width.c_str() );

Even better yet, what about using a function object ?:

# include <iostream>
# include <iomanip>
# include <ostream>
# include <list>
# include <algorithm>

inline void SpecialFormat( int n )
{
switch( n )
{
case 1 :
case 2 :
case 5 : std::cout << std::setw( 1 ) << n;
break;
case 10 : std::cout << std::setw( 5 ) << n;
break;
case 20 : std::cout << std::setw( 10 ) << n
<< std::setw( 3 )
<< std::setfill( '.' );
break;
case 30 : std::cout << std::setw( 15 ) << n;
break;
default:
std::cout << std::setw( 2 ) << std::left << n;
break;
}
}

int main()
{
std::list<int> int_list;
int_list.push_back( 10 );
int_list.push_back( 20 );
int_list.push_back( 30 );

std::for_each( int_list.begin(), int_list.end(), SpecialFormat );

return 0;
}

There are other possibilities too.

Hope this help's.

Cheers,
Chris Val
 
W

Wiseguy

Chris \( Val \) said:
If you only want a fixed width for each element, then you can
easily set the width of the string:

std::eek:stream_iterator<int> i( std::cout, " " );
Better yet, you might obtain it dynamically:

std::string Width( 4, ' ' );
std::eek:stream_iterator<int> i( std::cout, Width.c_str() );

how does that enforce a field width?...the above would just ALWAYS put
n-spaces after each item sent to the stream, right? that's not what I
want because my purpose is to use the iterators in stl algorithms like
copy.

Even better yet, what about using a function object ?:
inline void SpecialFormat( int n )
{
}

unfortunately the function object is not generic enough and needs to work with
stl algorithms. that's the whole purpose behind my quest: a generic ways of
using iterators that preserve the special formatting and (state) information of
the stream they are acting upon.

seems that for something like

o << setw(4) << something;

the field width restriction is only valid for the duration of the previous
statement and that adding another

o << somethign_else;

would NOT respect the previous setw()...that's the point of my contention.

so, a more related question would be "how to make something like setw()
permanent for the duration of a stream's existence?"
 
P

Pete Becker

Wiseguy said:
so, a more related question would be "how to make something like setw()
permanent for the duration of a stream's existence?"

That's not _really_ what you want. That would affect all insertions, not
just the ones you're currently interested in.

The way to do it is to write your own variation of ostream_iterator that
does a setw before each insertion. It's not very complicated, just a bit
tedious.
 
C

Chris \( Val \)

| "Chris \( Val \)" <[email protected]> scribbled on the stall wall:
| >
| > | >>
| > If you only want a fixed width for each element, then you can
| > easily set the width of the string:
| >
| > std::eek:stream_iterator<int> i( std::cout, " " );
|
| > Better yet, you might obtain it dynamically:
| >
| > std::string Width( 4, ' ' );
| > std::eek:stream_iterator<int> i( std::cout, Width.c_str() );
| >
|
| how does that enforce a field width?...the above would just ALWAYS put
| n-spaces after each item sent to the stream, right?

Right.

| that's not what I want because my purpose is to use the iterators
| in stl algorithms like copy.
|
| > Even better yet, what about using a function object ?:
| >>
| > inline void SpecialFormat( int n )
| > {
| > }
|
| unfortunately the function object is not generic enough and needs to work with
| stl algorithms. that's the whole purpose behind my quest: a generic ways of
| using iterators that preserve the special formatting and (state) information of
| the stream they are acting upon.
|
| seems that for something like
|
| o << setw(4) << something;
|
| the field width restriction is only valid for the duration of the previous
| statement and that adding another
|
| o << somethign_else;
|
| would NOT respect the previous setw()...that's the point of my contention.

Nor should it.

| so, a more related question would be "how to make something like setw()
| permanent for the duration of a stream's existence?"

I'm sorry, but I agree with 'Pete Becker' here.

Cheers,
Chris Val
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top