C++ Iomanip库中的setfill和setw问题

3

我的代码:

#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 的工作原理有误解?


有些控制符只影响到下一次的输出,而有些则会影响到所有的输出。std::setfill将设置填充字符用于所有接下来的输出。 - Some programmer dude
3个回答

4
许多对象是“粘性”的,它们会附着在流上并影响后续行的内容。
当您有以下代码时:
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;

4

填充字符是“粘性”的,因此它会一直保持有效,直到您更改它。

在您的情况下,您希望数字字段的填充为0,但字符字段的填充为空格,因此您需要明确设置,例如:

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

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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接