std::setfill 和 std::setw 用于输入流?

std::setfill and std::setw for input streams?

本文关键字:std 输入流 用于 setfill setw      更新时间:2023-10-16

请考虑以下代码:

int xx;
std::cin >> std::setfill('0') >> std::setw(4) >> xx;

当将12发送到标准输入时,我希望xx的值1200,而在发送12345时,我希望它是1234的。

但是,似乎std::setfillstd::setw没有效果,我分别得到了1212345

这是一个错误还是根据标准?有没有获得预期功能的好方法?

另请注意,当我更改要std::stringxx类型时,std::setw生效,而std::setfill仍然没有生效。

我的编译器是gcc-7.0.1.

根据C++标准,setfill输出流有关。至于setw,当与char*string一起使用时,它适用于输入流。例如,以下程序输出abcd输入字符串abcdef(1234123456):

string a;
cin >> setw(4) >> a;
cout << a;

setwsetfill并没有如此普遍地应用。

听起来您想模仿在固定宽度列中格式化给定输入,然后重新读取它的效果。该库确实为此提供了工具:

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没有得到有关更改的备忘录。