Oletetaanpa tuoterek.cpp - ohjelmassa että hinnat haluttaisiinkin tulostaa kahdella desimaalilla:
ostream &tulosta(ostream &os) const {
os.precision(2); os.setf(ios::left | ios::showpoint | ios::fixed ); :-(
os << setw(20) << nimike << " " << setiosflags(ios::right)
<< setw(10) << hinta << " "
<< setw(4) << kpl;
return os;
}
...
ostream &operator<<(ostream &os,const cTuote &tuote) {
return tuote.tulosta(os); }
Nyt tietysti voisi olla ohjelmoijalle yllätys, jos hän kutsuisi
cTuote tuote("Volvo|23700|1");
const double pi = 3.14159265;
cout.precision(6);
cout << pi << '\n';
cout << tuote << '\n';
cout << pi << '\n';
ja jälkimmäinen piin arvo tulostuisikin vain kahdella desimaalilla. Tämän vuoksi pitäisi alkuperäiset tulostusasetukset palauttaa, mikäli niitä muutetaan.
ostream &tulosta(ostream &os) const {
long oldf = os.setf(ios::left | ios::showpoint | ios::fixed );
int olddes = os.precision(2);
... tulostusta ...
os.precision(olddes); os.flags(oldf);
return os;
}
Mutta kuka tämän jaksaa tehdä kerrasta toiseen?
Entäpä jos teemmekin luokan cStreamPre ( stream precision ):
ostream &tulosta(ostream &os) const {
cStreamPre pre(os,2);
... tulostusta ...
return os;
}
ja nyt piikin tulee taas pyydetyllä 6:lla desimaalilla molemmilla kerroilla! Miten?
class cStreamPre {
ostream &os;
ios::fmtflags oldf;
int oldp;
public:
cStreamPre(ostream &aos=cout,int npre=1,long flags=0) : os(aos) {
oldf = os.setf(ios::showpoint | ios::fixed | flags);
oldp = os.precision(npre);
}
~cStreamPre() { os.flags(oldf); os.precision(oldp); }
};
Luokan muodostaja tallettaa olion attribuutteihin tulostuksen muotoilun ennen kuin muotoiluja on muutettu. Kun syntyneen olion vaikutusalue lakkaa, eli poistutaan siitä ohjelmalohkosta jossa olio on syntynyt ( auto), kutsutaan olion hajottajaa, joka palauttaa alkuperäiset arvot. Nyt ohjelmoijan tarvitsee vain antaa olion syntyä automaattisesti
cStreamPre pre(os,2);
lohkon alussa. Ja tämähän saadaan vähemmällä kirjoittamisella kuin tarkkuuden muuttaminen normaalisti:
os.precision(2); os.setf(ios::left | ios::showpoint | ios::fixed );
Huomattakoon, että "temppu" toimii vaikka kesken tulostuksen poistuttaisiin ylimääräisellä return--lauseella. Samoin "temppu" toimii, vaikka tulostuksen sisällä kutsuttaisiin toista samalla tavalla toteutettua tulostusta!