|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Hi,
I'd like to use copy() to send the content of an integer container to cout. How can I make sure that /all/ of them are printed with width 2? #include <iostream> #include <iterator> int v[]={42,3,42}; using namespace std; int main(){ cout.width(2); copy(v,v+3,ostream_iterator<int>(cout," ")); cout<<endl; return 0; } gives 42 3 42 I'd like it to be 42 3 42 instead. I read in Stroustrup that width() only applies to the next output. I thought using format flags with setf would be the way to do it like when I want to output the integers in say octal. But there are no format "flags" for width. What can I do? Ralf |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
On Thu, 06 Dec 2007 17:27:13 +0100 in comp.lang.c++, Ralf Goertz
<r_goertz@expires-2006-11-30.arcornews.de> wrote, >I'd like to use copy() to send the content of an integer container to >cout. How can I make sure that /all/ of them are printed with width 2? You realize that by requiring std::copy you are doing it the hard way? Homework? You could define an adapter class that is implicitly constructed from the int, and use output_iterator<adapter> to call your code to do the formatting. |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
David Harmon wrote:
> Ralf Goertz wrote >>I'd like to use copy() to send the content of an integer container to >>cout. How can I make sure that /all/ of them are printed with width 2? > > You realize that by requiring std::copy you are doing it the hard > way? Homework? No, it's not homework. Reading this newsgroup I got the impression that using std::copy is the preferred way to output containers. So yes I could have used a loop to do it. That is not the point. I wonder why one can *permanently* switch an output stream to another base but not to a width other than 0. I thought that I had missed something, that's why I asked. > You could define an adapter class that is implicitly constructed > from the int, and use output_iterator<adapter> to call your code to > do the formatting. Okay, thanks. But that surely is "doing it the hard way". Ralf |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On Dec 6, 5:27 pm, Ralf Goertz
<r_goe...@expires-2006-11-30.arcornews.de> wrote: > I'd like to use copy() to send the content of an integer > container to cout. How can I make sure that /all/ of them are > printed with width 2? You can't. An ostream will never output a field with less width than is necessary to display it correctly, so any value outside the range of [-9...99] will display wider. > #include <iostream> > #include <iterator> > int v[]={42,3,42}; > using namespace std; > int main(){ > cout.width(2); > copy(v,v+3,ostream_iterator<int>(cout," ")); ostream_iterator is pretty worthless as classes go. You'll have to write your own if you want anything but the simplest formatting. (The implementation shouldn't be that difficult. Defining the interface so that you don't have to specify more than you need is far from trivial, however.) > cout<<endl; > return 0; > } > gives > 42 3 42 > I'd like it to be > 42 3 42 > instead. I read in Stroustrup that width() only applies to the > next output. That's the convention. You could write a class along the lines of: class FixedWidthInt { public: FixedWidthInt( int i ) : i( i ) {} friend std: stream& operator<<(std: stream& dest,FixedWidthInt const&obj ) { int w = dest.width() ; dest << obj.i ; dest.width( w ) ; return *dest ; } private: int i ; } ; and invoke: std::cout.width( 2 ) ; copy( v.begin(), v.end(), std: stream_iterator< FixedWidthInt >( std::cout ) ) ;I don't like it, though; it more or less changes the expected behavior of the ostream. Alternatively, if the width is always constant, you could use a template: template< int w > class FixedWidthInt { public: FixedWidthInt( int i ) : i( i ) {} friend std: stream& operator<<(std: stream& dest,FixedWidthInt const&obj ) { dest << std::setw( w ) << obj.i ; return *dest ; } private: int i ; } ; // ... copy( v.begin(), v.end(), std: stream_iterator< FixedWidthInt< 2 > >( std::cout ) ) ;This seems more acceptable to me, since you aren't counting on the width not changing. (I.e. this FixedWidthInt doesn't cause the width not to be reset, against expectations of a << operator. The preceding one does.) Finally, you could arrange that FixedWidthInt get the width, not from a template argument (which must be a compile time constant), but from a special format field, set by maniipulators. Something like the following: class FixedWidthBase { public: static long width( std::ios& stream ) { return stream.iword( index() ) ; } static long width( std::ios& stream, long newWidth ) { std::swap( stream.iword( index() ), newWidth ) ; return newWidth ; } private: static int index() { if ( ourWidth < 0 ) { ourWidth = std::ios::xalloc() ; } return ourWidth ; } static int ourWidth ; } ; int FixedWidthBase: urWidth = -1 ;template< typename T > class FixedWidth : private FixedWidthBase { public: FixedWidth( T const& value ) : myValue( value ) { } friend std: stream&operator<<( std: stream& dest,FixedWidth const& obj ) { dest << std::setw( width( dest ) ) << obj.myValue ; return dest ; } private: T myValue ; } ; int fixedwidth( std::ios& stream, int newWidth ) { return FixedWidthBase::width( stream, newWidth ) ; } // ... fixedwidth( std::cout, 3 ) ; std::copy( v.begin(), v.end(), std: stream_iterator< FixedWidth< int > >( std::cout,"\n" ) ) ; > I thought using format flags with setf would be the way to do > it like when I want to output the integers in say octal. But > there are no format "flags" for width. What can I do? See above. The real solution is to design and implement an ostream_iterator that is useful, but that's decidedly non-trivial. Failing that, I suspect that the template version of FixedWidth that I propose above might be a useful snippet. Another important thing to remember: there is no requirement that the type of the ostream_iterator be the same as the type you are writing. All you need is that the type you are writing be convertible to it. You can do an awful lot with user defined classes along the lines of those above. (It's far from perfect, but it solves a lot of problems with ostream_iterator.) -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
On Dec 7, 8:42 am, Ralf Goertz
<r_goe...@expires-2006-11-30.arcornews.de> wrote: > David Harmon wrote: > > Ralf Goertz wrote > >>I'd like to use copy() to send the content of an integer container to > >>cout. How can I make sure that /all/ of them are printed with width 2? > > You realize that by requiring std::copy you are doing it the hard > > way? Homework? > No, it's not homework. Reading this newsgroup I got the > impression that using std::copy is the preferred way to output > containers. So yes I could have used a loop to do it. That is > not the point. I wonder why one can *permanently* switch an > output stream to another base but not to a width other than 0. > I thought that I had missed something, that's why I asked. Alternatively, one might ask why one can set the length for a single output, but one can't set the base for a single output. I'm not really sure that there's much logic behind which is which: width is volatile, and all of the others permanent. But it's easy to get the other effect when you need it: all of my manipulators restore the original state in their destructor, for example (so any changes loose effect at the end of the full expression), and it's pretty easy to add state, and manipulators which manipulate it, as I did in my answer to your posting. > > You could define an adapter class that is implicitly > > constructed from the int, and use output_iterator<adapter> > > to call your code to do the formatting. > Okay, thanks. But that surely is "doing it the hard way". Not if it solves a general problem. Creating a class which outputs an int, always with width 2, is doing it the hard way. Creating a template class which outputs its type with the width it reads from an additional state variable may require a little more code to begin with (it took me about 15 minutes to write and test -- where as writing the loop would probably take less than a minute), but it could easily save work in the long run, if the problem is frequent. -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
James Kanze wrote:
> On Dec 6, 5:27 pm, Ralf Goertz > <r_goe...@expires-2006-11-30.arcornews.de> wrote: > >> I'd like to use copy() to send the content of an integer >> container to cout. How can I make sure that /all/ of them are >> printed with width 2? > > You could write a class along the lines of: > > class FixedWidthInt > { > public: > FixedWidthInt( int i ) : i( i ) {} > friend std: stream& operator<<(> std: stream& dest,> FixedWidthInt const&obj ) > { > int w = dest.width() ; > dest << obj.i ; > dest.width( w ) ; > return *dest ; > } > private: > int i ; > } ; > > and invoke: > > std::cout.width( 2 ) ; > copy( v.begin(), v.end(), > std: stream_iterator< FixedWidthInt >( std::cout ) ) ;That - to my surprise - didn't work. That is (after having changed "return *dest" to "return dest") it compiled but only wrote the first int with width 2 like my own attempt. gcc-Version 4.2.1 (SUSE Linux) > I don't like it, though; it more or less changes the expected > behavior of the ostream. Alternatively, if the width is always > constant, you could use a template: > > template< int w > > class FixedWidthInt > { > public: > FixedWidthInt( int i ) : i( i ) {} > friend std: stream& operator<<(> std: stream& dest,> FixedWidthInt const&obj ) > { > dest << std::setw( w ) << obj.i ; > return *dest ; > } > private: > int i ; > } ; > I also like this better and it worked (again after replacing "*dest" by "dest"). Something like that was what I expected to find in the standard. > This seems more acceptable to me, since you aren't counting on > the width not changing. (I.e. this FixedWidthInt doesn't cause > the width not to be reset, against expectations of a << > operator. The preceding one does.) > > Finally, you could arrange that FixedWidthInt get the width, not > from a template argument (which must be a compile time > constant), but from a special format field, set by > maniipulators. Something like the following: I think I would go with the template as I usually know at compile time what width I need. >> I thought using format flags with setf would be the way to do >> it like when I want to output the integers in say octal. But >> there are no format "flags" for width. What can I do? > > See above. The real solution is to design and implement an > ostream_iterator that is useful, but that's decidedly > non-trivial. Failing that, I suspect that the template version > of FixedWidth that I propose above might be a useful snippet. Yes it is. Thanks a lot. Ralf |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
On Dec 7, 6:18 pm, Ralf Goertz
<r_goe...@expires-2006-11-30.arcornews.de> wrote: > James Kanze wrote: > > On Dec 6, 5:27 pm, Ralf Goertz > > <r_goe...@expires-2006-11-30.arcornews.de> wrote: > >> I'd like to use copy() to send the content of an integer > >> container to cout. How can I make sure that /all/ of them are > >> printed with width 2? > > You could write a class along the lines of: > > class FixedWidthInt > > { > > public: > > FixedWidthInt( int i ) : i( i ) {} > > friend std: stream& operator<<(> > std: stream& dest,> > FixedWidthInt const&obj ) > > { > > int w = dest.width() ; > > dest << obj.i ; > > dest.width( w ) ; > > return *dest ; > > } > > private: > > int i ; > > } ; > > and invoke: > > > std::cout.width( 2 ) ; > > copy( v.begin(), v.end(), > > std: stream_iterator< FixedWidthInt >( std::cout ) ) ;> That - to my surprise - didn't work. That is (after having changed > "return *dest" to "return dest") it compiled but only wrote the first > int with width 2 like my own attempt. I did say "along the lines of". That's sort of a blatant admission that I just typed it in directly, without having tried it. The "return *dest" is proof of it as well. In fact, of course, the problem is that every output resets the width. So if there's any output between two FixedWidthInt, the width will get reset as well. Which makes it very, very fragile at best. > gcc-Version 4.2.1 (SUSE Linux) > > I don't like it, though; it more or less changes the expected > > behavior of the ostream. Alternatively, if the width is always > > constant, you could use a template: > > template< int w > > > class FixedWidthInt > > { > > public: > > FixedWidthInt( int i ) : i( i ) {} > > friend std: stream& operator<<(> > std: stream& dest,> > FixedWidthInt const&obj ) > > { > > dest << std::setw( w ) << obj.i ; > > return *dest ; > > } > > private: > > int i ; > > } ; > I also like this better and it worked (again after replacing > "*dest" by "dest"). Something like that was what I expected to > find in the standard. Do you mean, used by ostream_iterator, or as an additional formatting parameter. I've occasionally felt that there should be two copies of all of the formatting parameters: one volatile, and one sticky. The convention would be that << sets all of the volatile ones to the sticky values when it finishes. But of course, then, you'd need two sets of manipulators, etc. It's probably more complexity than it is worth. > > This seems more acceptable to me, since you aren't counting > > on the width not changing. (I.e. this FixedWidthInt doesn't > > cause the width not to be reset, against expectations of a > > << operator. The preceding one does.) > > Finally, you could arrange that FixedWidthInt get the width, > > not from a template argument (which must be a compile time > > constant), but from a special format field, set by > > maniipulators. Something like the following: > I think I would go with the template as I usually know at > compile time what width I need. I think that's usually the case. And the template form is considerably simpler (and doesn't have the threading issues of the more general form). -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
![]() |
| Outils de la discussion | |
|
|