Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::ostringstream puts sign in wrong location?

Tags:

c++

I am using std::ostringstream to format a double to a string with a specific format (using apostrophes as thousands separators). However, in some cases ostringstream gave me a different result from what I expected.

As far as I can tell, the expected output of the code below should be "+01"; instead it outputs "0+1". What am I doing wrong here, and how can I get the result I need?

#include <iomanip>
#include <iostream>
#include <sstream>

int main() 
{
    std::ostringstream stream;
    stream << std::showpos; // Always show sign
    stream << std::setw(3); // Minimum 3 characters
    stream << std::setfill( '0' ); // Zero-padded
    stream << 1; // Expected output: "+01"

    std::cout << stream.str(); // Output: "0+1"
    return 0;
}

Code on ideone

like image 429
downwash Avatar asked Oct 13 '17 12:10

downwash


4 Answers

There are three options for the padding, left, right, and internal.

You want internal padding, between the sign and the value.

stream << std::setfill( '0' ) << std::internal; // Zero-padded
like image 158
Bo Persson Avatar answered Oct 24 '22 14:10

Bo Persson


You can use std::internal juste before std::showpos (as shown here).

We need to add the std::internal flag to tell the stream to insert "internal padding" -- i.e., the padding should be inserted between the sign and the rest of the number.

#include <iomanip>
#include <iostream>
#include <sstream>

int main() 
{
    std::ostringstream stream;

    stream << std::setfill('0');
    stream << std::setw(3);
    stream << std::internal;
    stream << std::showpos;
    stream << 1; 

    std::cout << stream.str(); // Output: "+01"
    return 0;
}
like image 12
informaticienzero Avatar answered Oct 24 '22 14:10

informaticienzero


The fill character is used with any type to fill a given width. By default the fill characters go to the left of the value, and that’s what you’re seeing with those zeros. The solution is to override that default and tell the stream to put the fill characters inside the text:

std::cout << std::internal << std::setfill(0) << std::setw(3) << 1 << '\n';

You can also use std::left or std::right to put the fill characters on the left of the value or the right of the value.

like image 9
Pete Becker Avatar answered Oct 24 '22 13:10

Pete Becker


That is, unfortunately, how it is supposed to work. The '0' is used as a fill character, not as a part of the number.

To fix it, you must output the + or - separately:

std::ostringstream oss;
oss << "+-"[x<0];
oss << std::setw(2) << std::setfill('0') << std::abs(x);
return/cout/whatever oss.str();
like image 1
Dúthomhas Avatar answered Oct 24 '22 12:10

Dúthomhas