C++ Reference Material
Input and Output
This page contains a summary of many things you may find it useful to know when dealing with input and output in C++, whether it be standard I/O, or file I/O. The starting point for much of the material that you will find here was Chapter 8 of Neill Graham's Learning C++ (McGraw-Hill, 1991). That chapter, though somewhat outdated at the time of this writing (summer, 2003), still contains an excellent short summary of C++ I/O. A number of other references from the Annotated C++ Book List were also consulted in the preparation of this page. This material is very difficult to find all in one place and in useful summary form. Since the current presentation is unlikely to be regarded as definitive, comments are welcome.
The current page will be most useful to you if all of the following are true, and this is what the page assumes:
cinto read various kinds of input from the keyboard, and
coutto write various kinds of output to the screen.
The purpose of the current page is to provide more detailed information on some of the more commonly used I/O facilities that are available from the C++ Stream-Related Headers. For convenience, some of that information is repeated on this web page, and there are also direct links from this page to various parts of that material.
The four basic input/output classes are pictured below in a simple UML class diagram, which shows their (multiple-inheritance) relationship. (By the way, UML = Unified Modeling Language, a language for describing, among other things, C++ class relationships by the use of diagrams like that shown.) Class ios is the (virtual) base class for both istream and ostream, which are both, in turn, base classes for iostream.
All of these classes are generally available by including the <iostream> header. However, it is worth pointing out that the Standard does not require that the iostream header automatically include the ios, istream and iostream headers, and in any case it is just good programming practice to include explicitly each header you need, even if it might be included by another header you are using.
Class ios provides a number of basic facilities used by all the other input/output classes, and which include the features in the list shown below. See this part of the Standard Library Reference on this site for additional details.
Class istream provides facilities for reading formatted input, including an overloaded extraction operator, operator>>, and other input functions. See this part of the Standard Library Reference on this site for additional details.
Class ostream provides facilities for writing formatted output, including an overloaded insertion operator, operator<<, and other output functions. See this part of the Standard Library Reference on this site for additional details.
Class iostream provides facilities for both the reading and the writing of formatted output, which are inherited from istream and ostream. It also provides four "standard" objects for dealing with "standard I/O", as discussed in the following section. See this part of the Standard Library Reference on this site for additional details.
Although a C++ program may read input from a variety of sources, and write output to a variety of destinations, the console keyboard and the console screen have traditionally been the source and destination (respectively) of program I/O. For that reason we generally refer to, and think of, the keyboard as the "standard input" for a C++ program, and the screen as the "standard output". Either or both of these may be "redirected" at run time to come from some other source, or go to some other destination, such as a file. How this is done, and whether it can be done at all, will depend on the operating system under which the program is running.
In addition to "standard output", C++ programs automatically provide a "standard error" object where error messages can be written, and a "standard log" where the program may write a log of whatever program activities may later be of interest. In the simplest case all of these "output" objects are tied to the console screen, but this is only the most frequent and obvious default. Here, then, are the four "Standard I/O" objects, made available by including the <iostream> header:
Each of these objects is initialized and "set up for business" before the main program begins, and none is destroyed during normal program execution, so they can all be used throughout the life of a program.
A format state governs how output values will be printed and how input values will be interpreted, and consists of
Each format flag is designated by name with an ios constant, as shown in the table which follows. The table also gives the purpose of each flag. Note as well that there are certain groups of flags, called bit fields, three of which also have names provided by ios constants. Further details on these bit fields are given in the notes following the table. Some of these flags apply only to input streams, others only to output streams, while some apply to both. For more specific information on this, see the table of manipulators later on this page.
|Flag||Bit Field||Flag Purpose|
|ios::left||ios::adjustfield||Left-justify all output|
|ios::right||Right-justify all output|
|ios::internal||Left-justify sign or base indicator, and right-justify rest of number|
|ios::dec||ios::basefield||Display integers in base 10 (decimal) format|
|ios::oct||Display integers in base 8 (octal) format|
|ios::hex||Display integers in base 16 (hexadecimal) format|
|ios::fixed||ios::floatfield||Use fixed point notation when displaying floating-point numbers (the usual convention)|
|ios::scientific||Use exponential (i.e., scientific) notation when displaying floating-point numbers|
|ios::showbase||Show base indicator when displaying integer output|
|ios::showpoint||Show decimal point when displaying floating-point numbers (default is 6 significant digits)|
|ios::showpos||Show a leading plus sign (+) when displaying positive numbers|
|ios::uppercase||Use uppercase E when displaying exponential or hexadecimal numbers|
|ios::boolalpha||Use textual rather than numerical format to read and write boolean values (true and false, rather than 1 and 0)|
|ios::skipws||Skip whitespace on input|
|ios::unitbuf||Flush output buffer after each insertion (which really has nothing to do with formatting)|
Some notes to keep in mind about the contents of the above table:
file.setf(ios::dec | ios::showpoint | ios::fixed)which would set all three indicated flags (and leave the other flags unchanged). The logical OR operator can also be used.
A format state also has the following three parameters:
As we have noted above, the fieldwidth parameter is not persistent, in that it only applies to the next input or output item. That begs the question: What about the fill character and the precision value–are they persistent? You should write a short sample program to perform some tests suitable for answering this question.
Both format-state flags and format-state parameters can be controlled either by member functions of the stream classes, or by stream manipulators. This gives the programmer many options, and with this come the eternal compromises that have to be made between extra flexibility with extra power, and extra complexity with potential confusion.
The following three stream member functions (note that the first two have two versions each) may be used to deal with format-state flags.
Typical uses of the two-parameter version of this function look like this:
stream.setf(ios::left, ios::adjustfield) stream.setf(0, ios::floatfield)That second example above clears all flags in the ios::floatfield bit field.
The following three stream member functions (each with two versions) may be used to deal with format-state parameters.
A manipulator is a function object that can be used as an operand to an input or output operator to manipulate a stream. There are two kinds of manipulators, those that take parameters and those that do not. Many manipulators have names that suggest the format-state flags that they set, or unset, or the format-state parameters they give values to, for that is what many (but not all) manipulators do.
The following tables show the available manipulators, and indicate, where applicable, the relationships between format-state flags and manipulators, or between format-state parameters and manipulators. The last column in each table indicates whether a given manipulator (and any associated flag or parameter) applies to input streams only, to output streams only, or to both input and output streams.
Because we have two distinct ways of setting both format-state flags and format-state parameters, the obvious question of when to use which method arises. The key thing to keep in mind when answering this question is this: The member functions all return the current state of whatever you happen to be setting, if you are using the version of one of these functions that takes one or more parameters. The manipulators, on the other hand, do not return the current state. So, if you wish to retain the current state for any reason (to reset the stream to that original state later, for example), then use one or more member functions to set the state; otherwise, it doesn't matter.
|Manipulators without Parameters|
|left||ios::left||Turn the flag on||output|
|right||ios::right||Turn the flag on||output|
|internal||ios::internal||Turn the flag on||output|
|dec||ios::dec||Turns flag on||output|
|oct||ios::oct||Turn the flag on||input/output|
|hex||ios::hex||Turn the flag on||input/output|
|fixed||ios::fixed||Turns the flag on||output|
|scientific||ios::scientific||Turn the flag on||output|
|ios::showbase||Turn the flag on/off||output|
|ios::showpoint||Turn the flag on/off||output|
|ios::showpos||Turn the flag on/off||output|
|ios::uppercase||Turn the flag on/off||output|
|ios::boolalpha||Turns flag on/off||input/output|
|ios::skipws||Turn the flag on/off||input|
|ios::unitbuf||Turn the flag on/off||output|
|endl||N/A||Output a newline character
and flush the stream
|ends||N/A||Output a null||output|
|flush||N/A||Flush the stream||output|
|ws||N/A||Skip leading whitespace||input|
See this part of the Standard Library Reference on this site for additional details on manipulators without parameters.
|Manipulators with Parameters|
|Set the number base to int_radix_value (10, 8 or 16)||input/output|
|As specified by fmtflags_value||Turn the flags specified in fmtflags_value on/off||input/output|
|setfill(int_char_code)||fill character||Set the fill character to the character whose code is specified by int_char_code||output|
|setprecision(int_num_digits)||precision||Set the number of digits of precision to int_num_digits||output|
|setw(int_width)||width||Set the fieldwidth in the output to int_width, which must be >= 0; for input of strings, the maximum number of characters read in will be one less than int_width (ensures that the input will fit into a char array whose size is given by int_width)||input/output|
See this part of the Standard Library Reference on this site for additional details on manipulators with parameters.
Although the "Standard I/O objects" (cin, cout, cerr and clog) are very convenient for some purposes, such as for I/O in testing and pedagogical situations and reporting errors to the console, in the real world C++ programs spend much more time dealing with data that comes from other sources, and is sent to other destinations, such as files on disk.
Files fall into two major categories—textfiles and binary files—whose differences are summarized in the following table.
|Comparison of Textfiles and Binary Files|
|Easy for humans to read||Impossible for humans to read|
|Easy to modify||Harder to modify|
|Easy to transfer||Harder to transfer|
|Slower access||Faster access|
|Less accurate (subject to
conversion and roundoff errors)
|Data stored exactly|
|Less compact storage||More compact storage|
An expanded form of the UML class diagram given previously is show below, and illustrates the additional classes that are needed to deal with files. Those classes above the horizontal line are generally available by including <iostream>, and those below the line by including <fstream>, but be reminded once again that it's a good idea to include explicitly the header containing any class (or other entity) that you wish to use.
Before a program can gain access to a physical file for input or output, a "stream object" must be created and connected to the designated physical file. This can be done in essentially two ways: by the constructor when the stream object (stream variable, if you like) is declared, or later by calling an "open" member function with the stream object as target.
Also, files may be "opened" in various "modes", which are summarized in the following table.
|File Stream Modes (Values of Type openmode)|
|ios::in||Open in input (read) mode|
|ios::out||Open in output (write) mode|
|ios::app||Open in append mode|
|ios::ate||Go to end of file when opened|
|ios::binary||Open in binary mode (default is text mode)|
|ios::trunc||If file exists, delete file contents|
You may also occasionally encounter the non-standard modes ios::nocreate (if file does not exist, open for output will fail) and/or ios::noreplace (if file exists, open for output will fail), but these should not be used in new code that attempts to be standard-compliant.
Some notes to keep in mind about the contents of the above table:
fstreamis opened by default in input/output mode (ios::in | ios::out), i.e., capable of being both read from and written to.
When a program attempts to read input data from a stream, many things can go wrong. For example, the physical source that the program is looking for may not even exist, or may be inaccessible for some reason. Or, during the course of reading the input, values that are malformed in some way may be encountered, there may be fewer values than expected, and so on. It is therefore necessary to have some means of dealing with the various errors that may arise.
Also, streams may be in various "states", which are summarized in the following table.
|Stream States (Values of Type iostate)|
|ios::goodbit||No problems with the stream|
|ios::failbit||Failure to read or write expected characters|
|ios::eofbit||End-of-file encountered when reading|
In C++ a stream variable is often examined as a boolean quantity. If is is "true" (non-zero) the stream may be assumed to be in a "good" state (nothing untoward has happened), while if it is "false" (zero or null), something "not so good" has happened and appropriate action should be taken. This simple approach is often used when attempting to open a file, usually for input, to test for existence, and when reading input.
For more detailed handling of errors, class ios provides the four functions shown below for testing the error state of a stream. Each of these functions returns true (non-zero) if the corresponding error condition holds, and false (zero) otherwise.
Some notes on these functions:
By default, files are read from, and written to, sequentially. It is possible, however, to move directly to any valid "file position" within a file and start reading (or writing, as the case may be, depending on the mode used to open the file) at that point in the file. Although it is possible to read and write at "random" locations in textfiles, binary files are more likely candidates for this kind of program activity.
One or more of the three types shown next will be required for working with the functions shown below. Details on the functions themselves are available by following the associated links.
|Seek Origin for Seek Direction (Values of Type seekdir)|
|ios::beg||Relative to beginning of stream (positive offset is absolute position)|
|ios::cur||Relative to current stream position (negative offset toward beginning of stream, positive offset toward end of stream)|
|ios::end||Relative to end of stream (negative offset toward begining of stream)|
The following functions are the ones you would use for direct reading from a file (random file access for reading):
The following functions are the ones you would use for direct writing to a file (random file access for writing):
fstream class is capable of both reading and
writing a file alternately after the file has been opened simultaneously
in both modes, care must be taken. In particular, note that it is not
possible to switch between reading and writing arbitrarily. Once a read
or write has taken place, the only way to switch between the two is to
perform a seek operation. And if you don't actually want to move the file
pointer, you can always seek to the current position, like this:
f.seekg(f.tellg(), ios::beg); //Seek to current file position
Failure to do this can result in unexplained or even bizarre behavior during subsequent actions on the file.