Skip to content. Skip to navigation

ICTP Portal

Sections
You are here: Home Manuals on-line PGI Compiler pgC_lib stdlibug 2.3 Formatted Input/Output
Personal tools
Document Actions

2.3 Formatted Input/Output



Click on the banner to return to the user guide home page.

2.3 Formatted Input/Output

This section describes the formatting facilities of iostreams. Here we begin using the predefined streams, and see how to do simple input and output. We then explore in detail how to control parsing and formatting.

2.3.1 The Predefined Streams

There are eight predefined standard streams that are automatically created and initialized at program start. These standard streams are associated with the C standard files stdin, stdout, and stderr, as shown in Table 1:

Table 1: Predefined standard streams with their associated C standard files

Narrow character stream
Wide character stream
Associated C standard files
cin
wcin
stdin
cout
wcout
stdout
cerr
wcerr
stderr
clog
wclog
stderr

Like the C standard files, these streams are all associated by default with the terminal.

The difference between clog and cerr is that clog is fully buffered, whereas output to cerr is written to the external device after each formatting. With a fully buffered stream, output to the actual external device is written only when the buffer is full. Thus clog is more efficient for redirecting output to a file, while cerr is mainly useful for terminal I/O. Writing to the external device after every formatting, to the terminal in the case of cerr, serves the purpose of synchronizing output to and input from the terminal.

The standard streams are initialized in such a way that they can be used in constructors and destructors of static objects. Also, the predefined streams are synchronized with their associated C standard files. See Section 2.10.5 for details.

2.3.2 Input and Output Operators

Now let's try to do some simple input and output to the predefined streams. The iostreams facility defines shift operators for formatted stream input and output. The output operator is the shift operator operator<<(), also called the inserter (defined in Section 2.2.4.1):

cout << "result: " << x << '\n';

Input is done through another shift operator operator>>(), often referred to as the extractor (also defined in Section 2.2.4.1):

cin >> x >> y;

Both operators are overloaded for all built-in types in C++, as well as for some of the types defined in the Standard C++ Library; for example, there are inserters and extractors for bool, char, int, long, float, double, string, etc. When you insert or extract a value to or from a stream, the C++ function overload resolution chooses the correct extractor operator, based on the value's type. This is what makes C++ iostreams type-safe and better than C stdio (see Section 2.2.1.1).

It is possible to print several units in one expression. For example:

cout << "result: " << x;

is equivalent to:

(cout.operator<<("result: ")).operator<<(x);

This is possible because each shift operator returns a reference to the respective stream. Almost all shift operators for built-in types are member functions of their respective stream class.[15] They are defined according to the following patterns:

template<class charT, class traits>
basic_istream<charT, traits>& 
basic_istream<charT, traits>::operator>>(type& x)
{
  // read x
  return *this;
}

and:

template<class charT, class traits>
basic_ostream<charT, traits>&
basic_ostream<charT, traits>::operator<<(type x)
{
  // write x
  return *this;
}

Simple input and output of units as shown above is useful, yet not sufficient in many cases. For example, you may want to vary the way output is formatted, or input is parsed. Iostreams allow you to control the formatting features of its input and output operators in many ways. With iostreams, you can specify:

  • The width of an output field and the adjustment of the output within this field;

  • The precision and format of floating point numbers, and whether or not the decimal point should always be included;

  • Whether you want to skip white spaces when reading from an input stream;

  • Whether integral values are displayed in decimal, octal or hexadecimal format,

and many other formatting options.

There are two mechanisms that have an impact on formatting:

  • Formatting control through a stream's format state, and

  • Localization through a stream's locale.

The stream's format state is the main means of format control, as we will demonstrate in the next section.

2.3.3 Format Control Using the Stream's Format State

2.3.3.1 Format Parameters

Associated with each stream are a number of format state variables that control the details of formatting and parsing. Format state variables are classes inherited from a stream's base class, either ios_base or basic_ios<charT,traits>. There are two kinds of format parameters:

  • Parameters that can have an arbitrary value. The value is stored as a private data member in one of the base classes, and set and retrieved through public member functions inherited from that base class. There are three such parameters, described in Table 2 below:

    Access function
    Defined in

    base class
    Effect
    Default
    width()
    ios_base
    Minimal field width
    0
    precision()
    ios_base
    Precision of floating point values
    6
    fill()
    basic_ios
    Fill character for padding
    The space character

  • Parameters that can have only a few different values, typically two or three. They are represented by one or more bits in a data member of type fmtflags in class ios_base. These are usually called format flags. You can set format flags using the setf() function in class ios_base, clear them using unsetf(), and retrieve them through the flags() function.

    Some format flags are grouped because they are mutually exclusive; for example, output within an output field can be adjusted to the left or to the right, or to an internally specified adjustment. One and only one of the corresponding three format flags, left, right, or internal, can be set.[16] If you want to set one of these bits to 1, you need to set the other two to 0. To make this easier, there are bit groups whose main function is to reset all bits in one group. The bit group for adjustment is adjustfield, defined as left | right | internal.

