Проблемы c++ iomanip lib setfill и setw
Мой Код:
#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, является правильной. Но в следующих строках есть ведущие нули. Я не понимаю, почему это происходит? Есть ли проблема с моим кодом или я неправильно понимаю, как работают функции setfill и setw?
3 ответов:
Как упоминалось в других комментариях, многие манипуляторы ввода-вывода являются "липкими". Лично я предпочитаю решать такого рода задачи с помощью 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 }
Символ заливки является "липким", поэтому он остается в силе до тех пор, пока вы его не измените.
В вашем случае вы хотите
0в качестве заполнения для числовых полей, но пробел в качестве заполнения для символьных полей, поэтому вам придется установить это явно, что-то вроде этого:cout << setfill(' ') << setw (12) << left << "Seattle:";
Многие объекты
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;
Comments