stringstream: почему «showpoint» ведет себя так же, как и «fixed»? - PullRequest
1 голос
/ 03 июня 2011

Я хотел бы написать свой собственный 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 ]

1 голос
/ 03 июня 2011

То, что вы хотите, кажется мне довольно нестандартным поведением.

Возможно, это не самый лучший способ, но вы можете вывести все цифры в свой поток 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);  
0 голосов
/ 05 июня 2011

После долгого просмотра кода библиотеки std кажется, что все передается какой-то функции printf type: __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);, гдеprecision - это int и x double для печати.Для других флагов мы получаем:

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, но всегда сохраняетдесятичная точка, так что я думаю, что что-то вроде ответа Дшеффера вполне может быть лучшим.

...