Formatted IO with Streams


The class ios (which you can see in the header file iostream.h) contains data members to store all the formatting data pertaining to that stream. Some of this data has a range of values and is stored in variables; the floating-point precision, the output field width, and the character used to pad the output (normally a space). The rest of the formatting is determined by flags, which are usually combined to save space and are referred to collectively as the format flags.


Width, Fill and Precision


Internal variables are used to store those formatting attributes which can take on a range of values: the width of the output field, the fill character used when the data doesn't fill the output field, and the precision for printing floating-point numbers. These internal variables are inspected or changed with the following member functions:


Function Effect
int ios::width() Reads the current width. (Default is 0.) Used for insertion.
int ios::width(int n) Sets the width to 'n', return the previous width. A set width is valid only for the very next insertion.
int ios::fill() Reads the current fill character. (Default is space.)
int ios::fill(int n) Sets the fill character to 'n'. Returns the previous fill character.
int ios::precision() Reads the current floating-point precision. (Default is 6.)
int ios::precision(int n) Sets the floating-point precision to 'n'. Returns the previous precision. See ios::floatfield table for the meaning of "precision."


When the width is zero, inserting a value will produce 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 less 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.



For example, the following code:


     int x=68;

     cout << "-->" << x << "<--" << endl;

     cout << "-->";     cout.width(5);
     cout << x << "<--" << endl;

     cout << "-->";     cout.fill('0');    cout.width(5);
     cout << x << "<--" << endl;

would generate the following output:


     -->68<--
     -->   68<--
     -->00068<--


Format Flags


Those formatting options which do not support a range of values but may be turned on or off are called flags. Before we consider the format flags themselves, let's look at the functions with which we will manipulate the flags. There are several member functions (members of class ios) which you can use to identify or alter the status of one or more format flags. These functions use arguments of type fmtflags, which is actually a typedefed long int.


In order to determine what flags are set, call the ios::flags() function with no parameters. This will return the current format flags as a fmtflags. You can also call this same function to change all the flags at once, by passing a new fmtflags as a parameter. Example:


   fmtflags f;        //A variable to hold the flags in

   f = cout.flags()   //Store the current cout flags in f
   ...
   ...                //Some code in here changes the cout flags
   ...
   cout.flags(f)      //Restore all flags to what was previously saved.
                      //Return value was discarded.

Changing flags with the ios::flags() function forces all the flags to change, which is sometimes useful. More often, you want to change one flag at a time using ios::setf() and ios::unsetf(). In order to use these functions, however, you need to know about the flags you are changing.


What are the flags?


There are two types of formatting flags: ones that are simply on or off, and ones that work in a group with other flags. The on/off flags are:


On/Off flags Effect
ios::skipws Skip white space. (For input; this is the default)
ios::showbase Indicate the numeric base (dec, oct, or hex) when printing an integral value.
ios::showpoint Show decimal point and trailing zeros for all floating-point values.
ios::uppercase Display uppercase A-F for hexadecimal values and E for scientific values.
ios::showpos Show plus sign (+) for positive values.
ios::unitbuf "Unit buffering." The stream is flushed after each insertion. Turn on unit buffering when you want to make sure each character is output as soon as it is inserted into an output stream.
ios::stdio Synchronizes the stream with the C standard I/O system. If you have a program that uses both iostreams and the C standard I/O library, and you discover that your iostream output and printf() output are occuring in the wrong order, try setting this flag.


For example, to turn on the 'showpos' flag for the 'cout' stream, you can:

    cout.setf(ios::showpos);

You may then turn the flag off with:


    cout.unsetf(ios::showpos);

The second type of format flags are organized into groups related by function, but only one flag from the group may be selected at any time. This is similar to the buttons on an old car radio -- you push one in and the rest pop out. Unfortunately, this doesn't happen automatically, so you have to pay careful attention to which flags are set within each group.


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::dec flag is set and you call setf(ios::hex), you'll set the ios::hex flag but you won't clear the ios::dec flag, resulting in undefined behavior. You can remedy this by explicitly clearing the ios::dec flag with unset(ios::dec), or you can call the second form of the function:

    cout.setf(ios::hex,ios::basefield);

which will set the flag specified by the first parameter and clear all other flags within the group specified by the second parameter. Here are the flag groups and their effects:


ios::basefield Effect
ios::dec Format integral values in base 10 (decimal).
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.