Table 3 below gives an overview of all format flags and their effects on input and output operators. (For details on how the format flags affect input and output operations, see the Class Reference entry for ios_base.) The first column below, format flag, lists the flag names; for example, showpos stands for ios_base::showpos. The group column lists the name of the group for flags that are mutually exclusive. The third column gives a brief description of the effect of setting the flag. The stdio column refers to format characters used by the C functions scanf() or printf() that have the same or similar effect. The last column, default, lists the setting that is used if you do not explicitly set the flag.

Table 3: Flags and their effects on operators



Format flag
Group
Effect
stdio
Default
  adjustfield
Adds fill characters to certain generated output for adjustment:
  left[17]
left
right
internal
  left
right
adds fill characters at designated internal point
-
0
 
basefield
Converts integer input or generates integer output in:
%i
dec
dec
  decimal base
%d,%u
 
oct
  octal base
%o
 
hex
  hexadecimal base
%x
 
floatfield
Generates floating point output:
%g,%G
fixed
fixed
  in fixed-point notation
%f
 
scientific
  in scientific notation
%e,%E
 
boolalpha
  Inserts and extracts bool values in alphabetic format
  0
showpos
  Generates a + sign in non-negative generated numeric output
+
0
showpoint
  Always generates a decimal-point in generated floating-point output
#
0
showbase
  Generates a prefix indicating the numeric base of a generated integer output
  0
skipws
  Skips leading white space before certain input operations
  1
unitbuf
  Flushes output after each formatting operation
  0
uppercase
  Replaces certain lowercase letters with their uppercase equivalents in generated output
%X
%E
%G
0

The effect of setting a format parameter is usually permanent; that is, the parameter setting is in effect until the setting is explicitly changed. The only exception to this rule is the field width. The width is automatically reset to its default value 0 after each input or output operation that uses the field width. Here is an example:

int i; char* s[11];
cin >> setw(10) >> i >> s;                                    \\1
cout << setw(10) <<i << s;                                    \\2
//1Extracting an integer is independent of the specified field width. The extractor for integers always reads as many digits as belong to the integer. As extraction of integers does not use the field width setting, the field width of 10 is still in effect when a character sequence is subsequently extracted. Only 10 characters will be extracted in this case. After the extraction, the field width is reset to 0.
//2The inserter for integers uses the specified field width and fills the field with padding characters if necessary. After the insertion, it resets the field width to 0. Hence, the subsequent insertion of the string will not fill the field with padding characters for a string with less than 10 characters.

Please note: With the exception of the field width, all format parameter settings are permanent. The field width parameter is reset after each use.

The following code sample shows how you can control formatting by using some of the parameters:

#include <iostream>
using namespace ::std;
// _
ios_base::fmtflags original_flags = cout.flags();             \\1
cout<< 812<<'|';
cout.setf(ios_base::left,ios_base::adjustfield);              \\2
cout.width(10);                                               \\3
cout<< 813 << 815 << '\n';
cout.unsetf(ios_base::adjustfield);                           \\4
cout.precision(2);
cout.setf(ios_base::uppercase|ios_base::scientific);          \\5
cout << 831.0 << ' ' << 8e2;
cout.flags(original_flags);                                   \\6
//1Store the current format flag setting, in order to restore it later on.
//2Change the adjustment from the default setting right to left.
//3Set the field width from its default 0 to 10. A field width of 0 means that no padding characters are inserted, and this is the default behavior of all insertions.
//4Clear the adjustment flags.
//5Change the precision for floating-point values from its default 6 to 2, and set yet another couple of format flags that affect floating-point values.
//6Restore the original flags.

The output is:

812|813       815
8.31E+02 8.00E+02

2.3.3.2 Manipulators

Format control requires calling a stream's member functions. Each such call interrupts the respective shift expression. But what if you need to change formats within a shift expression? This is possible in iostreams. Instead of writing:

cout<< 812 << '|';
cout.setf(ios_base::left,ios_base::adjustfield);
cout.width(10);
cout<< 813 << 815 << '\n';

you can write:

cout<< 812 << '|' << left << setw(10) << 813 << 815 << endl;

In this example, objects like left, setw, and endl are called manipulators. A manipulator is an object of a certain type; let's call the type manip for the time being. There are overloaded versions of basic_istream <charT,traits>:: operator>>() and basic_ostream <charT,traits>:: operator<<() for type manip. Hence a manipulator can be extracted from or inserted into a stream together with other objects that have the shift operators defined. (Section 2.8 explains in greater detail how manipulators work and how you can implement your own manipulators.)

The effect of a manipulator need not be an actual input to or output from the stream. Most manipulators set just one of the above described format flags, or do some other kind of stream manipulation. For example, an expression like:

cout << left; 

is equivalent to:

cout.setf (ios_base::left, ios_base::adjustfield);.

Nothing is inserted into the stream. The only effect is that the format flag for adjusting the output to the left is set.

On the other hand, the manipulator endl inserts the newline character to the stream, and flushes to the underlying stream buffer. The expression:

cout << endl; 

is equivalent to:

cout << '\n'; cout.flush();

Some manipulators take arguments, like setw(int). The setw manipulator sets the field width. The expression:

cout << setw(10);

is equivalent to:

cout.width(10);

In general, you can think of a manipulator as an object you can insert into or extract from a stream, in order to manipulate that stream.

Some manipulators can be applied only to output streams, others only to input streams. Most manipulators change format bits only in one of the stream base classes, ios_base or basic_ios<charT,traits>. These can be applied to input and output streams.

Table 4 below gives an overview of all manipulators defined by iostreams. The first column, Manipulator, lists its name. All manipulators are classes defined in the namespace ::std. The second column, Use, indicates whether the manipulator is intended to be used with istreams (i), ostreams (o), or both (io). The third column, Effect, summarizes the effect of the manipulator. The last column, Equivalent, lists the corresponding call to the stream's member function.

Note that the second column indicates only the intended use of a manipulator. In many cases, it is possible to apply an output manipulator to an input stream, and vice versa. Generally, this kind of non-intended manipulation is harmless in that it has no effect. For instance, if you apply the output manipulator showpoint to an input stream, the manipulation will simply be ignored. However, if you use an output manipulator on a bidirectional stream during input, the manipulation will affect not current input operations, but subsequent output operations.

Table 4: Manipulators

Manipulator
Use
Effect
Equivalent
boolalpha
io
Puts bool values in alphabetic format
io.setf(ios_base::boolalpha)
dec
io
Converts integers to/from decimal notation
io.setf(ios_base::dec, ios_base::basefield)
endl
o
Inserts newline and flushes buffer
o.put(o.widen('\n'));
o.flush()
ends
o
Inserts end of string character
o.put(o.widen('\0'))
fixed
o
Puts floating point values in fixed-point notation
o.setf(ios_base::fixed, ios_base::floatfield)
flush
o
Flushes stream buffer
o.flush()
hex
io
Converts integers to/from hexadecimal notation
io.setf(ios_base::hex, ios_base::basefield)
internal
o
Adds fill characters at a designated internal point
o.setf(ios_base::internal, ios_base::adjustfield)
left
o
Adds fill characters for adjustment to the left
o.setf(ios_base::left, ios_base::adjustfield)
noboolalpha
io
Resets the above
io.unsetf(ios_base::boolalpha)
noshowbase
o
Resets the above
o.unsetf (ios_base::showbase)
noshowpoint
o
Resets the above
o.unsetf (ios_base::showpoint)
noshowpos
o
Resets the above
o.unsetf (ios_base::showpos)
noskipws
i
Resets the above
i.unsetf(ios_base::skipws)
nounitbuf
o
Resets the above
o.unsetf(ios_base::unitbuf)
nouppercase
  Resets the above
o.unsetf (ios_base::uppercase)
oct
io
Converts to/from octal notation
io.setf(ios_base::oct, ios_base::basefield)
resetiosflags (ios_base::fmtflags mask)
io
Clears ios flags
io.setf((ios_base::fmtflags)0, mask)
right
o
Adds fill characters for adjustment to the right
o.setf(ios_base::right, ios_base::adjustfield)
scientific
  Puts floating point values in scientific notation
o.setf(ios_base::scientific, ios_base::floatfield)
setbase
(int base)
io
Sets base for integer notation (base = 8, 10, 16)
io.setf (base == 8?ios_base::oct: base == 10 ?
ios_base::dec : base == 16 ?
ios_base::hex :
ios_base::fmtflags(0),
ios_base::basefield)
setfill(charT c)
io
Sets fill character for padding
io.fill(c)
setiosflags (ios_base::fmtflags mask)
io
Sets ios flags
io.setf(mask)
setprecision
(int n)
io
Sets precision of floating point values
io.precision(n)
setw(int n)
io

