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:
std::cout << "result: " << x << '\n';
Input is done through another shift operator operator>>(), often referred to as the extractor:
std::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 C++ Standard 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 preferable to C stdio (see Chapter 27).
It is possible to print several units in one expression. For example:
std::cout << "result: " << x;
is equivalent to:
std::operator<<(std::cout,"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. (The shift operators for the character types, such as char and wchar_t, are an exception to this rule; they are namespace-scope functions in the C++ Standard Library namespace ::std.) These operators 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; }
The notable exceptions are extractors and inserters for character types and pointers to such, which are defined as non-members.
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 the standard 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
Localization through a stream's locale
The stream's format state is the main means of format control, as we demonstrate in the next section.