- Next chapter
- Previous chapter
- Table of contents

# Chapter 11: The IO-stream Library

> We're always interested in getting feedback. E-mail us if you like this guide, if you think that important material is omitted, if you encounter errors in the code examples or in the documentation, if you find any typos, or generally just if you feel like e-mailing. Mail to Frank Brokken or use an e-mail form. Please state the concerned document version, found in the title.

As an extension to the standard stream (`FILE`) approach well known from the C programming language, C++ offers an I/O library based on `class` concepts.

Earlier (in chapter 3) we've already seen examples of the use of the C++ I/O library. In this chapter we'll cover the library to a larger extent.

Apart from defining the insertion (<<) and extraction(>>) operators, the use of the C++ I/O library offers the additional advantage of type safety in all kinds of standard situations. Objects (or plain values) are inserted into the iostreams. Compare this to the situation commonly encountered in C where the `fprintf()` function is used to indicate by a format string what kind of value to expect where. Compared to this latter situation C++'s iostream approach uses the objects where their values should appear, as in

`cout << "There were " << nMaidens << " virgins present\n";`

The compiler notices the type of the `nMaidens` variable, inserting its proper value at the appropriate place in the sentence inserted into the `cout` iostream.

Compare this to the situation encountered in C. Although C compilers are getting smarter and smarter over the years, and although a well-designed C compiler may warn you for a mismatch between a format specifier and the type of a variable encountered in the corresponding position of the argument list of a `printf()` statement, it can't do much more than warn you. The type safety seen in C++ prevents you from making type mismatches, as there are no types to match.

Apart from this, the iostreams offer more or less the same set of possibilities as the standard streams of C: files can be opened, closed, positioned, read, written, etc.. The remainder of this chapter presents an overview.

In general, input is managed by `istream` objects, having the derived classes `ifstream` for files, and `istrstream` for strings (character arrays), whereas output is managed by `ostream` objects, having the derived classes `ofstream` for files and `ostrstream` for strings.

If a file should allow both reading from and writing to, a `fstream` object (c.q. `strstream` object) should be used.

Finally, in order to use the `iostream` facilities, the header file `iostream` must be included in source files using these facilities. When `ifstream, ofstream` or `fstream` objects are to be used, the `fstream` header file, which in turn includes `iostream`, must be included. An analogous situation holds true for string streams. Here the header file `strstream` is required.

## 11.1: Streams: insertion (<<) and extraction (>>)

The insertion and extraction operators are used to write information to or read information from, respectively, ostream and istream objects (and to all classes derived from these classes). By default, white space is skipped when the insertion and extraction operators are used.

### 11.1.1: The insertion operator <<

The insertion operator (`<<`) points to the `ostream` object wherein the information is inserted. The extraction operator points to the object receiving the information obtained from the `istream` object.

As an example, the `<<` operator as defined with the `class ostream` is an overloaded operator having as prototype, e.g.,

`ostream &ostream::operator <<(char const *text)`

The normal associativity of the `<<`-operator remains unaltered, so when a statement like

(cout << "hello " << "world")
is encountered, the leftmost two operands are evaluated first (`cout << "hello "`), and a `ostream &` object, which is actually the same `cout` object. From here, the statement is reduced to
(cout << "world")
and the second string is inserted into `cout`.

Since the `<<` operator has a lot of (overloaded) variants, many types of variables can be inserted into `ostream` objects. There is an overloaded `<<`-operator expecting an `int`, a `double`, a pointer, etc. etc.. For every part of the information that is inserted into the stream the operator returns the `ostream` object into which the information so far was inserted, and the next part of the information to be inserted is devoured.

As we have seen in the discussion of friends, even new classes can contain an overloaded `<<` operator to be used with `ostream` objects (see sections 13.3 and 13.3.1).

### 11.1.2: The extraction operator >>

With the extraction operator, a similar situation holds true as with the insertion operator, the extraction operator operating comparably to the `scanf()` function. I.e., white space characters are skipped. Also, the operator doesn't expect pointers to variables that should be given new values, but references (with the exception of the `char *`, but `string` variables are used as references).

Consider the following code:

        int
            i1,
            i2;
        char
            c;

        cin >> i1 >> i2;                // see (1)

        while (cin >> c && c != '.')    // see (2)
            process(c);

        char                            // see (3)
            buffer[80];
                                        // see (3)
        while (cin >> buffer)
            process(buffer);

This example shows several characteristics of the extraction operator worth noting. Assume the input consists of the following lines:

        125
        22
        h e l l o
        w o r l d .
        this example shows
        that we're not yet done
        with C++

