stringstream:为什么“showpoint”表现得像“固定”一样?

时间:2011-06-03 19:10:10

标签: g++ stringstream lexical-cast

我想编写自己的lexical_cast,在将double转换为std::string时会保留小数点。所以我正在使用ostringstream并设置标记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;
}

然而,这会打印不必要的0位数,这是我期望设置std::ios::fixed而不是std::ios::showpoint的行为:

1.00000000000000
5.60000000000000
0.333333333333333

没有设置std::ios::showpoint就会给出

1
5.6
0.333333333333333

但我想要这样的事情:

1.0
5.6
0.333333333333333

任何简单的方法?

2 个答案:

答案 0 :(得分:1)

你想要的东西对我来说似乎是一种相当自定义的行为。

这可能不是最好的方法,但您可以将所有数字输出到您的ostringstream,然后在流中搜索最后一个非'0'字符。将流的结束位置设置为该位置。

类似于:

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);  

答案 1 :(得分:0)

经过很长一段时间查看std库的代码后,似乎所有内容都被移交给printf类型函数:__builtin_vsnprintf(__out, __size, __fmt, __args)。格式字符串__fmt的设置取决于ostringstream对象上设置的标志,可以使用

进行查询
std::ostringstream s;
// ...
char format[50];
std::__num_base::_S_format_float(s,format,'\0');

默认格式字符串为%.*g,用于printf("%.*g",precision,x);precisionintxdouble打印。对于我们得到的其他标志:

s.setf(std::ios::fixed);      // %.*f
s.setf(std::ios::showpoint);  // %#.*g

然而格式%#g不仅保留小数点,还保留所有尾随零。该文档说明了#g结合使用的用法:

"printf" will always print out a decimal point and trailing zeros will not
be removed; usually 'g' and 'G' remove trailing zeros.

不幸的是,我找不到任何其他printf格式的字符串,其行为与%g一样好,但始终保持小数点,所以我猜想像dschaeffer的答案一样可能是最好的。