Десятичные точки с std::stringstream?

У меня есть куча целых чисел, которые я помещаю в stringstreams. Теперь я хочу изменить stringstreams на strings, сохраняя постоянную точность с strings. Как бы я это сделал? Я знаю, что могу использовать stringstreams.precision(), но по какой-то причине это не работает:

float a = 5.23;
float b = 3.134;
float c = 3.0;

std::stringstream ta;
std::stringstream tb;
std::stringstream tc;

ta << a;
tb << b;
tc << c;

ta.precision(2);
tb.precision(2);
tc.precision(2);

std::string out = "";
out += ta.str() + "\n";
out += tb.str() + "\n";
out += tc.str() + "\n";

Вернет 5.23\n3.134\n3.0, а не 5.23\n3.13\n3.00


person noobcpp    schedule 25.02.2011    source источник


Ответы (2)


Я думаю, что ваша проблема в том, что precision() устанавливает точность, используемую в будущих операциях вставки потока, а не при создании окончательной строки для представления. То есть, написав

ta << a;
tb << b;
tc << c;

ta.precision(2);
tb.precision(2);
tc.precision(2);

Вы устанавливаете precision слишком поздно, так как первые три строки уже преобразовали числа с плавающей запятой в строки с точностью по умолчанию.

Чтобы исправить это, попробуйте изменить порядок выполнения этих операторов на

ta.precision(2);
tb.precision(2);
tc.precision(2);

ta << a;
tb << b;
tc << c;

Это приведет к тому, что при записи в stringstream будет использоваться ваша пользовательская точность, а не существующие значения по умолчанию.

Однако эффект модификатора precision имеет смысл только в том случае, если вы явно указываете потоку, что хотите использовать для вывода либо фиксированную точность, либо экспоненциальную нотацию. Для этого вы можете использовать модификаторы fixed или scientific:

ta.precision(2);
tb.precision(2);
tc.precision(2);

ta << fixed << a;
tb << fixed << b;
tc << fixed << c;

Это позволит правильно отображать соответствующее количество цифр.

В связи с этим вам не нужно использовать три stringstreams для достижения вашей цели. Вы можете просто использовать один:

std::stringstream t;
t.precision(2);

t << fixed << a << '\n' << b << '\n' << c << '\n';

std::string out = t.str();
person templatetypedef    schedule 25.02.2011
comment
спасибо, но он не работает. я все еще получаю 3.0, а не 3.00 - person noobcpp; 25.02.2011
comment
@noobcpp- Упс! Виноват. Я только что обновил это, упомянув, что вам нужно использовать режим fixed или scientific для строковых потоков. Попробуйте внести это изменение и посмотрите, исправит ли оно ситуацию. - person templatetypedef; 25.02.2011
comment
+1. @noobcpp: Также проверьте: cplusplus.com/reference/iostream/ios_base/precision (хотя они говорят использовать 0 в месте, которое вызывает ошибку компиляции). - person Merlyn Morgan-Graham; 25.02.2011
comment
Вам не нужно выделять вызов precision на отдельной строке: t << setprecision(2) << fixed << a ... - person user470379; 25.02.2011
comment
Прошло 2 года, а этот пост до сих пор спасает жизни! Спасибо @templatetypedef - person Hanlet Escaño; 21.05.2013

В С++ 20 вы можете использовать std::format, который эффективнее перемещается и менее многословен, чем std::stringstream:

float a = 5.23;
float b = 3.134;
float c = 3.0;
std::string out = std::format("{:.2f}\n{:.2f}\n{:.2f}\n", a, b, c);

А пока вы можете использовать библиотеку {fmt}, std::format основанную на (godbolt).

Отказ от ответственности: я автор {fmt} и C++20 std::format.

person vitaut    schedule 03.03.2021