Resetting std::stringstream format flags - c++

I need to print hex and decimal values in my console. I used the following piece of code to do it.
std::stringstream ss;
ss << "0x" << std::uppercase << std::hex << 15;
std::cout << ss.str() << std::endl;
ss.str("");
ss.clear();
ss << 15;
std::cout << ss.str() << std::endl;
But I am getting both values in Hex format. How to reset stringstream?

How to reset stringstream?
Format flags are sticky.
You can save the old format flags to restore them later:
std::stringstream ss;
auto oldFlags = ss.flags(); // <<
ss << "0x" << std::uppercase << std::hex << 15;
std::cout << ss.str() << std::endl;
ss.flags(oldFlags); // <<
ss << 15;
std::cout << ss.str() << std::endl;

Assuming you know which formatting flag are actually used, you can just save their original value and restore them later. When the set of formatting flags being changed is large and possibly somewhat out of the control of the function, there are essentially two approaches which are both, unfortunately, not really very cheap:
Do not use the std::stringstream directly but rather use a temporary stream to which the format flags get applied:
{
std::ostream out(ss.rdbuf());
out << std::showbase << std::uppercase << std::hex << 15;
}
ss << 15;
You can use the copyfmt() member to copy all the formatting flags and later restore these:
std::ostream aux(0); // sadly, something stream-like is needed...
out.copyfmt(ss);
out << std::showbase << std::uppercase << std::hex << 15;
ss.copyfmt(aux);
out << 15;
Both approaches need to create a stream which is, unfortunately, not really fast due to a few essentially mandatory synchronizations (primarily for creating the std::locale member).

Just use
std::nouppercase
ss << std::uppercase;
...
ss << std::nouppercase;
...

Related

Convert Hexadecimal string to decimal number in C++

I want to convert a hexadecimal string to a decimal number (integer) in C++ and tried with following ways:
std::wstringstream SS;
SS << std::dec << stol(L"0xBAD") << endl;
But it returned 0 instead 2989.
std::wstringstream SS;
SS << std::dec << reinterpret_cast<LONG>(L"0xBAD") << endl;
But it returned -425771592 instead 2989.
But, when I use it like below, it works fine and gives 2989 as expect.
std::wstringstream SS;
SS << std::dec << 0xBAD << endl;
But I want to input a string and get 2989 as output, instead integer input like 0xBAD. For example, I want to input "0xBAD" and cast it to integer and then convert to a decimal number.
Thanks in advance.
// stol example
#include <iostream> // std::cout
#include <string> // std::string, std::stol
int main ()
{
std::string str_dec = "1987520";
std::string str_hex = "2f04e009";
std::string str_bin = "-11101001100100111010";
std::string str_auto = "0x7fffff";
std::string::size_type sz; // alias of size_t
long li_dec = std::stol (str_dec,&sz);
long li_hex = std::stol (str_hex,nullptr,16);
long li_bin = std::stol (str_bin,nullptr,2);
long li_auto = std::stol (str_auto,nullptr,0);
std::cout << str_dec << ": " << li_dec << '\n';
std::cout << str_hex << ": " << li_hex << '\n';
std::cout << str_bin << ": " << li_bin << '\n';
std::cout << str_auto << ": " << li_auto << '\n';
return 0;
}

c++11. Is it possible to do this: string foo = cout << (.00000023)*(.00000023) << endl; -with precision

I want to save the output from
std::cout << endl << std::setprecision(20) << std::fixed;
cout << ((.0000023)*(.00000023))<< endl;
Which is: 0.00000000000052900000
-into a string variable.
You could split this into steps using std::ostringstream:
std::ostringstream output;
output << << endl << std::setprecision(20) << std::fixed;
output << ((.0000023)*(.00000023))<< endl;
std::string result_string = output.str();
I suggest to try std::ostringstream:
std::ostringstream oss;
oss << ...;
std::string result(oss.str());
Note that it's slow on some platfroms/compilers.
See std::stringstream to stream into a string.
#include <string>
#include <sstream>
int main()
{
std::ostringstream stream;
stream << 10 + 10;
std::string result = stream.str(); // result contains "20"
return 0;
}
Edit: String manipulators work with std::ostringstream just like std::cout.
stream << std::fixed << (1.0 / 100.0); // result will contain "0.010000"

How to remove redundancy in formatted ofstream

