Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Saving old stream format and restoring it

Reply
Thread Tools

Saving old stream format and restoring it

 
 
Marcus Kwok
Guest
Posts: n/a
 
      02-17-2006
How do you save the formatting options for a stream? In the program
below, notice that when I define my operator<<() for the custom type, it
permanently changes the output format of the stream:

#include <iostream>
#include <iomanip>

struct Data {
double d;
};

std:stream&
operator<<(std:stream& o, const Data& d)
{
//std:stream old;
//old.copyfmt(o);
o << "during: " << std::fixed << std::setprecision(3) << d.d;
//o.copyfmt(old);
return o;
}

int main()
{
Data d;
d.d = 3.14159;

double dd;
dd = 3.14159;
std::cout << "before: " << dd << '\n';
std::cout << d << '\n';
std::cout << " after: " << dd << '\n';

return 0;
}

output:
before: 3.14159
during: 3.142
after: 3.142


When I uncomment the lines in operator<<(), I get a "no appropriate
default constructor available" error, and when I tried

std:stream old(o);

I get a "no copy constructor available or copy constructor is declared
'explicit'" error.


So, how do I save the old formatting options for the stream, and restore
them before returning?

--
Marcus Kwok
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      02-17-2006
Marcus Kwok wrote:

> How do you save the formatting options for a stream? In the program
> below, notice that when I define my operator<<() for the custom type, it
> permanently changes the output format of the stream:
>
> #include <iostream>
> #include <iomanip>
>
> struct Data {
> double d;
> };
>
> std:stream&
> operator<<(std:stream& o, const Data& d)
> {
> //std:stream old;
> //old.copyfmt(o);
> o << "during: " << std::fixed << std::setprecision(3) << d.d;
> //o.copyfmt(old);
> return o;
> }
>
> int main()
> {
> Data d;
> d.d = 3.14159;
>
> double dd;
> dd = 3.14159;
> std::cout << "before: " << dd << '\n';
> std::cout << d << '\n';
> std::cout << " after: " << dd << '\n';
>
> return 0;
> }
>
> output:
> before: 3.14159
> during: 3.142
> after: 3.142
>
>
> When I uncomment the lines in operator<<(), I get a "no appropriate
> default constructor available" error, and when I tried
>
> std:stream old(o);
>
> I get a "no copy constructor available or copy constructor is declared
> 'explicit'" error.
>
>
> So, how do I save the old formatting options for the stream, and restore
> them before returning?
>


Just don't change them:

#include <iostream>
#include <iomanip>
#include <sstream>

struct Data {
double d;
};

std:stream&
operator<<(std:stream& o, const Data& d)
{
std::stringstream str;
str << "during: " << std::fixed << std::setprecision(3) << d.d;
o << str.str();
return o;
}

int main()
{
Data d;
d.d = 3.14159;

double dd;
dd = 3.14159;
std::cout << "before: " << dd << '\n';
std::cout << d << '\n';
std::cout << " after: " << dd << '\n';

return 0;
}


Best

Kai-Uwe Bux
 
Reply With Quote
 
 
 
 
Dietmar Kuehl
Guest
Posts: n/a
 
      02-17-2006
Marcus Kwok wrote:
> std:stream&
> operator<<(std:stream& o, const Data& d)
> {
> //std:stream old;


Use 'std:stream old(0);' instead: the constructor of 'std:stream'
requires a stream buffer but this can be null.
--
<private.php?do=newpm&u=> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
 
Reply With Quote
 
Dietmar Kuehl
Guest
Posts: n/a
 
      02-17-2006
Kai-Uwe Bux wrote:
> Just don't change them:


> std:stream&
> operator<<(std:stream& o, const Data& d)
> {
> std::stringstream str;
> str << "during: " << std::fixed << std::setprecision(3) << d.d;
> o << str.str();
> return o;
> }


This doesn't work: for example, when called using code like this
it behaves in unexpected ways:

std::cout << std::showpos << d;
--
<private.php?do=newpm&u=> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
 
Reply With Quote
 
Neil Cerutti
Guest
Posts: n/a
 
      02-17-2006
On 2006-02-17, Dietmar Kuehl <> wrote:
> Marcus Kwok wrote:
>> std:stream&
>> operator<<(std:stream& o, const Data& d)
>> {
>> //std:stream old;

>
> Use 'std:stream old(0);' instead: the constructor of 'std:stream'
> requires a stream buffer but this can be null.


I was going to suggest:

std:stream::ios_type old;

The docs say it can't be used until init is called, but it's not clear
if that means you can't simply copy format information in and then out
again.

If you wind up needing to call init before copyfmt, then yucky.

--
Neil Cerutti
A billion here, a billion there, sooner or later it adds up to
real money. --Everett Dirksen
 
Reply With Quote
 
Dietmar Kuehl
Guest
Posts: n/a
 
      02-17-2006
Neil Cerutti wrote:

> I was going to suggest:
>
> std:stream::ios_type old;


I have no idea what the above is...? Are you referring to
'std::ios_base'? This cannot hold the complete format and I
don't think it is equipped with a 'copyfmt()' member function.
The other candidate would be 'std::ios'. However:

> If you wind up needing to call init before copyfmt, then yucky.


The design of the initialization of 'std::ios_base' and 'std::ios'
sucks^H^H^H^H^His suboptimal and you indeed need to call 'init()'
before you can do anything to 'std::ios'. In particular, a call
to 'init()' is strictly required even to destruct the object (the
standard is explicit about this in lib.basic.ios.cons paragraph 2,
second sentence).
--
<private.php?do=newpm&u=> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
 
Reply With Quote
 
Marcus Kwok
Guest
Posts: n/a
 
      02-17-2006
Dietmar Kuehl <> wrote:
> Marcus Kwok wrote:
>> std:stream&
>> operator<<(std:stream& o, const Data& d)
>> {
>> //std:stream old;

>
> Use 'std:stream old(0);' instead: the constructor of 'std:stream'
> requires a stream buffer but this can be null.


Nice, this seems to work great. Thanks.

--
Marcus Kwok
 
Reply With Quote
 
Dietmar Kuehl
Guest
Posts: n/a
 
      02-17-2006
Marcus Kwok wrote:
> Dietmar Kuehl <> wrote:
>> Use 'std:stream old(0);' instead: the constructor of 'std:stream'
>> requires a stream buffer but this can be null.

>
> Nice, this seems to work great. Thanks.


Note, however, this creation of a stream object is relatively
involved. At the very least it initialized quite a few member
variables and it might even do memory allocations. Thus, if you
need to save the format frequently you might want to consider
using just one stream object, e.g. by using a function static
object:

{
static std:stream old(0);
...
}

This object will only be constructed once. Of course, it will
also cause problems in multi-threaded code.
--
<private.php?do=newpm&u=> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
 
Reply With Quote
 
Neil Cerutti
Guest
Posts: n/a
 
      02-17-2006
On 2006-02-17, Dietmar Kuehl <> wrote:
> Neil Cerutti wrote:
>
>> I was going to suggest:
>>
>> std:stream::ios_type old;

>
> I have no idea what the above is...? Are you referring to
> 'std::ios_base'? This cannot hold the complete format and I
> don't think it is equipped with a 'copyfmt()' member function.
> The other candidate would be 'std::ios'. However:


Yes, thanks for the correction. I had meant to use a basic_ios type.

>> If you wind up needing to call init before copyfmt, then yucky.

>
> The design of the initialization of 'std::ios_base' and 'std::ios'
> sucks^H^H^H^H^His suboptimal and you indeed need to call 'init()'
> before you can do anything to 'std::ios'. In particular, a call
> to 'init()' is strictly required even to destruct the object (the
> standard is explicit about this in lib.basic.ios.cons paragraph 2,
> second sentence).


So there's a default constructor because...

No wonder Stroustrup doesn't cover this stuff.

--
Neil Cerutti
 
Reply With Quote
 
Marcus Kwok
Guest
Posts: n/a
 
      02-17-2006
Dietmar Kuehl <> wrote:
> Marcus Kwok wrote:
>> Dietmar Kuehl <> wrote:
>>> Use 'std:stream old(0);' instead: the constructor of 'std:stream'
>>> requires a stream buffer but this can be null.

>>
>> Nice, this seems to work great. Thanks.

>
> Note, however, this creation of a stream object is relatively
> involved. At the very least it initialized quite a few member
> variables and it might even do memory allocations. Thus, if you
> need to save the format frequently you might want to consider
> using just one stream object, e.g. by using a function static
> object:
>
> {
> static std:stream old(0);
> ...
> }
>
> This object will only be constructed once. Of course, it will
> also cause problems in multi-threaded code.


Oh, I see. So, for example, if I had a

std::vector<Data> v;

and did a

std::copy(v.begin(), v.end(), std:stream_iterator<Data>(std::cout, "\n"));

then it would have to create/destroy a new std:stream for every
element in the vector, correct? That does seem like quite a bit of
overhead.

The static member/multithreading issue is also significant, but since
that is OT here (until they add concurrency to the standard) I can defer
that argument to another place and time.

It would be nice if the standard had a lightweight "format" class to
store this in.

This question was mainly academic for me, and due to the two issues
above, it looks like it may not be possible to have a completely
satisfactory solution that can be used in production code. I guess I
should just stick to explicitly formatting where needed.

--
Marcus Kwok
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
IE 7 - saving and restoring History - What files do I need to keep ? me Computer Support 16 10-16-2009 02:46 AM
Saving and restoring streampos's Wolfgang Thomsen C++ 1 04-26-2007 01:21 PM
Re: Saving and restoring the desktop? Pennywise@DerryMaine.Gov Computer Support 3 10-16-2006 09:08 AM
Help with saving and restoring program state Jacob H Python 4 01-25-2005 11:16 PM
Saving and restoring with YAML Ben Giddings Ruby 2 10-01-2003 04:53 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57