1. In the first part of the example two int values are extracted from the input: these values are assigned, respectively, to `i1` and `i2`. White-space (newlines, spaces, tabs) is skipped, and the values 125 and 22 are assigned to `i1` and `i2`.

   If the assignment fails, e.g., when there are no numbers to be converted, the result of the extraction operator evaluates to a zero result, which can be used for testing purposes, as in:

   `if (!(cin >> i1))`
2. In the second part, characters are read. However, white space is skipped, so the characters of the words `hello` and `world` are produced by `cin`, but the blanks that appear in between are not.

   Furthermore, the final `'.'` is not processed, since that one's used as a sentinel: the delimiter to end the `while`-loop, when the extraction is still successful.

3. In the third part, the argument of the extraction operator is yet another type of variable: when a `char *` is passed, white-space delimited strings are extracted. So, here the words `this, example, shows, that, we're, not, yet, done, with` and `C++` are returned.

   Then, the end of the information is reached. This has two consequences: First, the `while`-loop terminates. Second, an empty string is copied into the `buffer` variable.

## 11.2: Four standard iostreams

In C three standard files are available: `stdin`, the standard input stream, normally connected to the keyboard, `stdout`, the (buffered) standard output stream, normally connected to the screen, and `stderr`, the (unbuffered) standard error stream, normally not redirected, and also connected to the screen.

In C++ comparable iostreams are

- `cin`, an `istream` object from which information can be extracted. This stream is normally connected to the keyboard.
- `cout`, an `ostream` object, into which information can be inserted. This stream is normally connected to the screen.
- `cerr`, an `ostream` object, into which information can be inserted. This stream is normally connected to the screen. Insertions into that stream are unbuffered.
- `clog`, an `ostream` object, comparable to `cerr`, but using buffered insertions. Again, this stream is normally connected to the screen.

## 11.3: Files and Strings in general

In order to be able to create `fstream` objects, the header file `fstream` must be included. Files to read are accessed through `ifstream` objects, files to write are accessed through `ofstream` objects. Files may be accessed for reading and writing as well. The general `fstream` object is used for that purpose.

String stream objects can be used to read or write objects to streams in memory, allowing the use of, e.g., the insertion and extraction operators on these objects. To use the string stream objects `istrstream, ostrstream` or `strstream` the header file `strstream` must be included. Note that a `strstream` object is not a `string` object. A `strstream` object should be approached like a `fstream` object, not as a `char *` object having special characteristics.

### 11.3.1: String stream objects: a summary

Strings can be processed similarly to `iostream` objects, if objects of the class `istrstream, ostrstream` or `strstream` are constructed. Objects of these classes can be used to, respectively, read information from memory, write information to memory, or both.

These objects can be created by constructors expecting the address of a block of memory (and its size) as its argument. It is also possible to let the objects to the memory management themselves.

Let's go through some examples. To write something into a block of memory using a `ostrstream` object, the following code could be used:

        char
            buffer[100];
        ostrstream
            os(buffer, 100);    // construct the ostrstream object

                                // fill 'buffer' with a well-known text
        os << "Hello world " << endl << ends;

        cout << os.str(); // display the string

Note the final `ends` that is appended: When an ascii-z string is inserted into an `ostrstream` object it will not automatically write a trailing ascii-z sentinel (comparable to the way `ostream` objects behave). In order to append a terminating ascii-z, the symbolic value `ends` can be used. After inserting an `ends` further insertions into the `ostrstream` object will succeed, but they will not normally be visible:

        char
            buffer[100];
        ostrstream
            os(buffer, 100);    // construct the ostrstream object

        os << "Hello world " << ends;

        os << " More text " << ends;

        cout << os.str() << endl; // this only shows 'Hello world'

The information, however, is stored in the string, as shown by the following example:

        void bytes(ostrstream &str)
        {
            char
                *cp = str.str();

            cout << str.pcount() << ": ";

            for (int idx = 0; idx < 10; ++idx)
                cout << setw(3) << static_cast<int>(cp[idx]) << " ";
            cout << endl;
        }

        int main()
        {
            char buffer[10];

            memset(buffer, 10, 10);

            ostrstream
                str(buffer, 100);

            bytes(str);

            str << "A";

            bytes(str);

            str << "B" << ends;

            bytes(str);

            str << "C";

            bytes(str);

            return (0);
        }

