I'd like to write my own lexical_cast
which preserves the decimal point when converting double
to std::string
. So I'm using ostringstream
and set the flag std::ios::showpoint
:
#include <string>
#include <iostream>
#include <boost/lexical_cast.hpp>
template <typename Source>
std::string my_string_cast(Source arg){
std::ostringstream interpreter;
interpreter.precision(std::numeric_limits<Source>::digits10);
interpreter.setf(std::ios::showpoint);
interpreter << arg;
return interpreter.str();
}
int main(int argc, char** argv) {
std::cout << my_string_cast(1.0) << std::endl;
std::cout << my_string_cast(5.6) << std::endl;
std::cout << my_string_cast(1.0/3.0) << std::endl;
return 0;
}
This, however, prints unnecessary 0 digits, a behaviour I'd expect from setting std::ios::fixed
but not std::ios::showpoint
:
1.00000000000000
5.60000000000000
0.333333333333333
Without setting std::ios::showpoint
it gives
1
5.6
0.333333333333333
but I want something like this:
1.0
5.6
0.333333333333333
Any easy way?
After a long time looking through the code of the std library it seems everything gets handed over to some printf
type function: __builtin_vsnprintf(__out, __size, __fmt, __args)
. The format string __fmt
is set depending on the flags set on the ostringstream
object and can be queried using
std::ostringstream s;
// ...
char format[50];
std::__num_base::_S_format_float(s,format,'\0');
The default format string is %.*g
which is used as in printf("%.*g",precision,x);
where precision
is an int
and x
the double
to be printed. For the other flags we get:
s.setf(std::ios::fixed); // %.*f
s.setf(std::ios::showpoint); // %#.*g
Yet the format %#g
doesn't just keep the decimal point but also keeps all trailing zeros. The doc says about the usage of #
combined with g
:
"printf" will always print out a decimal point and trailing zeros will not
be removed; usually 'g' and 'G' remove trailing zeros.
Unfortunately, I can't find any other printf
format string which behaves as nice as %g
but always keeps the decimal point, so I guess something along the lines of dschaeffer's answer might well be the best.