C++ Iomanip lib setfill and setw issues

C++ Iomanip lib setfill and setw issues

本文关键字:setw issues and setfill Iomanip lib C++      更新时间:2023-10-16

我的代码:

#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的工作方式?

填充字符是"粘性"的,因此它在您更改之前一直有效。

在您的情况下,您希望0作为数字字段的填充,但空格作为字符字段的填充。因此,您必须显式设置,类似于以下内容:

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

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

当你有这个:

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

这将使CCD_ 6对于下一行保持活动。所以你可能更喜欢

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

正如其他评论中提到的,许多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
}