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 fromstd::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
How Can a Windows Service Execute a Gui Application
How Does C++ Linking Work in Practice
Why Aren't Pointers Initialized With Null by Default
Are C++ Reads and Writes of an Int Atomic
Why Do We Need a Pure Virtual Destructor in C++
How to Find Which Elements Are in the Bag, Using Knapsack Algorithm [And Not Only the Bag'S Value]
"\N" or '\N' or Std::Endl to Std::Cout
On Which Platforms Does Integer Divide by Zero Trigger a Floating Point Exception
Why No Default Move-Assignment/Move-Constructor
How to Find If a Given Key Exists in a C++ Std::Map
Create Random Number Sequence With No Repeats
Displaying the #Include Hierarchy For a C++ File in Visual Studio
Why Is Conversion from String Constant to 'Char*' Valid in C But Invalid in C++
Deoptimizing a Program For the Pipeline in Intel Sandybridge-Family Cpus
Removing Item from Vector, While in C++11 Range 'For' Loop
Difference Between Conversion Specifiers %I and %D in Formatted Io Functions (*Printf/*Scanf)