Description
By default, stream output using << uses builtin rules about formatting, for example, how many significant digits a formatted floating-point number should have. These default rules can be changed by the user.
One way of changing the defaults is illustrated by:
cout.precision(4);and another way is:
cout << boolalpha << true;The first of these is a conventional member function call, while the second is an instance of a manipulator. A manipulator is a mechanism for changing formatting rules on the fly. In this example, boolalpha is used to change the formatting such that a bool is output as false or true instead of 0 or 1. Common manipulators include setprecision, scientific, hex, and uppercase.
Related to formatting is the issue of checking the I/O stream for error conditions. One way to do this is to use rdstate() on the stream:
if (cout.rdstate() & ios_base::badbit) // errorThis is useful, for example, in a case where a disk has a bad sector on it, that cannot be read.
Concept
The sample program first outputs a floating-point number, after setting its precision to 2 (the total number of digits). Then scientific notation (d.ddddEdd) is set and the number is output again. The stream error state is checked, and the stream formatting values reset to their defaults.
Next, a bool value is output using both the default 0/1 format, and using the false/true format.
Then, a user-defined manipulator colon is used to format output. In this example, colon is a function that takes an ostream& argument. In the standard I/O library is an operator<< function that takes another function pointer as its parameter, and calls that function. This mechanism provides the linkage to make manipulators work.
Finally, a complex number type is defined, consisting of (real,imaginary) pairs of numbers. Outputting a value of this type using default formatting rules is straightforward; the two halves of the number are simply output in turn. But applying formatting rules to a user-defined type is a bit harder. For example, you might want the formatting rules to apply to the type only, and not permanently change the underlying I/O stream.
To achieve this end, a formatting class is defined, in this example Fmt. It captures the details of formatting, for example the precision. Then another class, Bound, is used to combine an output value together with a Fmt into an object. Finally, an output operator for the Bound object is defined.
For example, a call:
Complex c(12.3456, 98.7654); Fmt f(4); cout << f(c) << endl;turns into:
cout << Bound(f, c) << endl;This call in turn uses an ostringstream object to format the output into a string. This is done so that the actual I/O stream state is unaffected by the format settings. Finally, the string is output to the actual cout stream.
Output of the program is:
12.3456 12 1.2346e+01 1 true The number is: 12.3456 (12.3456,98.7654) (12.35,98.77) 12.3456
Supported
Supported
Supported