473,396 Members | 1,774 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Saving old stream format and restoring it

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::ostream&
operator<<(std::ostream& o, const Data& d)
{
//std::ostream 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::ostream 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
Feb 17 '06 #1
15 3697
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::ostream&
operator<<(std::ostream& o, const Data& d)
{
//std::ostream 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::ostream 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::ostream&
operator<<(std::ostream& 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
Feb 17 '06 #2
Marcus Kwok wrote:
std::ostream&
operator<<(std::ostream& o, const Data& d)
{
//std::ostream old;


Use 'std::ostream old(0);' instead: the constructor of 'std::ostream'
requires a stream buffer but this can be null.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Feb 17 '06 #3
Kai-Uwe Bux wrote:
Just don't change them: std::ostream&
operator<<(std::ostream& 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;
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Feb 17 '06 #4
On 2006-02-17, Dietmar Kuehl <di***********@yahoo.com> wrote:
Marcus Kwok wrote:
std::ostream&
operator<<(std::ostream& o, const Data& d)
{
//std::ostream old;


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


I was going to suggest:

std::ostream::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
Feb 17 '06 #5
Neil Cerutti wrote:
I was going to suggest:

std::ostream::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).
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Feb 17 '06 #6
Dietmar Kuehl <di***********@yahoo.com> wrote:
Marcus Kwok wrote:
std::ostream&
operator<<(std::ostream& o, const Data& d)
{
//std::ostream old;


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


Nice, this seems to work great. Thanks.

--
Marcus Kwok
Feb 17 '06 #7
Marcus Kwok wrote:
Dietmar Kuehl <di***********@yahoo.com> wrote:
Use 'std::ostream old(0);' instead: the constructor of 'std::ostream'
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::ostream old(0);
...
}

This object will only be constructed once. Of course, it will
also cause problems in multi-threaded code.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Feb 17 '06 #8
On 2006-02-17, Dietmar Kuehl <di***********@yahoo.com> wrote:
Neil Cerutti wrote:
I was going to suggest:

std::ostream::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
Feb 17 '06 #9
Dietmar Kuehl <di***********@yahoo.com> wrote:
Marcus Kwok wrote:
Dietmar Kuehl <di***********@yahoo.com> wrote:
Use 'std::ostream old(0);' instead: the constructor of 'std::ostream'
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::ostream 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::ostream_iterator<Data>(std::cout, "\n"));

then it would have to create/destroy a new std::ostream 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
Feb 17 '06 #10
Marcus Kwok wrote:
How do you save the formatting options for a stream? In the program


See the boost io_state_saver library at
http://www.boost.org/libs/io/doc/ios_state.html

Jeff Flinn
Feb 17 '06 #11
Dietmar Kuehl wrote:
Kai-Uwe Bux wrote:
Just don't change them:

std::ostream&
operator<<(std::ostream& 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;


Good catch. Thanks.

So, what about:

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

Although, that is probably less efficient than saving the old streams state
and reinstalling it afterwards.
Best

Kai-Uwe Bux
Feb 18 '06 #12
"Jeff Flinn" <NO****@nowhere.com> wrote in news:dt57kp$l2s$1
@bluegill.adi.com:
Marcus Kwok wrote:
How do you save the formatting options for a stream? In the program


See the boost io_state_saver library at
http://www.boost.org/libs/io/doc/ios_state.html


Egad, these guys have a library for everything !
:-)

--
Life is complex, with real and imaginary parts.
Feb 18 '06 #13
Marcus Kwok wrote:
Oh, I see. So, for example, if I had a

std::vector<Data> v;

and did a

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

then it would have to create/destroy a new std::ostream for every
element in the vector, correct? That does seem like quite a bit of
overhead.
Indeed. Of course, the above vector is empty so no harm is done :-)
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.
I haven't played with it but in theory, at least, you could use a
pointer to stream in thread local storage. In addition, you might,
of course, put the state restoration code not into the formatting
function but into the calling function.
It would be nice if the standard had a lightweight "format" class to
store this in.


Yes, indeed. Boost has apparently something but I haven't used that
class either.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Feb 18 '06 #14
Kai-Uwe Bux wrote:
So, what about:

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

Although, that is probably less efficient than saving the old streams
state and reinstalling it afterwards.


Indeed: it even constructs at least one more object requiring
dynamic memory allocation (the string). In fact, with the given
changes of merely setting the formatting flags and the precision,
it might be best to simply restore just them:

std::ostream&
operator<< (std::ostream& o, Data const& d)
{
std::ios_base::fmtflags flags = o.setf(std::ios_base::fixed);
std::streamsize precision = o.precision(3);
o << "during: " << d.d;
o.precision(precision);
o.flags(flags);
}
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Feb 19 '06 #15
Dietmar Kuehl <di***********@yahoo.com> wrote:
Kai-Uwe Bux wrote:
So, what about:

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

Although, that is probably less efficient than saving the old streams
state and reinstalling it afterwards.


Indeed: it even constructs at least one more object requiring
dynamic memory allocation (the string). In fact, with the given
changes of merely setting the formatting flags and the precision,
it might be best to simply restore just them:

std::ostream&
operator<< (std::ostream& o, Data const& d)
{
std::ios_base::fmtflags flags = o.setf(std::ios_base::fixed);
std::streamsize precision = o.precision(3);
o << "during: " << d.d;
o.precision(precision);
o.flags(flags);
}


This seems elegant; only saving and restoring the things that get
modified.

--
Marcus Kwok
Feb 20 '06 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Jacob H | last post by:
Hello list... I'm developing an adventure game in Python (which of course is lots of fun). One of the features is the ability to save games and restore the saves later. I'm using the pickle...
2
by: Von Shean | last post by:
I have a requirement to save web pages from a different site on to my server as mht files ...and later i would need to email them to different recipients. I am using c# for my development....
3
by: cdj | last post by:
Hi all, I've got a picturebox on a form, and a save button. When I go to save, the app craps out with the following error: ================== An unhandled exception of type...
2
by: Peder Y | last post by:
Say I have several images, a jpg a gif and a bmp. Now, I want to save these files to a single binary file. I store the images in, say, Image img1, img2, img3; 1) How can I retrieve the size...
4
by: Andrew Inwards | last post by:
Is it possible to save a MS Word document in a string? I suspect not because Ive tried saving it in using various encoding formats and it always gets corrupted. Thanks Andrew
0
by: Dennis | last post by:
I have the following: Dim stream As New IO.MemoryStream fmParent.Icon = icon.FromHandle(New IntPtr(retval)) frmParent.Icon.Save(stream) 'RESIZE ICON to 16 x 16 Dim im As Image im =...
1
by: Tom | last post by:
I have a large application; lots of forms, multiple dynamic DLLs, etc. I also have, in the appliation, a general 'Preferences' class object (which is in itself a separate DLL, and I just include a...
4
by: Pedro Leite | last post by:
Good Afternoon. the code below is properly retreiving binary data from a database and saving it. but instead of saving at client machine is saving at the server machine. what is wrong with my...
1
by: Wolfgang Thomsen | last post by:
Hello, I need to process very large files which are made of blocks of data. To speed up the reading of a specific block, I let my program note down the streampos of each block's beginning in a...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.