请考虑以下代码:
int xx;
std::cin >> std::setfill('0') >> std::setw(4) >> xx;
当将12
发送到标准输入时,我希望xx
的值1200
,而在发送12345
时,我希望它是1234
的。
但是,似乎std::setfill
和std::setw
没有效果,我分别得到了12
和12345
。
这是一个错误还是根据标准?有没有获得预期功能的好方法?
另请注意,当我更改要std::string
的xx
类型时,std::setw
生效,而std::setfill
仍然没有生效。
我的编译器是gcc-7.0.1
.
根据C++标准,setfill
与输出流有关。至于setw
,当与char*
或string
一起使用时,它适用于输入流。例如,以下程序输出abcd
输入字符串abcdef
(1234
123456
):
string a;
cin >> setw(4) >> a;
cout << a;
setw
和setfill
并没有如此普遍地应用。
听起来您想模仿在固定宽度列中格式化给定输入,然后重新读取它的效果。该库确实为此提供了工具:
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;
}
演示。
不过,此功能不会将12345
修剪为1234
。这将需要通过string
进行另一次转换。
由于历史事故,GCC 和 MSVC 支持将setfill
与 istream 一起使用。它将调用ios::fill(c)
来存储填充字符,但从任何从 istream 读取值的提取函数都不会使用它。所以你可以编译它,但它没有做OP期望的。
在过去,大多数I/O操纵器同时使用输入和输出流。在1996年中期(即在最初的C++98标准之前),I/O机械手的规范在N0958中由第27-652期和N0964中的第27-651期更改。
似乎GCC和MSVC中的iostreams实现从未针对仅适用于ostream的更改进行调整setfill
。Clang库(libc ++)是在2010年左右从头开始编写的,因此是根据最终标准实现的,没有任何1990年代标准草案的残余。
有趣的是,Angelika Langer和Klaus Kreft合著的《标准C++IOStreams and Locales: Advanced Programmer's Guide and Reference》一书也说setfill
同时处理输入和输出流。因此,不仅仅是GCC和Dinkumware没有得到有关更改的备忘录。