cout
The ostream
insertion operators convert values to text form. By default, they format values as follows:
• A type char
value, if it represents a printable character, is displayed as a character in a field one character wide.
• Numeric integer types are displayed as decimal integers in a field just wide enough to hold the number and, if present, a minus sign.
• Strings are displayed in a field equal in width to the length of the string.
The default behavior for floating-point types has changed. The following are the differences between ancient and current C++ implementations:
• New style— Floating-point types are displayed with a total of six digits, except that trailing zeros aren’t displayed. (Note that the number of digits displayed has no connection with the precision to which the number is stored.) The number is displayed in fixed-point notation or else in E notation (see Chapter 3, “Dealing with Data”), depending on the value of the number. In particular, E notation is used if the exponent is 6 or larger or -5 or smaller. Again, the field is just wide enough to hold the number and, if present, a minus sign. The default behavior corresponds to using the standard C library function fprintf()
with a %g
specifier.
• Old style— Floating-point types are displayed with six places to the right of the decimal, except that trailing zeros aren’t displayed. (Note that the number of digits displayed has no connection with the precision to which the number is stored.) The number is displayed in fixed-point notation or else in E notation (see Chapter 3), depending on the value of the number. Again, the field is just wide enough to hold the number and, if present, a minus sign.
Because each value is displayed in a width equal to its size, you have to provide spaces between values explicitly; otherwise, consecutive values would run together.
Listing 17.2 illustrates the output defaults. It displays a colon (:
) after each value so you can see the width of the field used in each case. The program uses the expression 1.0 / 9.0
to generate a nonterminating fraction so you can see how many places get printed.
Not all compilers generate output formatted in accordance with the current C++ Standard. Also the current standard does allow for regional variations. For example, a European implementation can follow the continental fashion of using a comma instead of a period for displaying decimal fractions. That is, it may write 2,54
instead of 2.54
. The locale library (header file locale
) provides a mechanism for imbuing an input or output stream with a particular style, so a single compiler can offer more than one locale choice. This chapter uses the U.S. locale.
// defaults.cpp -- cout default formats
#include <iostream>
int main()
{
using std::cout;
cout << "12345678901234567890
";
char ch = 'K';
int t = 273;
cout << ch << ":
";
cout << t << ":
";
cout << -t <<":
";
double f1 = 1.200;
cout << f1 << ":
";
cout << (f1 + 1.0 / 9.0) << ":
";
double f2 = 1.67E2;
cout << f2 << ":
";
f2 += 1.0 / 9.0;
cout << f2 << ":
";
cout << (f2 * 1.0e4) << ":
";
double f3 = 2.3e-4;
cout << f3 << ":
";
cout << f3 / 10 << ":
";
return 0;
}
Here is the output of the program in Listing 17.2:
12345678901234567890
K:
273:
-273:
1.2:
1.31111:
167:
167.111:
1.67111e+006:
0.00023:
2.3e-005:
Each value fills its field. Note that the trailing zeros of 1.200 are not displayed but that floating-point values without terminating zeros have six places displayed. Also this particular implementation displays three digits in the exponent; others might use two.
The ostream
class inherits from the ios
class, which inherits from the ios_base
class. The ios_base
class stores information that describes the format state. For example, certain bits in one class member determine the number base used, whereas another member determines the field width. By using manipulators, you can control the number base used to display integers. By using ios_base
member functions, you can control the field width and the number of places displayed to the right of the decimal. Because the ios_base
class is an indirect base class for ostream
, you can use its methods with ostream
objects (or descendants), such as cout
.
The members and methods found in the ios_base
class were formerly found in the ios
class. Now ios_base
is a base class to ios
. In the new system, ios
is a template class with char
and wchar_t
specializations, and ios_base
contains the nontemplate features.
Let’s look at how to set the number base to be used in displaying integers. To control whether integers are displayed in base 10, base 16, or base 8, you can use the dec
, hex
, and oct
manipulators. For example, the following function call sets the number base format state for the cout
object to hexadecimal:
hex(cout);
After you do this, a program will print integer values in hexadecimal form until you set the format state to another choice. Note that the manipulators are not member functions, hence they don’t have to be invoked by an object.
Although the manipulators really are functions, you normally see them used this way:
cout << hex;
The ostream
class overloads the <<
operator to make this usage equivalent to the function call hex(cout)
. The manipulators are in the std
namespace. Listing 17.3 illustrates using these manipulators. It shows the value of an integer and its square in three different number bases. Note that you can use a manipulator separately or as part of a series of insertions.
// manip.cpp -- using format manipulators
#include <iostream>
int main()
{
using namespace std;
cout << "Enter an integer: ";
int n;
cin >> n;
cout << "n n*n
";
cout << n << " " << n * n << " (decimal)
";
// set to hex mode
cout << hex;
cout << n << " ";
cout << n * n << " (hexadecimal)
";
// set to octal mode
cout << oct << n << " " << n * n << " (octal)
";
// alternative way to call a manipulator
dec(cout);
cout << n << " " << n * n << " (decimal)
";
return 0;
}
Here is some sample output from the program in Listing 17.3:
Enter an integer: 13
n n*n
13 169 (decimal)
d a9 (hexadecimal)
15 251 (octal)
13 169 (decimal)
You probably noticed that the columns in output from Listing 17.3 don’t line up; that’s because the numbers have different field widths. You can use the width
member function to place differently sized numbers in fields that have equal widths. The method has these prototypes:
int width();
int width(int i);
The first form returns the current setting for field width. The second sets the field width to i
spaces and returns the previous field width value. This allows you to save the previous value in case you want to restore the width to that value later.
The width()
method affects only the next item displayed, and the field width reverts to the default value afterward. For example, consider the following statements:
cout << '#';
cout.width(12);
cout << 12 << "#" << 24 << "#
";
Because width()
is a member function, you have to use an object (cout
, in this case) to invoke it. The output statement produces the following display:
# 12#24#
The 12
is placed in a field 12 characters wide at the right end of the field. This is called right-justification. After that, the field width reverts to the default, and the two #
characters and the 24
are printed in fields equal to their own size.
The width()
method affects only the next item displayed, and the field width reverts to the default value afterward.
C++ never truncates data, so if you attempt to print a seven-digit value in a field with a width of two, C++ expands the field to fit the data. (Some languages just fill the field with asterisks if the data doesn’t fit. The C/C++ philosophy is that showing all the data is more important than keeping the columns neat; C++ puts substance before form.) Listing 17.4 shows how the width()
member function works.
// width.cpp -- using the width method
#include <iostream>
int main()
{
using std::cout;
int w = cout.width(30);
cout << "default field width = " << w << ":
";
cout.width(5);
cout << "N" <<':';
cout.width(8);
cout << "N * N" << ":
";
for (long i = 1; i <= 100; i *= 10)
{
cout.width(5);
cout << i <<':';
cout.width(8);
cout << i * i << ":
";
}
return 0;
}
Here is the output of the program in Listing 17.4:
default field width = 0:
N: N * N:
1: 1:
10: 100:
100: 10000:
The output displays values right-justified in their fields. The output is padded with spaces. That is, cout
achieves the full field width by adding spaces. With right-justification, the spaces are inserted to the left of the values. The character used for padding is termed the fill character. Right-justification is the default.
Note that the program in Listing 17.4 applies the field width of 30 to the string displayed by the first cout
statement but not to the value of w
. This is because the width()
method affects only the next single item displayed. Also note that w
has the value 0
. This is because cout.width(30)
returns the previous field width, not the width to which it was just set. The fact that w
is 0
means that zero is the default field width. Because C++ always expands a field to fit the data, this one size fits all. Finally, the program uses width()
to align column headings and data by using a width of five characters for the first column and a width of eight characters for the second column.
By default, cout
fills unused parts of a field with spaces. You can use the fill()
member function to change that. For example, the following call changes the fill character to an asterisk:
cout.fill('*'),
That can be handy for, say, printing checks so that recipients can’t easily add a digit or two. Listing 17.5 illustrates using this member function.
// fill.cpp -- changing fill character for fields
#include <iostream>
int main()
{
using std::cout;
cout.fill('*'),
const char * staff[2] = { "Waldo Whipsnade", "Wilmarie Wooper"};
long bonus[2] = {900, 1350};
for (int i = 0; i < 2; i++)
{
cout << staff[i] << ": $";
cout.width(7);
cout << bonus[i] << "
";
}
return 0;
}
Here’s the output of the program in Listing 17.5:
Waldo Whipsnade: $****900
Wilmarie Wooper: $***1350
Note that, unlike the field width, the new fill character stays in effect until you change it.
The meaning of floating-point precision depends on the output mode. In the default mode, it means the total number of digits displayed. In the fixed and scientific modes, to be discussed soon, precision means the number of digits displayed to the right of the decimal place. The precision default for C++, as you’ve seen, is 6
. (Recall, however, that trailing zeros are dropped.) The precision()
member function lets you select other values. For example, the following statement causes cout
to set the precision to 2
:
cout.precision(2);
Unlike the case with width()
, but like the case for fill()
, a new precision setting stays in effect until it is reset. Listing 17.6 demonstrates precisely this point.
// precise.cpp -- setting the precision
#include <iostream>
int main()
{
using std::cout;
float price1 = 20.40;
float price2 = 1.9 + 8.0 / 9.0;
cout << ""Furry Friends" is $" << price1 << "!
";
cout << ""Fiery Fiends" is $" << price2 << "!
";
cout.precision(2);
cout << ""Furry Friends" is $" << price1 << "!
";
cout << ""Fiery Fiends" is $" << price2 << "!
";
return 0;
}
Here is the output of the program in Listing 17.6:
"Furry Friends" is $20.4!
"Fiery Fiends" is $2.78889!
"Furry Friends" is $20!
"Fiery Fiends" is $2.8!
Note that the third line of this output doesn’t include a trailing decimal point. Also the fourth line displays a total of two digits.
Certain forms of output, such as prices or numbers in columns, look better if trailing zeros are retained. For example, the output to Listing 17.6 would look better as $20.40 than as $20.4. The iostream
family of classes doesn’t provide a function whose sole purpose is to accomplish that. However, the ios_base
class provides a setf()
(for set flag) function that controls several formatting features. The class also defines several constants that can be used as arguments to this function. For example, the following function call causes cout
to display trailing decimal points:
cout.setf(ios_base::showpoint);
In the default floating-point format, it also causes trailing zeros to be displayed. That is, instead of displaying 2.00
as 2
, cout
will display it as 2.00000
if the default precision of 6 is in effect. Listing 17.7 adds this statement to Listing 17.6.
In case you’re wondering about the notation ios_base::showpoint
, showpoint
is a class-scope static constant that is defined in the ios_base
class declaration. Class scope means that you have to use the scope-resolution operator (::
) with the constant name if you use the name outside a member function definition. So ios_base::showpoint
names a constant defined in the ios_base
class.
// showpt.cpp -- setting the precision, showing trailing point
#include <iostream>
int main()
{
using std::cout;
using std::ios_base;
float price1 = 20.40;
float price2 = 1.9 + 8.0 / 9.0;
cout.setf(ios_base::showpoint);
cout << ""Furry Friends" is $" << price1 << "!
";
cout << ""Fiery Fiends" is $" << price2 << "!
";
cout.precision(2);
cout << ""Furry Friends" is $" << price1 << "!
";
cout << ""Fiery Fiends" is $" << price2 << "!
";
return 0;
}
Here is the output of the program in Listing 17.7, using the current C++ formatting:
"Furry Friends" is $20.4000!
"Fiery Fiends" is $2.78889!
"Furry Friends" is $20.!
"Fiery Fiends" is $2.8!
This output shows the trailing zeros for the first line. The third line shows the decimal point but no trailing zeros because the precision has been set to 2
and two digits already have been displayed.
setf()
The setf()
method controls several other formatting choices besides when the decimal point is displayed, so let’s take a closer look at it. The ios_base
class has a protected data member in which individual bits (called flags in this context) control different formatting aspects, such as the number base and whether trailing zeros are displayed. Turning a flag on is called setting the flag (or bit) and means setting the bit to 1
. (Bit flags are the programming equivalent to setting DIP switches to configure computer hardware.) The hex
, dec
, and oct
manipulators, for example, adjust the three flag bits that control the number base. The setf()
function provides another means of adjusting flag bits.
The setf()
function has two prototypes. The first is this:
fmtflags setf(fmtflags);
Here fmtflags
is a typedef
name for a bitmask type (see the following Note) used to hold the format flags. The name is defined in the ios_base
class. This version of setf()
is used for setting format information controlled by a single bit. The argument is a fmtflags
value that indicates which bit to set. The return value is a type fmtflags
number that indicates the former settings of all the flags. You can then save that value if you later want to restore the original settings. What value do you pass to setf()
? If you want to set bit number 11 to 1
, you pass a number that has its number 11 bit set to 1
. The return value would have its number 11 bit assigned the prior value for that bit. Keeping track of bits sounds (and is) tedious. However, you don’t have to do that job; the ios_base
class defines constants that represent the bit values. Table 17.1 shows some of these definitions.
A bitmask type is a type that is used to store individual bit values. It could be an integer type, an enum
, or an STL bitset
container. The main idea is that each bit is individually accessible and has its own meaning. The iostream
package uses bitmask types to store state information.
Because these formatting constants are defined within the ios_base
class, you must use the scope-resolution operator with them. That is, you must use ios_base::uppercase
, not just uppercase
. If you don’t use a using
directive or using
declaration, you can use the scope-resolution operator to indicate that these names are in the std
namespace. That is, you can use std::ios_base::showpos
, and so on. Changes remain in effect until they are overridden. Listing 17.8 illustrates using some of these constants.
// setf.cpp -- using setf() to control formatting
#include <iostream>
int main()
{
using std::cout;
using std::endl;
using std::ios_base;
int temperature = 63;
cout << "Today's water temperature: ";
cout.setf(ios_base::showpos); // show plus sign
cout << temperature << endl;
cout << "For our programming friends, that's
";
cout << std::hex << temperature << endl; // use hex
cout.setf(ios_base::uppercase); // use uppercase in hex
cout.setf(ios_base::showbase); // use 0X prefix for hex
cout << "or
";
cout << temperature << endl;
cout << "How " << true << "! oops -- How ";
cout.setf(ios_base::boolalpha);
cout << true << "!
";
return 0;
}
Here is the output of the program in Listing 17.8:
Today's water temperature: +63
For our programming friends, that's
3f
or
0X3F
How 0X1! oops -- How true!
Note that the plus sign is used only with the base 10 version. C++ treats hexadecimal and octal values as unsigned; therefore no sign is needed for them. (However, some C++ implementations may still display a plus sign.)
The second setf()
prototype takes two arguments and returns the prior setting:
fmtflags setf(fmtflags , fmtflags );
This overloaded form of the function is used for format choices controlled by more than 1 bit. The first argument, as before, is a fmtflags
value that contains the desired setting. The second argument is a value that first clears the appropriate bits. For example, suppose setting bit 3 to 1
means base 10, setting bit 4 to 1
means base 8, and setting bit 5 to 1
means base 16. Suppose output is in base 10, and you want to set it to base 16. Not only do you have to set bit 5 to 1
, you also have to set bit 3 to 0
; this is called clearing the bit. The clever hex
manipulator does both tasks automatically. Using the setf()
function requires a bit more work because you use the second argument to indicate which bits to clear and then use the first argument to indicate which bit to set. This is not as complicated as it sounds because the ios_base
class defines constants (shown in Table 17.2) for this purpose. In particular, you should use the constant ios_base::basefield
as the second argument and ios_base::hex
as the first argument if you’re changing bases. That is, the following function call has the same effect as using the hex
manipulator:
cout.setf(ios_base::hex, ios_base::basefield);
The ios_base
class defines three sets of formatting flags that can be handled this way. Each set consists of one constant to be used as the second argument and two to three constants to be used as a first argument. The second argument clears a batch of related bits; then the first argument sets one of those bits to 1
. Table 17.2 shows the names of the constants used for the second setf()
argument, the associated choice of constants for the first argument, and their meanings. For example, to select left-justification, you use ios_base::adjustfield
for the second argument and ios_base::left
as the first argument. Left-justification means starting a value at the left end of the field, and right-justification means ending a value at the right end of the field. Internal justification means placing any signs or base prefixes at the left of the field and the rest of the number at the right of the field. (Unfortunately, C++ does not provide a self-justification mode.)
Fixed-point notation means using the 123.4 style for floating-point values, regardless of the size of the number, and scientific notation means using the 1.23e04 style, regardless of the size of the number. If you are familiar with C’s printf()
specifiers, it may help you to know that the default C++ mode corresponds to the %g
specifier, fixed
corresponds to the %f
specifier, and scientific
corresponds to the %e
specifier.
Under the C++ Standard, both fixed and scientific notation have the following two properties:
• Precision means the number of digits to the right of the decimal rather than the total number of digits.
• Trailing zeros are displayed.
The setf()
function is a member function of the ios_base
class. Because that’s a base class for the ostream
class, you can invoke the function by using the cout
object. For example, to request left-justification, you use this call:
ios_base::fmtflags old = cout.setf(ios::left, ios::adjustfield);
To restore the previous setting, you use this:
cout.setf(old, ios::adjustfield);
Listing 17.9 illustrates further examples of using setf()
with two arguments.
The program in Listing 17.9 uses a math function, and some C++ systems don’t automatically search the math library. For example, some Unix systems require that you use the following:
$ CC setf2.C -lm
The -lm
option instructs the linker to search the math library. Similarly, some Linux systems using g++ require the same flag.
// setf2.cpp -- using setf() with 2 arguments to control formatting
#include <iostream>
#include <cmath>
int main()
{
using namespace std;
// use left justification, show the plus sign, show trailing
// zeros, with a precision of 3
cout.setf(ios_base::left, ios_base::adjustfield);
cout.setf(ios_base::showpos);
cout.setf(ios_base::showpoint);
cout.precision(3);
// use e-notation and save old format setting
ios_base::fmtflags old = cout.setf(ios_base::scientific,
ios_base::floatfield);
cout << "Left Justification:
";
long n;
for (n = 1; n <= 41; n+= 10)
{
cout.width(4);
cout << n << "|";
cout.width(12);
cout << sqrt(double(n)) << "|
";
}
// change to internal justification
cout.setf(ios_base::internal, ios_base::adjustfield);
// restore default floating-point display style
cout.setf(old, ios_base::floatfield);
cout << "Internal Justification:
";
for (n = 1; n <= 41; n+= 10)
{
cout.width(4);
cout << n << "|";
cout.width(12);
cout << sqrt(double(n)) << "|
";
}
// use right justification, fixed notation
cout.setf(ios_base::right, ios_base::adjustfield);
cout.setf(ios_base::fixed, ios_base::floatfield);
cout << "Right Justification:
";
for (n = 1; n <= 41; n+= 10)
{
cout.width(4);
cout << n << "|";
cout.width(12);
cout << sqrt(double(n)) << "|
";
}
return 0;
}
Here is the output of the program in Listing 17.9:
Left Justification:
+1 |+1.000e+00 |
+11 |+3.317e+00 |
+21 |+4.583e+00 |
+31 |+5.568e+00 |
+41 |+6.403e+00 |
Internal Justification:
+ 1|+ 1.00|
+ 11|+ 3.32|
+ 21|+ 4.58|
+ 31|+ 5.57|
+ 41|+ 6.40|
Right Justification:
+1| +1.000|
+11| +3.317|
+21| +4.583|
+31| +5.568|
+41| +6.403|
Note how a precision of 3 causes the default floating-point display (used for internal justification in this program) to display a total of three digits, while the fixed and scientific modes display three digits to the right of the decimal. (The number of digits displayed in the exponent for e-notation depends on the implementation.)
The effects of calling setf()
can be undone with unsetf()
, which has the following prototype:
void unsetf(fmtflags mask);
Here mask
is a bit pattern. All bits set to 1
in mask
cause the corresponding bits to be unset. That is, setf()
sets bits to 1
, and unsetf()
sets bits back to 0
. Here’s an example:
cout.setf(ios_base::showpoint); // show trailing decimal point
cout.unsetf(ios_base::boolshowpoint); // don't show trailing decimal point
cout.setf(ios_base::boolalpha); // display true, false
cout.unsetf(ios_base::boolalpha); // display 1, 0
You may have noticed that there is no special flag to indicate the default mode for displaying floating-point numbers. Here’s how the system works. Fixed notation is used if the fixed bit, and only the fixed bit is set. Scientific notation is used if the scientific bit and only the scientific bit is set. Any other combination, such as no bits set or both bits set, results in the default mode being used. So one way to invoke the default mode is this:
cout.setf(0, ios_base::floatfield); // go to default mode
The second argument turns both bits off, and the first argument doesn’t set any bits. A shorter way to accomplish the same end is to use unsetf() with ios_base::floatfield
:
cout.unsetf(ios_base::floatfield); // go to default mode
If you knew for certain that cout
were in the fixed state, you could use ios_base::fixed
as an argument to unsetf()
, but using ios_base::floatfield
works, regardless of the current state of cout
, so it’s a better choice.
Using setf()
is not the most user-friendly approach to formatting, so C++ offers several manipulators to invoke setf()
for you, automatically supplying the right arguments. You’ve already seen dec
, hex
, and oct
. These manipulators, most of which are not available to older C++ implementations, work like hex
. For example, the following statement turns on left-justification and the fixed decimal point option:
cout << left << fixed;
Table 17.3 lists these along with several other manipulatrs.
If your system supports these manipulators, take advantage of them; if it doesn’t, you still have the option of using setf()
.
iomanip
Header FileSetting some format values, such as the field width, can be awkward using the iostream
tools. To make life easier, C++ supplies additional manipulators in the iomanip
header file. They provide the same services already discussed, but in a notationally more convenient manner. The three most commonly used are setprecision()
for setting the precision, setfill()
for setting the fill character, and setw()
for setting the field width. Unlike the manipulators discussed previously, these take arguments. The setprecision()
manipulator takes an integer argument that specifies the precision, the setfill()
manipulator takes a char
argument that indicates the fill character, and the setw()
manipulator takes an integer argument that specifies the field width. Because they are manipulators, they can be concatenated in a cout
statement. This makes the setw()
manipulator particularly convenient when you’re displaying several columns of values. Listing 17.10 illustrates this by changing the field width and fill character several times for one output line. It also uses some of the newer standard manipulators.
Some C++ systems don’t automatically search the math library. As mentioned before, some Unix systems require that you use the following to access the math library:
$ CC iomanip.C -lm
// iomanip.cpp -- using manipulators from iomanip
// some systems require explicitly linking the math library
#include <iostream>
#include <iomanip>
#include <cmath>
int main()
{
using namespace std;
// use new standard manipulators
cout << fixed << right;
// use iomanip manipulators
cout << setw(6) << "N" << setw(14) << "square root"
<< setw(15) << "fourth root
";
double root;
for (int n = 10; n <=100; n += 10)
{
root = sqrt(double(n));
cout << setw(6) << setfill('.') << n << setfill(' ')
<< setw(12) << setprecision(3) << root
<< setw(14) << setprecision(4) << sqrt(root)
<< endl;
}
return 0;
}
Here is the output of the program in Listing 17.10:
N square root fourth root
....10 3.162 1.7783
....20 4.472 2.1147
....30 5.477 2.3403
....40 6.325 2.5149
....50 7.071 2.6591
....60 7.746 2.7832
....70 8.367 2.8925
....80 8.944 2.9907
....90 9.487 3.0801
...100 10.000 3.1623
Now you can produce neatly aligned columns. Using the fixed
manipulator causes trailing zeros to be displayed.
cin
Now it’s time to turn to input and getting data into a program. The cin
object represents the standard input as a stream of bytes. Normally, you generate that stream of characters at the keyboard. If you type the character sequence 2011
, the cin
object extracts those characters from the input stream. You may intend that input to be part of a string, to be an int
value, to be a float
value, or to be some other type. Thus, extraction also involves type conversion. The cin
object, guided by the type of variable designated to receive the value, must use its methods to convert that character sequence into the intended type of value.
Typically, you use cin
as follows:
cin >> value_holder;
Here value_holder
identifies the memory location in which to store the input. It can be the name of a variable, a reference, a dereferenced pointer, or a member of a structure or of a class. How cin
interprets the input depends on the data type for value_holder
. The istream
class, defined in the iostream
header file, overloads the >>
extraction operator to recognize the following basic types:
• signed char &
• unsigned char &
• char &
• short &
• unsigned short &
• int &
• unsigned int &
• long &
• unsigned long &
• long long &
(C++11)
• unsigned long long &
(C++11)
• double &
• long double &
These are referred to as formatted input functions because they convert the input data to the format indicated by the target.
A typical operator function has a prototype like the following:
istream & operator>>(int &);
Both the argument and the return value are references. With a reference argument (see Chapter 8, “Adventures in Functions”), a statement such as the following causes the operator>>()
function to work with the variable staff_size
itself rather than with a copy, as would be the case with a regular argument:
cin >> staff_size;
Because the argument type is a reference, cin
is able to directly modify the value of a variable used as an argument. The preceding statement, for example, directly modifies the value of the staff_size
variable. We’ll get to the significance of a reference return value in a moment. First, let’s examine the type conversion aspect of the extraction operator. For arguments of each type in the preceding list of types, the extraction operator converts the character input to the indicated type of value. For example, suppose staff_size
is type int
. In this case, the compiler matches
cin >> staff_size;
to the following prototype:
istream & operator>>(int &);
The function corresponding to that prototype then reads the stream of characters being sent to the program—say, the characters 2
, 3
, 1
, 8
, and 4
. For a system using a 2-byte int
, the function then converts these characters to the 2-byte binary representation of the integer 23184
. If, on the other hand, staff_size
were type double
, cin
would use operator>>(double &)
to convert the same input into the 8-byte floating-point representation of the value 23184.0
.
Incidentally, you can use the hex
, oct
, and dec
manipulators with cin
to specify that integer input is to be interpreted as hexadecimal, octal, or decimal format. For example, the following statement causes an input of 12
or 0x12
to be read as hexadecimal 12
, or decimal 18
, and it causes ff
or FF
to be read as decimal 255
:
cin >> hex;
The istream
class also overloads the >>
extraction operator for character pointer types:
• signed char
*
• char
*
• unsigned char
*
For this type of argument, the extraction operator reads the next word from input and places it at the indicated address, adding a null character to make a string. For example, suppose you have this code:
cout << "Enter your first name:
";
char name[20];
cin >> name;
If you respond to the request by typing Liz
, the extraction operator places the characters Liz
in the name
array. (As usual,