This little program produces the following output:

        0:  10  10  10  10  10  10  10  10  10  10
        1:  65  10  10  10  10  10  10  10  10  10
        3:  65  66   0  10  10  10  10  10  10  10
        4:  65  66   0  67  10  10  10  10  10  10

This output shows that all insertions succeed, but the `ends` writes an ascii-z character. This effectively creating an ascii-z string, preventing the display of the information beyond when the contents of the `ostrstream` object are inserted into `cout`.

Furthermore, note the use of the memberfunction `str()`, returning the string the `ostrstream` object operates on. Using `str()` the existence of `buffer` can be hidden from the users of the `ostrstream` object.

When an `ostrstream` object is created without an external memory buffer (e.g., ``ostrstream str;`' is defined), the `ostrstream` object allocates the required memory itself. In that case using the `str()` memberfunction will result in the freezing of the `ostrstream` object: it will no longer create room for new characters when additional text is inserted into the object, and, most important, it will not delete allocated memory when the object itself is deleted.

To prevent memory leakage here, the program using the `str()` memberfunction can take two actions:

- First, as `str()` returns a `char *` rather than a `char const *` the caller of `str()` may consider the returned string its own. Consequently, the caller of `str()` is responsible for deleting the string returned by `str()`. E.g.,

          ostrstram
              ostr;

          ostr << "Hello world" << ends;

          char
              *cp = ostr.gets();  // freezes ostr

          cout << cp;             // use ostr's string
          delete cp;              // caller deletes ostr's string

- Alternatively, the string can be unfrozen, after which insertions are again possible. Now, when the `ostrstream` object is destroyed the `ostrstream`'s internally stored string is destroyed too. E.g.,

          ostrstram
              ostr;

          ostr << "Hello world" << ends;

          char
              *cp = ostr.gets();  // freezes ostr

          cout << cp;             // use ostr's string

          ostr.freeze(0);         // ostr will now delete its own string, cp
                                  // should leave the memory it points to alone.

The following memberfunctions are available for `strstream` objects:

- `istrstream::istrstream(const char *str [, int size])`: This constructor creates an input string class `istrstream` object, associating it with an existing buffer starting at `str`, of size `size`. If `size` is not specified, the buffer is treated as a null-terminated string.
- `ostrstream::ostrstream()`: This constructor creates a new stream for output to a dynamically managed string, which will grow as needed.
- `ostrstream::ostrstream(char *str, int size [, int mode])`: This constructor creates a new stream for output to a statically defined string of length `size`, starting at `str`. The `mode` parameter may optionally be specified as one of the iostream modes. By default `ios::out` is used.
- `int ostrstream::pcount()`: returns the current length of the string associated with this `ostrstream` object.
- `char *ostrstream::str()`: The memberfunction returns a pointer to the string managed by this `ostrstream` object. This function implies `freeze()`, see below:
- `void ostrstream::freeze ([int n])`: If `n` is nonzero (the default), the string associated with this `ostrstream` object must not change dynamically anymore. While frozen, it will not be reallocated if it needs more space, and it will not be deallocated when the `ostrstream` object is destroyed. `freeze(1)` can be used to refer to the string as a pointer after creating it via `ostrstream` facilities. `freeze(0)` can be used to unfreeze (thaw ?) the object again. Following `freeze(0)` the `ostrstream` object will delete memory it allocated when the object itself is deleted.
- `int ostrstream::frozen()`: This member can be used to test whether `freeze(1)` is in effect for this string.

In order to use the `strstream` classes, the header file `strstream` must be included.

### 11.3.2: Writing streams

In order to be able to write to a file an `ofstream` object must be created, in order to be able to write to a string stream an `ostrstream` object must be created.

To open a file to write to, the `ofstream` constructor receives the name of the file to be opened:

`ofstream out("outfile");`

By default this will result in the creation of the file, and information inserted into it will be written from the beginning of the file. Actually, this corresponds to the creation of the `ofstream` object in standard output mode, for which the enumeration value `ios::out` could have been provided as well:

`ofstream out("outfile", ios::out);`

Alternatively, instead of (re)writing the file, the `ofstream` object could be created in the append mode, using the `ios::app` mode indicator:

`ofstream out("outfile", ios::app);`

Normally, information will be inserted into the `ofstream` object using the insertion operator `<<`, in the way it is used with the standard streams like `cout`, e.g.:

`out << "Information inserted into the 'out' stream\n";`

Just like the `fopen()` function of C may fail, the construction of the `ofstream` object might not succeed. When an attempt is made to create an `ofstream` object, it is a good idea to test the successful construction. The `ofstream` object returns 0 if its construction failed. This value can be used in tests, and the code can throw an exception (see chapter 12) or it can handle the failure itself, as in the following code:

        #include <iostream>
        #include <fstream>

        int main()
        {
            ofstream
                out("/");   // creating 'out' fails

            if (!out)
            {
                cerr << "creating ofstream object failed\n";
                exit(1);
            }
        }

Alternatively, a `ofstream` object may be constructed first, and opened later:

        ofstream
            out;

        out.open("outfile");

Here, the return value of `open()` may be inspected to see whether the stream has been successfully opened or not.

Analogous to an `ofstream` object, an `ostrstream` object can be created. Here no filename is required. E.g.,

`ostrstream text;`
opens an empty `ostrstream` object. There is no `open()` member function for `ostrstream` objects.

An `ostrstream` object may be initialized by an ascii-z string. E.g.,

`ostrstream text("hello world");`
These strings expand dynamically when more information is inserted into them. However, the inserted information is not automatically ascii-z terminated. In order to append an ascii-z to the information inserted into an `ostrstream` object an `ends` can be inserted:
`text << ", and there is more." << ends;`
The information that is stored in a `ostrstream` object can be retrieved from its `str()` member, which returns a `char const *`, but realize that this will `freeze' the object, see section 11.3.1. The number of characters returned by `str()` is obtained from the `pcount()` member, returning an `int`.

### 11.3.3: Reading streams

In order to be able to read from a file an `ifstream` object must be created, in order to be able to read from a string stream an `istrstream` object must be created.

To open a file to read from, the `ifstream` constructor receives the name of the file to be opened:

`ifstream in("infile");`

By default this will result in the opening of the file for reading. The file must exist for the `ifstream` object construction to succeed. Instead of the shorthand form to open a file for reading, and explicit `ios` flag may be used as well:

`ifstream in("infile", ios::in);`

As with the `ofstream` objects, `ifstream` objects may be constructed first, and opened later:

        ifstream
            ifstr;

        ifstr.open("infile");

Normally, information will be extracted from the `ifstream` object using the extraction operator `>>`, in the way it is used with the standard stream `cin`, e.g.:

`in >> x >> y;`

By default, the extraction operator skips blanks: between words, between characters, between numbers, etc.. Consequently, if the input consists of the following information:

        12
        13
        a b
        hello world

then the next code fragment will read `12` and `13` into `x` and `y`, will then return the characters `a` and `b`, and will finally read `hello` and `world` into the character array `buffer`:

        int
            x,
            y;
        char
            c,
            buffer[10];

        in >> x >> y >> c >> c >> buffer >> buffer;

Notice that no format specifiers are necessary. The type of the variables receiving the extracted information determines the nature of the extraction: integer values for `int`s, white space delimited strings for `char []`s, etc..

Just like the `fopen()` function of C may fail, the construction of the `ifstream` object might not succeed. When an attempt is made to create an `ifstream` object, it is a good idea to test the successful construction. The `ifstream` object returns 0 if its construction failed. This value can be used in tests, and the code can throw an exception (see section 12) or it can handle the failure itself, as in the following code:

        #include <iostream>
        #include <fstream>

        int main()
        {
            ifstream
                in("");         // creating 'in' fails

            if (!in)
            {
                cerr << "creating ifstream object failed\n";
                exit(1);
            }
        }

Analogous to an `ifstream` object, an `istrstream` object can be created. Here no filename is required. E.g.,

`istrstream text("hello world");`
opens an `istrstream` object that is initialized by an ascii-z string.

### 11.3.4: Reading and writing streams

In order to be able to read and write to a file a `fstream` object must be created. To read and write to a `strstream` a `strstream` object must be created. Again, the constructor receives the name of the file to be opened:

`fstream inout("infile", ios::in | ios::out);`

Note the use of the `ios` constants `ios::in` and `ios::out`, indicating that the file must be opened both for reading and writing. Multiple mode indicators may be used, concatenated by the binary or operator `'|'`. Alternatively, instead of `ios::out`, `ios::app` might have been used, in which case writing will always be done at the end of the file.

Under DOS-like operating systems, which use the multiple character `\r\n` sentinels to separate lines in textfiles the flag `ios::binary` (or `ios::bin`) is required for processing binary files to ensure that `\r\n` combinations are processed as two characters.

With `fstream` objects, the `ios::out` will result in the creation of the file, if the file doesn't exist, and if `ios::out` is the only mode specification of the file. If the mode `ios::in` is given as well, then the file is created only if it doesn't exist. So, we have the following possibilities:

        -------------------------------------------------------------
                                     Specified Filemode
                        ---------------------------------------------
         File:                ios::out            ios::in | ios::out
        -------------------------------------------------------------
         exists           File is rewritten     File is used as found

        doesn't exist      File is created         File is created
        -------------------------------------------------------------

Once a file has been opened in read and write mode, the `<<` operator may be used to write to the file, while the `>>` operator may be used to read from the file. These operations may be performed in random order. The following fragment will read a blank-delimited word from the file, will write a string to the file, just beyond the point where the string just read terminated, and will read another string: just beyond the location where the string just written ended:

        ...
        fstream
            f("filename", ios::in | ios::out);
        char
            buffer[80]; // for now assume this
                        // is long enough

        f >> buffer;    // read the first word

                        // write a well known text
        f << "hello world";

        f >> buffer;    // and read again

Since the operators `<<` and `>>` can apparently be used with `fstream` objects, you might wonder whether a series of `<<` and `>>` operators in one statement might be possible. After all, `f >> buffer` should produce a `fstream &`, shouldn't it?

The answer is: it doesn't. The compiler casts the `fstream` object into an `ifstream` object in combination with the extraction operator, and into an `ofstream` object in combination with the insertion operator. Consequently, a statement like

`f >> buffer << "grandpa" >> buffer;`
results in a compiler error like
`no match for `operator <<(class istream, char[8])'`
Since the compiler complains about the `istream` class, the `fstream` object is apparently considered an `ifstream` object in combination with the extraction operator.

Of course, random insertions and extractions are hardly used. Generally, insertions and extractions take place at specific locations in the file. In those cases, the position where the insertion or extraction must take place can be controlled and monitored by the `seekg()` and `tellg()` memberfunctions.

The memberfunction `tellg()` returns the current offsetposition of the stream for which it is called.

The memberfunction `seekg()` expects two arguments, the second one having a default value:

`seekg(long offset, seek_dir position = ios::beg);`
The first argument is a `long` offset with respect to a `seek_dir` postion. The `seek_dir` position may be one of:

- `ios::beg`: add `offset` to the begin of file position. Negative offsets result in an error condition, which must be cleared before any further operations on the file will succeed.
- `ios::end`: add `offset` to the end of file position. Positive offsets result in the insertion of as many padding `(char)0` characters as necessary to reach the intended offset.
- `ios::cur`: add `offset` to the current file position. If adding the `offset` to the current position would result in a position before `ios::beg`, then, again, an error condition results. If the position would be beyond `ios::end`, then extra `(char)0` characters are supplied.

Error conditions (see also section 11.3.6) occurring due to, e.g., reading beyond end of file, reaching end of file, or positioning before begin of file, can be cleared using the `clear()` memberfunction. Following `clear()` processing continues. E.g.,

        ...
        fstream
            f("filename", ios::in | ios::out);
        char
            buffer[80]; // for now assume this
                        // is long enough

        f.seekg(-10);   // this fails, but...
        f.clear();      // processing f continues

        f >> buffer;    // read the first word

`Strstream` objects can be given flags as well. The `ostrstream` object may be constructed by the following constructor:

`ostrstream text(initext, size, flags);`
where `initext` is an ascii-z terminated initialization text, `size` is the size of the internal buffer of the `strstream` object, and `flags` is a set of `ios` flags. The last and last two arguments are optional. If `size` is specified, the internal buffer will not grow dynamically, but will be given a static size of `size` bytes.

### 11.3.5: Special functions

Apart from the functions discussed so far, and the extraction and assignment operators, several other functions are available for `stream` objects which are worthwhile mentioning.

- `close()`: this function can be used to close a stream explicitly. When an `o(f)stream` is closed, any information remaining in its internal buffer is flushed automatically.
- `gcount()`: this function returns the number of characters read by `getline()` (described below) or `read()` (described below).
- `flush()`: this function flushed the output of the `ostream` object.
- `get()`: returns the next character as an `int`: End-of-file is returned as `EOF`, a value which can't be a character.
- `get(char c)`: this function reads a `char` from an `istream` object, and returns the `istream` object for which the function was called.
  The `get()` and `get(char c)` functions read separate characters, and will not skip whitespace.
- `getline(char *buffer, int size, int delimiter = '\n')`: this function reads up to `size - 1` characters or until `delimiter` was read into `buffer`, and appends a final `ascii-z`. The delimiter is not entered into `buffer`. The function changes the state of the output-stream to fail if a line was not terminated by the delimiter. Since this situation will prevent the function from reading more information, the function `clear` must be called in these circumstances to allow the function to produce more information. The frame for reading lines from an `istream` object is, therefore:

          #include <iostream>

          int main()
          {
              char
                  buffer[100];

              while (1)
              {
                  cin.getline(buffer, 100);
                  cout << buffer;
                  if (cin.eof())
                      return(0);

                  if (cin.good())
                      cout << endl;
                  else
                      cin.clear();
              }
          }

  A disadvantage of `getline()` might be that it requires a buffer of a predetermined size. Alternatively (and preferably) the function
  `istream &getline(istream &input, string &str, char delim);`
  can be used, which reads the next line from `input` into `str`. By default, lines are read until an end of line is seen. By specifying `delim` another line delimiter may be used. The delimiter is not included in the `str` object.
- `istream &ignore([int n] [, int delimiter])`. This function skips over a certain number of characters, but not beyond the `delimiter` character. By default, the `delimiter` character is `end of file' (`EOF`): the function `ignore()` will not skip beyond `EOF`. If the number of characters isn't specified, one character will be skipped.
- `int peek()`. This function returns the character that will be read with the next call to the function `get()`.
- `istream &putback(char c)`. This function attempts to put character `c` back into the stream. The most recently read character character may always be returned into the stream. If the character can't be returned, `EOF` is returned. This function is the analogue of C's `ungetc()` function.
- `int opfx()`. This function should be called before any further processing. If the `ostream` object is in the state `good', `flush()` is called for that object, and 1 is returned. Otherwise, 0 is returned. The `p` in `opfx()` indicates prefix: the function should be called before processing the `ostream` object.
- `int osfx()`: This function is the suffix equivalent for `opfx()`. called at the conclusion of any processing. All the `ostream` methods end by calling `osfx()`.
  If the `unitbuf` flag is set for this stream, `osfx()` flushes any buffered output for it, while any output buffered for the `C` output streams `stdout` and `stderr` files is flushed if the `stdio` flag was set for this stream.
- `istream &read(char *buffer, int size)`: this function reads `size` bytes from the `istream` object calling this memberfunction into `buffer`.
- `ostream &write(char const *str, int length)`: writes `length` characters in `str` to the `ostream` object for which it was called, and it returns the `ostream` object.

### 11.3.6: Good, bad, and ...: IOStream Condition States

Operations on streams may succeed and they may fail for several reasons. Whenever an operation fails, further read and write operations on the stream are suspended. Furtunately, it is possible to clear these error condition, so that a program can repair the problem, instead of having to abort.

Several condition member functions of the `fstreams` exist to manipulate or determine the states of the stream:

- `bad()`: this member function returns a non-zero value when an invalid operation has been requested, like seeking before the begin of file position.
- `eof()`: this member function returns a non-zero value when the stream has reached end of file (`EOF`).
- `fail()`: this member function returns a non-zero value when `eof()` or `bad()` returns a non-zero value.

Note that once one of these error conditions are raised, further processing of the stream is suspended. The member function `good()`, on the other hand, returns a non-zero value when there are no error conditions. Alternatively, the operator `'!'` could be used for that in combination with `fail()`. So `good()` and `!fail()` return identical logical values.

A subtlety is the following: Assume a stream is constructed, but not attached to an actual file. E.g., the statement `ifstream instream` creates the stream object, but doesn't assign it to a file. However, if we next check it's status through `good()` this member will return a non-zero value. The `good' status here indicates that the stream object has been cleanly constructed. It doesn't mean the file is also open. A direct test for that can be performed by inspecting `instream.rdbuf()->is_open`. If non-zero, the stream is open.

When an error condition has occurred (i.e., `fail()` returns a non-zero value), and can be repaired, then the member function `clear()` should be called to clear the error status of the file.

### 11.3.7: Formatting

While the insertion and extraction operators provide elegant ways to read information from and write information to `iostreams`, there are situations in which special formatting is required. Formatting may involve the control of the width of an output field or an input buffer or the form (e.g., the radix) in which a value is displayed. The functions `(v)form()` and `(v)scan()` can be used for special formatting. Although these latter functions are not available in all implementations, they are available with the egcs run-time system.

Apart from these memberfunctions, memberfunctions are available for defining the precision and the way numbers are displayed. Apart from using members, manipulators exist for controlling the display form and the width of output and input elements. Different from member functions, manipulators are part of insertion or extraction statements.

11.3.7.1: The (v)form() and (v)scan() members

To format information to be inserted into a stream the member `form()` is available:

`ostream& form(const char *format, ...);`
Note that this is a member-function, returning a reference to an `ostream` object. Therefore, it can be used in combination with, e.g., the insertion operator:
`cout.form("Hello %s", "world") << endl;`
produces a well known sentence.

The memberfunction `form()` is the analogue of C's `fprintf()` function. When variadic functions are constructed in which information must be inserted into a stream, the memberfunction `vform()` can be used, being the analogue of `vfprintf()`.

To scan information from a stream, the memberfunction `scan()` can be used, which is the analogue of C's `fscanf()` function. Similarly to `vfscanf()`, the memberfunction `vscan()` can be used in variadic functions.

11.3.7.2: Manipulators: dec, hex, oct and other manipulators

The `iostream` objects maintain format states controlling the default formatting of values. The format states can be controlled by memberfunctions and by manipulators. Manipulators are inserted into the stream, the memberfunctions are used by themselves.

The following manipulators are available:

- `dec, hex, oct`: These manipulators enforce the display of integral numbers in, respectively, decimal, hexadecimal and octal format. The default conversion is decimal. The conversion takes effect on information inserted into the stream after processing the manipulators. So, a statement like:
  `cout << 16 << ", " << hex << 16 << ", " << oct << 16;`
  will produce the output
  `16, 10, 20`

- `setbase(int b)`: This manipulator can be used to display integral values using the base 8, 10 or 16. It can be used instead of `oct, dec, hex` in situations where the base of integral values is parameterized.

- `setfill(int ch)`: This manipulator defines the filling character in situations where the values of numbers are too small to fill the width that is used to display these values. By default the blank space is used.

- `setprecision(int width)`: This manipulator can be used to set the precision in which a `float` or `double` is displayed. In order to use manipulators requiring arguments the header file `iomanip` must be included.

- `setw(int width)`: This manipulator expects as its argument the width of the field that is inserted or extracted next. It can be used as manipulator for insertion, where it defines the maximum number of characters that are displayed for the field, and it can be used with extraction, where it defines the maximum number of characters that are inserted into an array.

  For example, to insert 20 characters into `cout`, use:

  `cout << setw(20) << 8 << endl;`

  To prevent array-bounds overflow when extracting from `cin`, `setw()` can be used as well:

  `cin >> setw(sizeof(array)) >> array;`
  A nice feature here is that a long string appearing at `cin` is split into substrings of at most `sizeof(array) - 1` characters, and an ascii-z is appended. Notes:
  - `setw()` is valid only for the next field. It does not act like e.g., `hex` which changes the general state of the output stream for displaying numbers.
  - When `setw(sizeof(someArray))` is used, make sure that `someArray` really is an array, and not a pointer to an array: the size of a pointer, being 2 or 4 bytes, is usually not the size of the array that it points to....
  - In order to use `setw()` the header file `iomanip` must be included.

11.3.7.3: Setting the precision: the member precision()

The function `precision()` is used to define the precision of the display of floating point numbers. The function expects the number of digits (not counting the decimal point or the minus sign) that are to be displayed as its argument. For example,

        cout.precision(4);
        cout << sqrt(2) << endl;
        cout.precision(6);
        cout << -sqrt(2) << endl;

results in the following output:

        1.414
        -1.41421

When used without argument, `precision()` returns the actual precision value:

        cout.precision(4);
        cout << cout.precision() << ", " << sqrt(2) << endl;

Note that `precision()` is not a manipulator, but a memberfunction. Therefore, `cout.precision()` rather than `precision()` is inserted into the stream.

11.3.7.4: (Un)Setting display flags: the member (un)setf()

The memberfunction `setf()` is used to define the way numbers are displayed. It expects one or two arguments, all flags of the `iostream` class. In the following examples, `cout` is used, but other `ostream` objects might have been used as well:

- To display the numeric base of integral values, use
  `cout.setf(ios::showbase)`
  This results in no prefix for decimal values, `0x` for hexadecimal values, `0` for octal values. For example:

          cout.setf(ios::showbase);
          cout << 16 << ", " << hex << 16 << ", " << oct << 16 << endl;

  results in:
  `16, 0x10, 020`
- To display a trailing decimal point and trailing decimal zeros when real numbers are displayed, use
  `cout.setf(ios::showpoint)`
  For example:

          cout.setf(ios::showpoint);
          cout << 16.0 << ", " << 16.1 << ", " << 16 << endl;

  results in:
  `16.0000, 16.1000, 16`
  Note that the last `16` is an integral rather than a real number, and is not given a decimal point.

  If `ios::showpoint` is not used, then trailing zeros are discarded. If the decimal part is zero, then the decimal point is discarded as well.

- Comparable to the `dec, hex` and `oct` manipulators

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

  or

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

  can be used.
- To control the way real numbers are displayed `cout.setf(ios::fixed, ios::floatfield)` or `cout.setf(ios::scientific, ios::floatfield)` can be used. These settings result in, respectively, a fixed value display or a scientific (power of 10) display of numbers. For example,

          cout.setf(ios::fixed, ios::floatfield);
          cout << sqrt(200) << endl;
          cout.setf(ios::scientific, ios::floatfield);
          cout << sqrt(200) << endl;

  results in

          14.142136
          1.414214e+01

- `ios::left`: This format state is used to left-adjust the display of values for which the `setw()` manipulator (see below) is used. The format state can be set using the `setf()` member function, and it can be unset using the `unsetf()` member function. By default values are right-adjusted.

- `ios::internal`: This format state will add the fill-characters (blanks by default) between the minus sign of negative numbers and the value itself.

With `istream` objects the flag `ios::skipws` can be used to control the handling of whitespace characters when characters are extracted. Leading white space characters of numerical values are skipped when `istreamObject.unsetf(ios::skipws)` has been specified, but otherwise they must be read explicitly. Reading a `char *` or `string` variable in this situation will only succeed if the first character to be read isn't a white-space character. The following small program can be used to illustrate the effects of unsetting `ios::skipws`:

    #include <iostream>
    #include <string>

    int main()
    {
        string
            buffer;
        int
            i;
        char
            c;

        cin.unsetf(ios::skipws);

        cin >> i;           // skips leading ws
        cin >> buffer;      // doesn't skip leading ws.

        cout << "got " << i << " and " << buffer << endl;

        while (cin >> c)    // reads individual chars, if the previous
            cout << "got '" << c << "'\n";    // extraction succeeded.

        return (0);
    }

Summarizing:

- `setf(ios::showbase)` is used to display the numeric base of integral values,
- `setf(ios::showpoint)` is used to display the trailing decimal point and trailing zeros of real numbers
- `setf(ios::dec, ios::basefield), setf(ios::hex, ios::basefield)` and `setf(ios::oct, ios::basefield)` can be used instead of the `dec, hex` and `oct` manipulators.
- `cout.setf(ios::scientific, ios::floatfield)` and `cout.setf(ios::fixed, ios::floatfield)` can be used to obtain a fixed or scientific (power of 10) display of real values.
- `setf(ios::left)` is used to left-adjust values in the width of their fields
- `setf(ios::internal)` is used to left-adjust the minus sign of negative values (while the values themselves are right adjusted).
- `ios::skipws` is used to control the handling of white space characters by the extraction operator.

To unset flags, the function `unsetf()` can be used.

### 11.3.8: Constructing manipulators

Using a construction like `cout << hex << 13 << endl` the value 13 is displayed in hexadecimal format. One may wonder by what magic the `hex` manipulator accomplishes this. In this section the construction of manipulators like `hex` is covered.

Actually the construction of a manipulator is rather simple. To start, a definition of the manipulator is needed. Let's assume we want to create a manipulator `w10` which will set the field width of the next field to be written to the `ostream` object to 10. This manipulator is constructed as a function. The `w10` function will have to know about the `ostream` object in which the width must be set. By providing the function with a `ostream &` parameter, it obtains this knowledge. Now that the function knows about the `ostream` object we're referring to, it can set the width in that object.

Furthermore, it must be possible to use the manipulator in a `<<`-sequence. This implies that the return value of the manipulator must be a reference to an `ostream` object also.

From the above considerations we're now able to construct our `w10` function:

        #include <iostream>
        #include <iomanip>

        ostream &w10(ostream &str)
        {
            return (str << setw(10));
        }

The `w10` function can of course be used in a `stand alone' mode, but it can also be used as a manipulator. E.g.,

            #include <iostream>
            #include <iomanip>

            extern ostream &w10(ostream &str);

            int main()
            {
                w10(cout) << 3 << " ships sailed to America" << endl;
                cout << "And " << w10 << 3 << " other ships sailed too." << endl;
            }

The `w10` function can be used as manipulator because the `class ostream` has an overloaded `operator<<` accepting a pointer to a function that takes an `ostream &` and returns an `ostream &`. Its definition is:

        ostream& operator<<(ostream & (*func)(ostream &str))
        {
            return ((*func)(*this));
        }

- Next chapter
- Previous chapter
- Table of contents