Debdut Debdut - 3 months ago 21
C++ Question

C++ Iomanip lib setfill and setw issues

My Code:

#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;
}


Required Output :

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


My output :

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


What am I doing wrong? The first line of output,
Honolulu: 2215
, is correct. But the next lines have leading zeroes. I do not understand why this is happening? Is there a problem with my code or am I misunderstanding how the functions
setfill
and
setw
work?

Answer

As mentioned in other comments many of I/O manipulators are "sticky". I personally prefer to solve this kind of problem using 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_;
};

That this class does is backing up your current stream's format upon constructing and setting it back upon destructing.

You can use it this way:

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
}