#include // For abort()
#include
using namespace std;
int main() {
ofstream out("log.txt");
out.setf(ios::unitbuf);
out << "one\n";
out << "two\n";
abort();
} ///:~
It is necessary to turn on unit buffering before any insertions are made to the stream. When we commented out the call to setf( ), one particular compiler had written only the letter ‘o’ to the file log.txt. With unit buffering, no data was lost .
The standard error output stream cerrhas unit buffering turned on by default. There is a cost for unit buffering, of course, so if an output stream is heavily used, don’t enable unit buffering unless efficiency is not a consideration .
The second type of formatting flags work in a group. Only one of these flags can be, like the buttons on old car radios—you push one in, the rest pop out. Unfortunately this doesn’t happen automatically, and you have to pay attention to what flags you’re setting so that you don’t accidentally call the wrong setf( )function. For example, there’s a flag for each of the number bases: hexadecimal, decimal, and octal. Collectively, these flags are referred to as the ios::basefield. If the ios::decflag is set and you call setf(ios::hex), you’ll set the ios::hexflag, but you won’t clear the ios::decbit, resulting in undefined behavior. The proper thing to do is call the second form of setf( )like this: setf(ios::hex, ios::basefield). This function first clears all the bits in the ios::basefieldand then sets ios::hex. Thus, this form of setf( )ensures that the other flags in the group "pop out" whenever you set one. Of course, the ios::hexmanipulator does all this for you, automatically, so you don’t have to concern yourself with the internal details of the implementation of this class or to even care that it’s a set of binary flags. Later you’ll see that there are manipulators to provide equivalent functionality in all the places you would use setf( ) .
Here are the flag groups and their effects:
ios::basefield |
effect |
ios::dec |
Format integral values in base 10 (decimal) (the default radix—no prefix is visible). |
ios::hex |
Format integral values in base 16 (hexadecimal). |
ios::oct |
Format integral values in base 8 (octal). |
ios::floatfield |
effect |
ios::scientific |
Display floating-point numbers in scientific format. Precision field indicates number of digits after the decimal point. |
ios::fixed |
Display floating-point numbers in fixed format. Precision field indicates number of digits after the decimal point. |
"automatic" (Neither bit is set.) |
Precision field indicates the total number of significant digits. |
ios::adjustfield |
Effect |
ios::left |
Left-align values; pad on the right with the fill character. |
ios::right |
Right-align values. Pad on the left with the fill character. This is the default alignment. |
ios::internal |
Add fill characters after any leading sign or base indicator, but before the value. (In other words, the sign, if printed, is left-justified while the number is right-justified). |
Width, fill, and precision
The internal variables that control the width of the output field, the fill character used to pad an output field, and the precision for printing floating-point numbers are read and written by member functions of the same name .
Function |
effect |
int ios::width( ) |
Returns the current width. (Default is 0.) Used for both insertion and extraction. |
int ios::width(int n) |
Sets the width, returns the previous width. |
int ios::fill( ) |
Returns the current fill character. (Default is space.) |
int ios::fill(int n) |
Sets the fill character, returns the previous fill character. |
int ios::precision( ) |
Returns current floating-point precision. (Default is 6.) |
int ios::precision(int n) |
Sets floating-point precision, returns previous precision. See ios::floatfieldtable for the meaning of "precision." |
The filland precisionvalues are fairly straightforward, but widthrequires some explanation. When the width is zero, inserting a value produces the minimum number of characters necessary to represent that value. A positive width means that inserting a value will produce at least as many characters as the width; if the value has fewer than width characters, the fill character is used to pad the field. However, the value will never be truncated, so if you try to print 123 with a width of two, you’ll still get 123. The field width specifies a minimum number of characters; there’s no way to specify a maximum number .
The width is also distinctly different because it’s reset to zero by each inserter or extractor that could be influenced by its value. It’s really not a state variable, but rather an implicit argument to the inserters and extractors. If you want a constant width, call width( )after each insertion or extraction .
To make sure you know how to call all the functions previously discussed, here’s an example that calls them all: .
//: C04:Format.cpp
// Formatting Functions
#include
#include
#include "../require.h"
using namespace std;
#define D(A) T << #A << endl; A
int main() {
ofstream T("format.out");
assure(T);
D(int i = 47;)
D(float f = 2300114.414159;)
const char* s = "Is there any more?";
D(T.setf(ios::unitbuf);)
D(T.setf(ios::showbase);)
D(T.setf(ios::uppercase | ios::showpos);)
D(T << i << endl;) // Default is dec
D(T.setf(ios::hex, ios::basefield);)
D(T << i << endl;)
D(T.setf(ios::oct, ios::basefield);)
D(T << i << endl;)
D(T.unsetf(ios::showbase);)
D(T.setf(ios::dec, ios::basefield);)
D(T.setf(ios::left, ios::adjustfield);)
D(T.fill('0');)
D(T << "fill char: " << T.fill() << endl;)
D(T.width(10);)
T << i << endl;
D(T.setf(ios::right, ios::adjustfield);)
D(T.width(10);)
T << i << endl;
D(T.setf(ios::internal, ios::adjustfield);)
D(T.width(10);)
T << i << endl;
D(T << i << endl;) // Without width(10)
D(T.unsetf(ios::showpos);)
D(T.setf(ios::showpoint);)
D(T << "prec = " << T.precision() << endl;)
D(T.setf(ios::scientific, ios::floatfield);)
D(T << endl << f << endl;)
D(T.unsetf(ios::uppercase);)
D(T << endl << f << endl;)
D(T.setf(ios::fixed, ios::floatfield);)
D(T << f << endl;)
D(T.precision(20);)
D(T << "prec = " << T.precision() << endl;)
Читать дальше