Sets minimal field width


io.width(n)
showbase
o
Generates a prefix indicating the numeric base of an integer
o.setf(ios_base::showbase)
showpoint
o
Always generates a decimal-point for floating-point values
o.setf(ios_base::showpoint)
showpos
o
Generates a + sign for non-negative numeric values
o.setf(ios_base::showpos)
skipws
i
Skips leading white space
i.setf(ios_base::skipws)
unitbuf
o
Flushes output after each formatting operation
o.setf(ios_base::unitbuf)
uppercase
o
Replaces certain lowercase letters with their uppercase equivalents
o.setf(ios_base::uppercase)
ws
i
Skips white spaces
 

2.3.4 Localization Using the Stream's Locale

Associated with each stream is a locale that impacts the parsing and formatting of numeric values. This is how localization of software takes place. As discussed in the section on locale, the representation of numbers often depends on cultural conventions. In particular, the decimal point need not be a period, as in the following example:

cout.imbue(locale("De_DE"));
cout << 1000000.50 << endl; 

The output will be:

1000000,50

Other cultural conventions, like the grouping of digits, are irrelevant. There is no formatting of numeric values that involves grouping.

2.3.5 Formatted Input

In principle, input and output operators behave symmetrically. There is only one important difference: for output you control the precise format of the inserted character sequence, while for input the format of an extracted character sequence is never exactly described.

This is for practical reasons. You may want to extract the next floating point value from a stream, for example, without necessarily knowing its exact format. You want it whether it is signed or not, or in exponential notation with a small or capital E for the exponent, etc. Hence, extractors in general accept an item in any format permitted for its type.

Formatted input is handled as follows:

  1. Extractors automatically ignore all white space characters (blanks, tabulators, newlines [20]) that precede the item to be extracted.

  2. When the first relevant character is found, they extract characters from the input stream until they find a separator; that is, a character that does not belong to the item. White space characters in particular are separators.

  3. The separator remains in the input stream and becomes the first character extracted in a subsequent extraction.

Several format parameters, which control insertion, are irrelevant for extraction. The format parameter fill character, fill(), and the adjustment flags, left, right, and internal, have no effect on extraction. The field width is relevant only for extraction of strings, and ignored otherwise.

2.3.5.1 Skipping Characters

You can use the manipulator noskipws to switch off the automatic skipping of white space characters. For example, extracting white space characters may be necessary if you expect the input has a certain format, and you need to check for violations of the format requirements. This procedure is shown in the following code:

cin >> noskipws;
char c;
do 
{ float fl;
  c = ' '; cin >> fl >> c;  // extract number and separator
if (c == ',' || c == '\n')  // next char is ',' or newline ?
    process(fl);            // yes: use the number
}
while (c == ',');
if (c != '\n') error();     // no: error!

If you have to skip a sequence of characters other than white spaces, you can use the istream's member function ignore(). The call:

basic_ifstream<myChar,myTraits> InputStream("file-name");
InputStream.ignore(numeric_limits<streamsize>::max()
                  ,myChar('\n'));

or, for ordinary tiny characters of type char:

ifstream InputStream("file-name");
InputStream.ignore(INT_MAX,'\n');

ignores all characters until the end of the line. This example uses a file stream that is not predefined. File streams are described in Section 2.5.3.

2.3.5.2 Input of Strings

When you extract strings or character arrays from an input stream, characters are read until:

  • A white space character is found, or

  • The end of the input is reached, or

  • A certain number of characters are extracted, if width() != 0: In case of a string this number is the field width width(). In case of a character array this number is width()-1.

Note that the field width will be reset to 0 after the extraction of a string.

There are subtle differences between extracting a character sequence into a character array and extracting it into a string object. For example:

char buf[SZ];
cin >> buf;

is different from:

string s;
cin >> s;

Extraction into a string is safe, because strings automatically extend their capacity as necessary. You can extract as many characters as you want since the string always adjusts its size accordingly. Character arrays, on the other hand, have fixed size and cannot dynamically extend their capacity. If you extract more characters than the character array can take, the extractor writes beyond the end of the array. To prevent this, you must set the field width as follows each time you extract characters into a character array:

char buf[SZ];
cin >> width(SZ) >> buf;

©Copyright 1996, Rogue Wave Software, Inc.


Powered by Plone This site conforms to the following standards: