C ++ Iomanip lib setfill和setw问题

时间:2016-01-13 17:50:31

标签: c++ debugging

我的代码:

#include <iostream>
#include <iomanip>

using namespace std;

int main () {
    int time;
    int honolulu, seattle, london, moscow, hongkong, auckland;

    cout << "What is the current time in Philadelphia? ";
    cin >> time;

    honolulu = (time+2400-600)%2400;
    seattle = (time+2400-300)%2400;
    london = (time+2400+500)%2400;
    moscow = (time+2400+800)%2400;
    hongkong = (time+2400+1200)%2400;
    auckland = (time+2400+1700)%2400;

    cout << endl << "Current times in other cities: " << endl;
    cout << setw (12) << left << "Honolulu:";
    cout << setw (4) << setfill('0') << honolulu << endl;
    cout << setw (12) << left << "Seattle:";
    cout << setw (4) << setfill('0') << seattle << endl;
    cout << setw (12) << left << "London:";
    cout << setw (4) << setfill('0') << london << endl;
    cout << setw (12) << left << "Moscow:";
    cout << setw (4) << setfill('0') << moscow << endl;
    cout << setw (12) << left << "Hong Kong:";
    cout << setw (4) << setfill('0') << hongkong << endl;
    cout << setw (12) << left << "Auckland:";
    cout << setw (4) << setfill('0') << auckland << endl;

    return 0;
}

必需输出:

What is the current time in Philadelphia? 0415    

Current times in other cities: 
Honolulu:   2215
Seattle:    1150
London:     9150
Moscow:     1215
Hong Kong:  1615
Auckland:   2115

我的输出:

What is the current time in Philadelphia? 0415    

Current times in other cities: 
Honolulu:   2215
Seattle:00001150
London:000009150
Moscow:000001215
Hong Kong:001615
Auckland:0002115

我做错了什么?第一行输出Honolulu: 2215是正确的。但接下来的行有前导零。我不明白为什么会这样?我的代码是否有问题,或者我误解了setfillsetw函数的工作方式?

3 个答案:

答案 0 :(得分:4)

许多iomanip个对象都是“粘性的”,也就是说,它们会粘在流上并影响后续行。

当你有这个:

cout << setw (12) << left << "Seattle:";
cout << setw (4) << setfill('0') << seattle << endl;

将使setfill处于下一行的活动状态。所以你可能更喜欢

cout << setw (12) << setfill(' ') << left << "Seattle:";
cout << setw (4) << setfill('0') << seattle << endl;

答案 1 :(得分:4)

填充字符为“粘性”,因此在您更改之前它仍然有效。

在您的情况下,您希望0作为数字字段的填充,但是空格作为字符字段的填充,因此您必须明确地设置它,如下所示:

cout << setfill(' ') << setw (12) << left << "Seattle:";

答案 2 :(得分:2)

正如其他评论中所提到的,许多I / O操纵器都是“粘性的”。 我个人更喜欢使用RAII来解决这类问题:

class stream_format_raii {
public:
   stream_format_raii(std::ostream &stream)
      : stream_(stream)
      , state_(NULL) {
      state_.copyfmt(stream_);
   }

   ~stream_format_raii() {
      stream_.copyfmt(state_);
   }
public:
   std::ostream &stream_;
   std::ios  state_;
};

这个类所做的是在构造时备份当前流的格式,并在破坏时将其设置回来。

你可以这样使用它:

void printCity(std::ostream &os, const std::string name, int time) {
   stream_format_raii back(os);
   os << std::setw(12) << std::left << (name + ":");
   os << std::setw(4) << std::setfill('0') << time;
}


int main() {
   // Same as before
   printCity(std::cout, "Honolulu", honolulu);
   // Same as before
}