I have the following working code which produces formatted output using an ofstream, however I feel that all of the repeated format specifiers make it hard to read. Is there any way to set the precision, width and alignment permanently for a given stream, which would clean things up nicely?
#include <fstream>
#include <iomanip>
ofstream myfile;
myfile.open(Output.c_str(), ios::trunc);
for (int i = 0; i < iLen; i++) {
myfile <<std::fixed << std::setw( iWidth ) << std::setprecision( iDecimals )<< std::right << pDist[i] << " "
<<std::fixed << std::setw( iWidth ) << std::setprecision( iDecimals )<< std::right << pRes[i] << " "
<<std::fixed << std::setw( iWidth ) << std::setprecision( iDecimals )<< std::right << pPhase[i] << "\n";
}
myfile.close();
std::fixed, std::setprecision, and std::right are all "permanent". They set persistent flags on the stream object.
The only one that you need to put every time is setw, which (as I understand) does not set a flag on the stream object, just adds a certain amount of whitespace by altering the stream itself. But it leaves the stream alone.
This is similar to endl, which operates on the stream but leaves the actual stream object alone.
This answer by #LokiAstari on a similar question details which specifiers are, as they put it, "sticky" (and why).
EDIT: Cleared up distinctions between the stream object and the actual stream
The only manipulator you need to worry about is std::setw as the width is set back to zero whenever operator<< is called. Before your loop, you can set your "permanent" ios flags:
myfile << std::fixed << std::setprecision(iDecimals) << std::right;
for (int i = 0; i < iLen; i++) {
myfile << std::setw( iWidth ) << pDist[i] << " "
<< std::setw( iWidth ) << pRes[i] << " "
<< std::setw( iWidth ) << pPhase[i] << "\n";
}
If you want to unset these flags in one go, you can use:
std::cout.copyfmt(std::ios(NULL));
As stated in this answer.

c++ std::istringstream weird std::hex behaviour

EDIT:
I managed to get the same problem on a smaller scale:
std::istringstream hex;
std::string str = "0x7ffa428ab946";
std::cout << "str " << str << std::endl;
hex.str(str);
long caller;
hex >> std::hex >> caller;
std::cout << "caller " << caller << std::endl;
str = "0x7ff9ec0010f0";
std::cout << "str " << str << std::endl;
hex.str(str);
long address;
hex >> std::hex >> address;
std::cout << "address " << address << std::endl;
and get this:
str 0x7ffa428ab946
caller 140712834939206
str 0x7ff9ec0010f0
address 0
why is that?
hex >> std::hex >> caller;
will set eofbit on hex, but the subsequent
hex.str(str);
doesn't clear it. Thus, later attempts to extract from hex will simply fail.
Call hex.clear() after the hex.str(str); call to clear the flags.

Printing hex and int together in a text file

I am trying to print hex values for member[0] and member[1] and integer values for _records in the same text file with the following code:
std::ofstream myoutputfile;
myoutputfile << std::hex << (int)(unsigned char)_member[0] << ' ';
myoutputfile << std::hex << (int)(unsigned char)_member[1] << ' ';
myoutputfile<<_records << std::endl;
But this code prints _records in hex too. I have tried:
myoutputfile<<(int)_records << std::endl;
But still it prints it in hex.
Can anyone help please.
Set the format back to decimal using std::dec
myoutputfile<< std::dec << _records << std::endl;
As you've discovered, the base format specifiers are sticky, so there's no need to specify std::hex each time. Your code could be rewritten as follows to achieve the same effect.
std::ofstream myoutputfile;
myoutputfile << std::hex
<< (int)(unsigned char)_member[0] << ' '
<< (int)(unsigned char)_member[1] << ' '
<< std::dec << _records << std::endl;
You could also have the resetting to previous state done automatically by using Boost IO State Savers.
#include <boost/io/ios_state.hpp>
#include <ios>
#include <iostream>
#include <ostream>
int main()
{
auto hex_printer = [](std::ostream& os, unsigned char byte) {
boost::io::ios_flags_saver ifs(os);
os << std::hex << static_cast<unsigned>(byte) << ' ';
};
hex_printer(std::cout, 'A');
std::cout << 42 << '\n';
}
Live demo
The base that's use for conversion from numbers to text is a state of the output stream rather than a function of the input type. You need to do:
myoutputfile<< std::dec << _records << std::endl;
This changes the state of the output stream to put _records using decimal.
std::hex tells an ostream to print everything in hex from that point on. The equivalent that will return it to decimal is std::dec. Try the following:
std::ofstream myoutputfile;
myoutputfile << std::hex;
myoutputfile << _member[0] << ' ';
myoutputfile << _member[1] << ' ';
myoutputfile << std::dec << _records << std::endl;
Check out http://www.cplusplus.com/reference/ios/hex/ as an additional reference.
you can use fprintf, which prints formatted text:
frintf("%x %x %d\n",_member[0],_member[0],_records);
Hope this helps