与std :: stringstream一起使用时std :: setw的意外行为

时间:2014-09-17 16:22:25

标签: c++

请考虑以下代码:

std::string n("123456");


std::stringstream ss;
ss << std::setw(3) << n;
std::cout << ss.str() << " | " << (ss.fail() ? "True" : "False") << std::endl;

为什么打印

123456 | False 

而不是

123 | False

2 个答案:

答案 0 :(得分:2)

宽度修改器的效果由不同的格式化程序以不同方式处理。在表达式ss << std::setw(3) << n中,n的类型为std:string,您正在使用operator<<(ostream&, const std::string&),其执行以下操作(来自cppreference):

  

a)如果str.size()不小于os.width(),则使用范围   [str.begin(),str.end())as-is

在您的情况下,str.size()6ss.width()3,因此输出整个字符串

答案 1 :(得分:0)

<强>问题

其完全可预测的行为:setw()设置字段的最小宽度。如果您的输出超过此长度,则会写入其全长。顺便说一句,宽度将适用于以下所有输出,直到您再次更改它。

因为它只是关于格式化而且因为ostream没有关于坏的alignemnt的个人品味,fail()将总是返回false; - )

<强>解决方案

如果您的输出只是字符串,则您具有字符串expression的所有功能:

ss << setw(3) << n.substr(0,3) ;   // set mini and maxi. 

如果您有很多这样的格式,也有算术类型,您可以考虑编写一个小型适配器,如下所示:

template <class T>
string mfixed(ostream& os, T o, int n)
{
    stringstream ss; 
    ss.copyfmt(os);   // copy ALL format flags of ostream
    ss << setw(n)<< o;    // set the fixed length and ouput
    return ss.str().substr(0, n);  // truncate
}

您可以在代码中非常灵活地使用它:

ss << mfixed(ss, n, 3) 
    << " " << mfixed(ss, 25, 4) << " " << mfixed(ss, 100000, 3) 
    << " " << setprecision(2) << mfixed(ss, 1.0/3.0, 4);