C++ I/O occurs in streams, which are sequences of bytes. In input operations, the bytes flow from a device (e.g., a keyboard, a disk drive, a network connection) to main memory. In output operations, bytes flow from main memory to a device (e.g., a display screen, a printer, a disk drive, a network connection).
An application associates meaning with bytes. The bytes could represent characters, raw data, graphics images, digital speech, digital music, digital video or any other information an application may require. The system I/O mechanisms should transfer bytes from devices to memory (and vice versa) reliably. The time these transfers take typically is far greater than the time the processor requires to manipulate data internally. I/O operations require careful planning and tuning to ensure optimal performance.
C++ provides both “low-level” and “high-level” I/O capabilities. Low-level I/O capabilities (i.e., unformatted I/O) specify that some number of bytes should be transferred device-to-memory or memory-to-device. In such transfers, the individual byte is the item of interest. Such low-level capabilities provide high-speed, high-volume transfers but are not particularly convenient.
Programmers generally prefer a higher-level view of I/O (i.e., formatted I/O), in which bytes are grouped into meaningful units, such as integers, floating-point numbers, characters, strings and user-defined types. These type-oriented capabilities are satisfactory for most I/O other than high-volume file processing.
In the past, the C++ classic stream libraries supported only char
-based I/O. Because a char
normally occupies one byte, it can represent only a limited set of characters (such as those in the ASCII character set used by most readers of this book, or other popular character sets). Many languages use alphabets that contain more characters than a single-byte char
can represent. The ASCII character set does not provide these characters, but the Unicode® character set does. Unicode is an extensive international character set that represents the majority of the world’s languages, mathematical symbols and much more. C++ provides Unicode support via the types wchar_t
(the original C++ type for processing Unicode) and C++11 types char16_t
and char32_t
. In addition, the standard stream libraries are implemented as class templates—like classes array
and vector
that you saw in Chapter 7. These class templates can be specialized for the various character types—we use the predefined stream-library specializations for type char
in this book. For more information on Unicode, visit http:/
.
iostream
Library HeadersThe C++ stream libraries provide hundreds of I/O capabilities. Most of our C++ programs include the <iostream>
header, which declares basic services required for all stream-I/O operations. The <iostream>
header defines the cin
, cout
, cerr
and clog
objects, which correspond to the standard input stream, the standard output stream, the unbuffered standard error stream and the buffered standard error stream, respectively—cerr
, clog
and buffering are discussed in the next section. Both unformatted- and formatted-I/O services are provided. As you know, the <iomanip>
header declares the parameterized stream manipulators— such as setprecision
(Section 4.10.5) and setw
(Section 5.6)—for formatted I/O.
The iostream
library provides many class templates for performing common I/O operations. This chapter focuses on the following class templates:
basic_istream
for stream input operations
basic_ostream
for stream output operations
Though we do not use it in this chapter, class basic_iostream
provides both stream input and stream output operations.
In Chapter 7, you specialized the class templates array
and vector
for use with specific types—for example, you used array<int>
to create an array
class-template specialization for an array
that stores int
values. For each of the class templates basic_istream
, basic_ostream
and basic_iostream
, the iostream
library defines a specialization that performs char
-based I/O.1 The library also defines convenient short names (i.e., aliases) for these specializations:
istream
is a basic_istream<char>
that enables char
input—this is cin
’s type.
ostream
is a basic_ostream<char>
that enables char
output—this is the type of cout
, cerr
and clog
.
iostream
is a basic_iostream<char>
that enables both char
input and output.
We used the aliases istream
and ostream
in Chapter 10 when we overloaded the stream extraction and stream insertion operators.
iostream
Library Aliases Are Defined with typedef
The iostream
library defines each alias with the typedef
specifier, which you’ll sometimes use to create more readable type names. For example, the following statement defines the alias CardPtr
as a synonym for type Card*
:
typedef Card* CardPtr;
Section 22.3 discusses typedef
in detail.
cin, cout, cerr
and clog
Predefined object cin
is an istream
object and is said to be “connected to” (or attached to) the standard input device, which usually is the keyboard. The stream extraction operator (>>
) as used in
int grade;
cin >> grade; // data "flows" in the direction of the arrows
causes a value for int
variable grade
to be input from cin
to memory. The compiler selects the appropriate overloaded stream extraction operator, based on the type of the variable grade
. The >>
operator is overloaded to input data items of fundamental types, strings and pointer values.
The predefined object cout
is an ostream
object and is said to be “connected to” the standard output device, which usually is the display screen. The stream insertion operator (<<
), as used in the following statement, causes the value of variable grade
to be output from memory to the standard output device:
cout << grade; // data "flows" in the direction of the arrows
The compiler determines the data type of grade
(assuming grade
has been declared properly) and selects the appropriate stream insertion operator. The <<
operator is overloaded to output data items of fundamental types, strings and pointer values.
The predefined object cerr
is an ostream
object and is said to be “connected to” the standard error device, normally the screen. Outputs to object cerr
are unbuffered, meaning that each stream insertion to cerr
causes its output to appear immediately—this is appropriate for notifying a user promptly about errors.
The predefined object clog
is an object of the ostream
class and is said to be “connected to” the standard error device. Outputs to clog
are buffered. This means that each insertion to clog
could cause its output to be held in a buffer (that is, an area in memory) until the buffer is filled or until the buffer is flushed. Buffering is an I/O performance-enhancement technique discussed in operating-systems courses.