Restore the State of Std::Cout After Manipulating It

Restore the state of std::cout after manipulating it

you need to #include <iostream> or #include <ios> then when required:

std::ios_base::fmtflags f( cout.flags() );

//Your code here...

cout.flags( f );

You can put these at the beginning and end of your function, or check out this answer on how to use this with RAII.

Roll-Back or Undo Any Manipulators Applied To A Stream Without Knowing What The Manipulators Were

Yes.

You can save the state and restore it:

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{

std::ios state(NULL);
state.copyfmt(std::cout);

cout << "Hello" << hex << 42 << "\n";
// now i want to "roll-back" cout to whatever state it was in
// before the code above, *without* having to know what modifiers I added to it

// ... MAGIC HAPPENS! ...

std::cout.copyfmt(state);
cout << "This should not be in hex: " << 42 << "\n";
}

If you want to get back to the default state you don't even need to save the state you can extract it from a temporary object.

std::cout.copyfmt(std::ios(NULL));

How to bring std::cout output back to the top after a new line

You can use SetConsoleCursorPosition to set the cursor location back to the top left after doing the clear.

There are also ANSI escape codes (similar to the one you use to clear the screen) that would allow you to reposition the cursor.

"\033[r;cH"

replacing r with the row and c the column to move to. They are 1-based, and default to the top left, so you can use "\033[1;1H" or just "\033[H"

Reset properties of std::cout for integers or doubles in C++

Use resetiosflags:

std::cout << std::resetiosflags( std::ios_base::basefield ); // clears integer manipulations
std::cout << std::resetiosflags( std::ios_base::floatfield ); // clears floating-point manipulations
std::cout << std::resetiosflags( std::cout.flags() ); // clears all flags

How to make std::hex, std::bin, std::dec to be effective for only once?

Two ways, you can set it back using std::dec

std::cout << std::hex << (long int)s << std::dec << std::endl;

In general you can save the current state and then restore it

std::ios_base::fmtflags save = std::cout.flags();
std::cout << std::hex << (long int)s << std::endl;
std::cout.flags(save);

But this is tedious stuff.

How to automatically set stream mode back to default

I'm going to suggest an alternative approach. The manipulators apply to the std::[i|o]stream instance, but they do nothing with regards to the std::[i|o]streambuf which is managed by that std::[i|o]stream.

Therefore, you can create your own std::[i|o]stream, which will have its own formatting state, but writing to the same buffer std::cout uses:

#include <iostream>
#include <iomanip>

int main()
{
std::cout << std::hex << 32 << "\n";
std::ostream os(std::cout.rdbuf());
os << 32 << "\n" << std::hex;
std::cout << std::dec;
os << 32 << "\n";
std::cout << 32 << "\n";
}

Output:

20
32
20
32

Live on Coliru

This uses only features from standard library, and since the original stream is not touched, applying manipulators is trivially thread safe (because each thread operates on a different stream). Now, the actual writes and reads' thread safety depends on the thread safety of the managed stream buffer.

How should I manage ::std::cout after changing file descriptor 1 to refer to a different file?

Option 1: set stdin & stdout

According to cppreference.com:

By default, all eight standard C++ streams are synchronized with their respective C streams.

And as long as you didn't explicitly called sync_with_stdio(false), they'll stay that way. What does it mean? The following:

In practice, this means that the synchronized C++ streams are unbuffered, and each I/O operation on a C++ stream is immediately applied to the corresponding C stream's buffer. This makes it possible to freely mix C++ and C I/O.

So, flush()-ing your cin & cout before dup()-ing them should be enough, since they should be in a consistent state.

If you wish to work with files for example, you could use:

if (freopen("input.txt", "r", stdin) == NULL) {
// Handle error, errno is set to indicate error
}

if (freopen("output.txt", "w", stdout) == NULL) {
// Handle error, errno is set to indicate error
}

Note 1: Setting the global extern FILE * stdin or stdout won't work because it simply changes a single instance of a pointer to the relevant FILE struct of the os. Any module that copied this pointer at any moment prior to this change will continue using the old FILE. A specific example is libc++'s implementation for cout, which copies FILE * stdout to a private member during the object's init. freopen on the other hand changes the internal FILE structure of the OS to use the newly opened file, affecting anyone who has a FILE * to it.

Note 2: When using dup() flavors (rather than freopen()), we are changing the underlying fd, rather than the FILE*. The freopen() method does more than that. From POSIX:

The freopen() function shall first attempt to flush the stream associated with stream as if by a call to fflush(stream). Failure to flush the stream successfully shall be ignored. If pathname is not a null pointer, freopen() shall close any file descriptor associated with stream. Failure to close the file descriptor successfully shall be ignored. The error and end-of-file indicators for the stream shall be cleared.

dup()-ing might work, but, it might be tricky, since it won't affect other properties of the FILE*, including: Character width, Buffering state, The buffer, I/O, Binary/text mode indicator, End-of-file status indicator, Error status indicator, File position indicator & (After C++17) Reentrant lock used to prevent data races.

When possible, I suggest using freopen. Otherwise, you could follow the steps described by yourself (fflush(), clearerr()). Skipping fclose() will be wise, since we won't be able to reopen the same internal FILE by any of the API methods.

Option 2: set cin's & cout's rdbuf()

The other way around, just like some comments proposed, is replacing cin's and cout's underlying buffer using rdbuf().

What are your options here?

  • File streams: Open ifstream & ofstream and use them:

    std::ifstream fin("input.txt");
    if (!fin) {
    // Handle error
    }
    cin.rdbuf(fin.rdbuf());

    std::ofstream fout("output.txt");
    if (!fout) {
    // Handle error
    }
    cout.rdbuf(fout.rdbuf());
  • Network streams: Use boost's boost::asio::ip::tcp::iostream (It's derived from std::streambuf and thus will work):

    boost::asio::ip::tcp::iostream stream("www.boost.org", "http");
    if (!stream) {
    // Handle error
    }

    cin.rdbuf(stream.rdbuf());
    cout.rdbuf(stream.rdbuf());

    // GET request example

    cout << "GET /LICENSE_1_0.txt HTTP/1.0\r\n";
    cout << "Host: www.boost.org\r\n";
    cout << "Accept: */*\r\n";
    cout << "Connection: close\r\n\r\n";
    cout.flush();

    std::string response;
    std::getline(cin, response);
  • Custom streams: Use your own custom wrapper for std::streambuf. See an example here.

How do I save the state of std::mersenne_twister_engine to restore it later?

According to this, engine should support serialization into and from a standard stream.



Related Topics



Leave a reply



Submit