Format flags
One can modify the format flag of a stream with the help of special predefined flags which are static members of ios_base class (they can also be accessed by referring to a derived class ios), for example: ' ios::left', ' ios::scientific' etc. These flags are constants of typeios::fmtflags (some older compilers do not support this type; usually type long can be used instead in such a case). Note that type namefmtflags is declared within ios_base class, so must be referred to by its qualified name ios_base::fmtflags (or just ios::fmtflags).
Bit representation of flags usually contains one bit set (1) and the remaining bits unset (0). One can then construct a format flag with desired properties by „ORing” several flags with bitwise OR operator ('|').
Before we present a few examples, let us list the flags which can be used to produce a format flag of a stream. Flags boolalpha, showbase,showpoint, showpos, skipws, unitbuf and uppercase have „opposite” counterparts — their names are prefixed with ' no', e.g.,noboolalpha, noshowbase etc.
ios::left, ios::right, ios::internal — output data will be left or right justified within the width of a character field. „Internal” justification means „sign (or other prefix, like 0x) to the left, number to the right”. For example, if we print the number -123 within an 8 character wide field, we get with the three justifications
|-123 | | -123| |- 123|The three flags constitute one format field ios::adjustfield. At most one of the flags from the field can be set. If none is set, text will be right justified.
ios::dec, ios::hex, ios::oct — defines the base to which integral values are printed: decimal (default), hexadecimal and octal. Together they constitute format field ios::basefield. At most one of the flags from the field can be set. If none is set, base 10 will be used.
ios::scientific, ios::fixed — define a format for floating point numbers. Together they constitute format field ios::floatfield. At most one of the flags from the field can be set. If none is set, the default „general” format will be used. In scientific notation (flag scientific), one significant digit is writen before the decimal point, then as many digits as determined by the current precision, and then the letter 'e' followed by a number indicating the exponent of 10 by which the number appearing to the left of 'e' should be multiplied. Before the number and before the exponential part, a minus sign is output, if appropriate. For example, 1.123456e2 means 112.3456, while -1.123456e-3 is -0.001123456. In fixed format (flag fixed), numbers are output with as many digits after the decimal point as determined by the current value of precision. General format (the default) leaves the decision to the compiler — scientific or fixed format will be used depending on which one of them will fit smaller width with the same precision.
ios::boolalpha — if boolalpha is set, boolean values will be output as literals 'true' and 'false', instead of their numerical equivalents 1 and 0 (default: NO).
ios::showbase — if set, prefixes 0 and 0x will be added if an integral number is output in octal or hexadecimal representation (default: NO).
ios::showpoint — always show decimal point for floating point numbers, even if the fractional part is zero (default: NO).
ios::uppercase — if set, letters 'e' in scientific notation and 'x' in hexadecimal notation are output in uppercase (default: NO).
ios::unitbuf — if set, the buffer of output stream is flushed after each insertion to the stream (default: NO).
As we have already mentioned, some flags form groups, called fields. This is because they are not independent: you cannot ask for hexadecimal and octal notation simultaneously. Therefore, flags ios::dec, ios::hex and ios::oct belong to field ios::basefield; flagsios::left, ios::right and ios::internal to field ios::adjustfield and flags ios::scientific and ios::fixed to field ios::floatfield. Flags which are members of fields have to be set in a special way, which will be described in the following.
A format flag is an attribute of every object representing a stream, so to access it, methods of object's class should be invoked for this object (e.g., for cin or cout). The most important of these methods are:
ios::fmtflags flags(ios::fmtflags flg) — returns the format flag and sets its new value to flg.
To set new format flag for a stream, one can first construct it by ORing predefined flags and then call the methods described above, e.g.,
1. // construct new flag 2. ios::fmtflags n = ios::hex | ios::showbase 3. | ios::uppercase; 4. // set new flag and remember 5. // its old value 6. ios::fmtflags o = cout.flags(n); 7. // 8. // ... use new settings 9. // 10. cout.flags(o); // restore old settingsNote that on line 6 we set a new value for the flag, but we remembered its old value; in this way we were able to restore old settings in the last line.
Sometimes we do not want to change the format flag entirely, but only add one flag to it. One can do it in the following way:
// retrieve old flag ios::fmtflags oldf = cout.flags(); // create new one ios::fmtflags newf = oldf | ios::showpos; // set new one cout.flags(newf); // ... use new settings // ... and restore old settings cout.flags(oldf);This way of setting the format flag can be somewhat troublesome, therefore there exist methods allowing to do it in a more direct way.
ios::fmtflags setf(ios::fmtflags flg) — modifies the format flag by ORing it with flag flg; returns the original format flag;
ios::fmtflags setf(ios::fmtflags flg, ios::fmtflags field) modifies the format flag by ORing it with flag flg which belongs to field field; unsets the other flags from the same field; returns the original format flag. Flags which are members of fields should be set in this way in order to avoid a situation when two mutually exclusive flags are set simultaneously. For example
cout.setf(ios::scientific, ios::floatfield);
ios::fmtflags unsetf(ios::fmtflags flg) — unsets flag flg in the format flag by ANDing the latter with bitwise negation of flg.
P122: flags.cpp Format flags
1. #include <iostream> 2. using namespace std; 3. 4. typedef ios_base::fmtflags FFLAG; 5. 6. int main() { 7. int m = 49; 8. double x = 21.73; 9. 10. cout << "1. m = " << m << ", x = " << x << endl; 11. 12. FFLAG newf = ios::hex | ios::showbase 13. | ios::showpoint; 14. FFLAG oldf = cout.flags(newf); 15. cout << "2. m = " << m << ", x = " << x << endl; 16. 17. cout.setf(ios::scientific, ios::floatfield); 18. cout.unsetf(ios::showbase); 19. cout << "3. m = " << m << ", x = " << x << endl; 20. 21. cout.setf(ios::fixed, ios::floatfield); 22. cout.setf(ios::showbase | ios::uppercase); 23. cout << "4. m = " << m << ", x = " << x << endl; 24. 25. cout.flags(oldf); 26. cout << "5. m = " << m << ", x = " << x << endl; 27. }
1. m = 49, x = 21.73 2. m = 0x31, x = 21.7300 3. m = 31, x = 2.173000e+01 4. m = 0X31, x = 21.730000 5. m = 49, x = 21.73Note that the default precision is 6, but the meaning of this fact depends on formatting: for scientific and fixed formats the 6 refers to the number of digits after the decimal point (see lines 3 and 4), while for general format it denotes the total number of significant digits (line 2). Additionally, if ios::showpos is not set, trailing zeros are omitted (lines 1 and 5). On line 4 of the program above, we have assigned a name to the type ios_base::fmtflags using the typedef — in this way we can use this alias instead of typing the, somewhat lengthy, true name of this type.
Class ios defines also methods which allow us to specify the field width (number of character) within which a given piece of data is to be output and methods for modifying the current precision. Being methods, they always have to be called for a specific object (stream), e.g., forcout or cin:
streamsize width( ) — returns the current setting for the field width (length of the string within which a piece of data is to be output). The value 0 means „as many characters as necessary, but not more”. Type streamsize is a synonym of a signed integral type.
streamsize width(streamsize wid) — sets the value wid for the current field width; returns original setting. Note that field width is a minimum length of the output sequence of characters; if a given piece of data does not fit this size, it will not be truncated, but the field width actually used will be expanded as needed (as if field width were 0).
streamsize precision( ) — returns current setting of the floating-point numbers precision for this stream — see comments on precision after the program flags.cpp.
streamsize precision(streamsize prec) — sets new value, prec, for precision, returns the previous value.
char fill( ) — returns the character which is currently used for padding if output field is longer than data to be printed (a space character by default).
char fill(char chr) — sets new value, chr, for padding character, returns the previous value.
It should be kept in mind that
- setting the width of output field by invoking width(int wid) function affects only to the next stream insertion (write) operation; after that the default value (which is zero, meaning „as many as necessary”) will be restored;
- on the other hand, modifying precision of padding character is persistent — new settings will apply until they are explicitly changed.
char str[10]; cin.width(sizeof(str)); cin >> str;will read at most 9 characters from keyboard, appending ' \0' as the tenth, if necessary— this guarantees that even when the user typed more characters than expected, superfluous characters will not overflow the array str (corrupting the memory). These superfluous character will then remain in the keyboard buffer and will be input during the next stream extraction (read) operation (what can lead to confusion...). We will tell how one can clear the buffer in a moment.
No comments:
Post a Comment