Reputation: 4850
Consider this code:
int xx;
std::cin >> std::setfill('0') >> std::setw(4) >> xx;
When sending 12
to the standard input I am expecting the value of xx
to be 1200
and when sending 12345
I am expecting it to be 1234
.
However, it seems std::setfill
and std::setw
have no effect and I am getting 12
and 12345
respectively.
Is this a bug or it is according to the standard? Is there a good way to get the expected functionality?
Also note, when I change the type of xx
to be std::string
the std::setw
takes effect while std::setfill
still doesn't.
My compiler is gcc-7.0.1
.
Upvotes: 3
Views: 2108
Reputation: 171403
Due to historical accident, GCC and MSVC support using setfill
with an istream. It will call ios::fill(c)
to store the fill character, but that is never used by any of the extraction functions that read values from an istream. So you can compile it, but it doesn't do what the OP expects.
In the olden times, most I/O manipulators worked with both input and output streams. In mid-1996 (i.e. prior to the original C++98 standard) the specification for I/O manipulators was changed by issue 27-652 in N0958 and issue 27-651 in N0964.
It seems that the iostreams implementations in GCC and MSVC were never adjusted for the change that made setfill
only apply to ostreams. The Clang library (libc++) was written from scratch around 2010 and so was implemented according to the final standard, without any remnants of draft standards from the 1990s.
Interestingly, (at least some editions of) the book Standard C++ IOStreams and Locales: Advanced Programmer's Guide and Reference by Angelika Langer and Klaus Kreft also said that setfill
worked with both input and output streams. So it wasn't only GCC and Dinkumware that didn't get the memo about the change.
Upvotes: 1
Reputation: 4399
According to C++ standard, setfill
pertains to output stream. As for the setw
, it works for input stream when used together with char*
or string
. For example, following program outputs abcd
for input string abcdef
(and 1234
for 123456
):
string a;
cin >> setw(4) >> a;
cout << a;
Upvotes: 3
Reputation: 137910
setw
and setfill
are not applied so universally.
It sounds like you want to imitate the effect of formatting the given input in a fixed-width column, then re-reading it. The library does provide tools for exactly that:
int widen_as_field( int in, int width, char fill ) {
std::stringstream field;
field << std::setw( width ) << std::setfill( fill );
field << std::setiosflags( std::ios::left );
field << in;
int ret;
field >> ret;
return ret;
}
Demo.
This function will not trim 12345
to 1234
, though. That would take another conversion through string
.
Upvotes: 1