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_stri开发者_StackOverflowng_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?
What you are wanting seems like a fairly custom behavior to me.
It may not the best way, but you can output all of the digits to your ostringstream, then search for the last non '0' character in the stream. Set the ending position of you stream to that position.
something along the lines of:
size_t endPos = interpreter.str().find_last_of("0");
size_t begPos = interpreter.str().find_first_of(".") +2;
if( endPos < begPos )
return interpreter.str().substr(0, begPos);
else
return interpreter.str().substr(0, endPos);
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.
精彩评论