They’ll never be happy together. He’s not her type.
OVERHEARD AT A COCKTAIL PARTY
int
and double
Conceptually, the numbers 2 and 2.0 are the same number. But C++ considers them to be of different types. The whole number 2
is of type int
; the number 2.0
is of type double
, because it contains a fraction part (even though the fraction is 0
). Once again, the mathematics of computer programming is a bit different from what you may have learned in mathematics classes. Something about the practicalities of computers makes a computer’s numbers differ from the abstract definitions of these numbers. The whole numbers in C++ behave as you would expect them to. The type int
holds no surprises. But values of type double
are more troublesome. Because it can store only a limited number of significant digits, the computer stores numbers of type double
as approximate values. Numbers of type int
are stored as exact values. The precision with which double
values are stored varies from one computer to another, but you can expect them to be stored with 14 or more digits of accuracy. For most applications this is likely to be sufficient, though subtle problems can occur even in simple cases. Thus, if you know that the values in some variable will always be whole numbers in the range allowed by your computer, it is best to declare the variable to be of type int
.
Number constants of type double
are written differently from those of type int
. Constants of type int
must not contain a decimal point. Constants of type double
may be written in either of two forms. The simple form for double
constants is like the everyday way of writing decimal fractions. When written in this form, a double
constant must contain a decimal point. There is, however, one thing that constants of type double
and constants of type int
have in common: No number in C++ may contain a comma.
The more complicated notation for constants of type double
is frequently called scientific notation or floating-point notation and is particularly handy for writing very large numbers and very small fractions. For instance,
3.67 × 1017
which is the same as
367000000000000000.0
is best expressed in C++ by the constant 3.67e17
. The number
5.89 × 10−6
which is the same as
0.00000589
is best expressed in C++ by the constant 5.89e
-6
. The e
stands for exponent and means “multiply by 10 to the power that follows.”
This e
notation is used because keyboards normally have no way to write exponents as superscripts. Think of the number after the e
as telling you the direction and number of digits to move the decimal point. For example, to change 3.49e4
to a numeral without an e
, you move the decimal point four places to the right to obtain 34900.0
, which is another way of writing the same number. If the number after the e
is negative, you move the decimal point the indicated number of spaces to the left, inserting extra zeros if need be. So, 3.49e
-2
is the same as 0.0349
.
The number before the e
may contain a decimal point, although it is not required. However, the exponent after the e
definitely must not contain a decimal point.
Since computers have size limitations on their memory, numbers are typically stored in a limited number of bytes (that is, a limited amount of storage). Hence, there is a limit to how large the magnitude of a number can be, and this limit is different for different number types. The largest allowable number of type double
is always much larger than the largest allowable number of type int
. Most current implementations of C++ will allow values of type int
as large as 2,147,483,647
and values of type double
up to about 10308.
C++ has other numeric types besides int
and double
. Some are described in Display 2.2. The various number types allow for different size numbers and for more or less precision (that is, more or fewer digits after the decimal point). In Display 2.2, the values given for memory used, size range, and precision are only one sample set of values, intended to give you a general feel for how the types differ. The values vary from one system to another and may be different on your system.
Type Name | Memory Used | Size Range | Precision |
---|---|---|---|
short (also called short int) |
2 bytes |
−32,768 to 32,767 |
(not applicable) |
int |
4 bytes |
−2,147,483,648 to 2,147,483,647 |
(not applicable) |
long (also called long int) |
4 bytes |
−2,147,483,648 to 2,147,483,647 |
(not applicable) |
float |
4 bytes |
approximately 10−38 to 1038 |
7 digits |
double |
8 bytes |
approximately 10− 308 to 10 308 |
15 digits |
long double |
10 bytes |
approximately 10− 4932 to 10 4932 |
19 digits |
These are only sample values to give you a general idea of how the types differ. The values for any of these entries may be different on your system. |
Although some of these other numeric types are spelled as two words, you declare variables of these other types just as you declare variables of types int
and double
. For example, the following declares one variable of type long double
:
long double bigNumber;
The type names long
and long int
are two names for the same type. Thus, the following two declarations are equivalent:
long bigTotal;
and the equivalent
long int bigTotal;
Of course, in any one program, you should use only one of the above two declarations for the variable bigTotal
, but it does not matter which one you use. Also, remember that the type name long
by itself means the same thing as long int
, not the same thing as long double
.
The types for whole numbers, such an int
and similar types, are called integer types. The type for numbers with a decimal point—such as the type double
and similar types—are called floating-point types. They are called floating-point because when the computer stores a number written in the usual way, like 392.123
, it first converts the number to something like e
notation, in this case something like 3.92123e2
. When the computer performs this conversion, the decimal point floats (that is, moves) to a new position.
You should be aware that there are other numeric types in C++. However, in this book we will use only the types int
, double
, and occasionally long
. For most simple applications, you should not need any types except int
and double
. However, if you are writing a program that uses very large whole numbers, then you might need to use the type long
.
The size of integer data types can vary from one machine to another. For example, on a 32-bit machine an integer might be 4 bytes while on a 64-bit machine an integer might be 8 bytes. Sometimes this is problematic if you need to know exactly what range of values can be stored in an integer type. To address this problem, new integer types were added to C++11 that specify exactly the size and whether or not the data type is signed or unsigned. These types are accessible by including <cstdint>
. Display 2.3 illustrates some of these number types. In this text we will primarily use the more ambiguous types of int
and long
, but consider the C++11 types if you want to specify an exact size.
Type Name | Memory Used | Size Range |
---|---|---|
int8_t |
1 byte |
−128 to 127 |
uint8_t |
1 byte |
0 to 255 |
int16_t |
2 bytes |
−32,768 to 32,767 |
uint16_t |
2 bytes |
0 to 65,535 |
int32_t |
4 bytes |
−2,147,483,648 to 2,147,483,647 |
uint32_t |
4 bytes |
0 to 4,294,967,295 |
int64_t |
8 bytes |
−9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
uint64_t |
8 bytes |
0 to 18,446,744,073,709,551,615 |
long long |
At least 8 bytes |
C++11 also includes a type named auto
that deduces the type of a variable based on an expression on the right side of the equal sign. For example, the following line of code defines a variable named x
whose data type matches whatever is computed from “expression”:
auto x = expression;
This feature doesn’t buy us much at this point but will save us some long, messy code when we start to work with longer data types that we define ourselves.
In the other direction, C++11 also introduces a way to determine the type of a variable or expression. decltype (expr)
is the declared type of variable or expression expr
and can be used in declarations:
int x = 10;
decltype (x*3.5) y;
This code declares y
to be the same type as x*3.5
. The expression x*3.5
is a double
so y
is declared as a double
.
char
We do not want to give you the impression that computers and C++ are used only for numeric calculations, so we will introduce some nonnumeric types now, though eventually we will see other more complicated nonnumeric types. Values of the type char
, which is short for character, are single symbols such as a letter, digit, or punctuation mark. Values of this type are frequently called characters in books and in conversation, but in a C++ program this type must always be spelled in the abbreviated fashion char
. For example, the variables symbol
and letter
of type char
are declared as follows:
char symbol, letter;
A variable of type char
can hold any single character on the keyboard. So, for example, the variable symbol
could hold an 'A'
or a '+'
or an 'a'
. Note that uppercase and lowercase versions of a letter are considered different characters.
The text in double quotes that are output using cout
are called string
values. For example, the following, which occurs in the program in Display 2.1, is a string:
"Enter the number of candy bars in a package\n"
Be sure to notice that string constants are placed inside of double quotes, while constants of type char
are placed inside of single quotes. The two kinds of quotes mean different things. In particular, 'A'
and "A"
mean different things. 'A'
is a value of type char
and can be stored in a variable of type char
. "A"
is a string of characters. The fact that the string happens to contain only one character does not make "A"
a value of type char
. Also notice that, for both strings and characters, the left and right quotes are the same.
The use of the type char
is illustrated in the program shown in Display 2.4. Notice that the user types a space between the first and second initials. Yet the program skips over the blank and reads the letter B as the second input character. When you use cin
to read input into a variable of type char
, the computer skips over all blanks and line breaks until it gets to the first nonblank character and reads that nonblank character into the variable. It makes no difference whether there are blanks in the input or not. The program in Display 2.4 will give the same output whether the user types in a blank between initials, as shown in the sample dialogue, or the user types in the two initials without a blank, like so:
JB
char
1 #include <iostream>
2 using namespace std;
3 int main( )
4 {
5 char symbol1, symbol2, symbol3;
6 cout << "Enter two initials, without any periods:\n";
7 cin >> symbol1 >> symbol2;
8 cout << "The two initials are:\n";
9 cout << symbol1 << symbol2 << endl;
10 cout << "Once more with a space:\n";
11 symbol3 = ' ';
12 cout << symbol1 << symbol3 << symbol2 << endl;
13 cout << "That's all.";
14 return 0;
15 }
Sample Dialogue
Enter two initials, without any periods:
J B
The two initials are:
JB
Once more with a space:
J B
That's all.
bool
The next type we discuss here is the type bool
. This type was added to the C++ language by the ISO/ANSI (International Standards Organization/American National Standards Organization) committee in 1998. Expressions of type bool
are called Boolean after the English mathematician George Boole (1815–1864), who formulated rules for mathematical logic.
Boolean expressions evaluate to one of the two values, true or false. Boolean expressions are used in branching and looping statements that we study in Section 2.4. We will say more about Boolean expressions and the type bool
in that section.
string
Although C++ lacks a native data type to directly manipulate strings, there is a string
class that may be used to process strings in a manner similar to the data types we have seen thus far. The distinction between a class and a native data type is discussed in Chapter 10. Further details about the string
class are discussed in Chapter 8.
To use the string
class we must first include the string
library:
#include <string>
Your program must also contain the following line of code, normally placed at the start of the file:
using namespace std;
You declare variables of type string
just as you declare variables of types int
or double
. For example, the following declares one variable of type string
and stores the text "Monday"
in it:
string day;
day = "Monday";
You may use cin
and cout
to read data into strings, as shown in Display 2.5. If you place the ‘+’ symbol between two strings, then this operator concate-nates the two strings together to create one longer string. For example, the code:
string day, day1, day2;
day1 = "Monday";
day2 = "Tuesday";
day = day1 + day2;
Results in the concatenated string of:
"MondayTuesday"
Note that a space is not automatically added between the strings. If you wanted a space between the two days, then a space must be added explicitly:
day1 + " " + day2
string
Class 1 #include <iostream>
2 #include <string>
3 using namespace std;
4 int main()
5 {
6 string middleName, petName;
7 string alterEgoName;
8
9 cout << "Enter your middle name and the name of your pet.\n";
10 cin >> middleName;
11 cin >> petName;
12
13 alterEgoName = petName + " " + middleName;
14
15 cout << "The name of your alter ego is ";
16 cout << alterEgoName << "." << endl;
17
18 return 0;
19 }
Sample Dialogue 1
Enter your middle name and the name of your pet.
Parker Pippen
The name of your alter ego is Pippen Parker.
Sample Dialogue 2
Enter your middle name and the name of your pet. Parker Mr. Bojangles The name of your alter ego is Mr. Parker.
When you use cin
to read input into a string
variable, the computer only reads until it encounters a whitespace character. Whitespace characters are all the characters that are displayed as blank spaces on the screen, including the blank or space character, the tab character, and the new-line character '\n'
. This means that you cannot input a string that contains spaces. This may sometimes cause errors, as indicated in Display 2.5, Sample Dialogue 2. In this case, the user intends to enter "Mr. Bojangles"
as the name of the pet, but the string is only read up to "Mr."
since the next character is a space. The "Bojangles"
string is ignored by this program but would be read next if there was another cin
statement. Chapter 8 describes a technique to input a string that may include spaces.
As a general rule, you cannot store a value of one type in a variable of another type. For example, most compilers will object to the following:
int intVariable;
intVariable = 2.99;
The problem is a type mismatch. The constant 2.99
is of type double
and the variable intVariable
is of type int
. Unfortunately, not all compilers will react the same way to the above assignment statement. Some will issue an error message, some will give only a warning message, and some compilers will not object at all. But even if the compiler does allow you to use this assignment, it will probably give intVariable
the int
value 2
, not the value 3
. Since you cannot count on your compiler accepting this assignment, you should not assign a double
value to a variable of type int
.
The same problem arises if you use a variable of type double
instead of the constant 2.99
. Most compilers will also object to the following:
int intVariable;
double doubleVariable;
doubleVariable = 2.00;
intVariable = doubleVariable;
The fact that the value 2.00
“comes out even” makes no difference. The value 2.00
is of type double
, not of type int
. As you will see shortly, you can replace 2.00
with 2
in the preceding assignment to the variable doubleVariable
, but even that is not enough to make the assignment acceptable. The variables intVariable
and doubleVariable
are of different types, and that is the cause of the problem.
Even if the compiler will allow you to mix types in an assignment statement, in most cases you should not. Doing so makes your program less portable, and it can be confusing. For example, if your compiler lets you assign 2.99
to a variable of type int
, the variable will receive the value 2
, rather than 2.99
, which can be confusing since the program seems to say the value will be 2.99
.
There are some special cases where it is permitted to assign a value of one type to a variable of another type. It is acceptable to assign a value of type int
to a variable of type double
. For example, the following is both legal and acceptable style:
double doubleVariable;
doubleVariable = 2;
The above will set the value of the variable named doubleVariable
equal to 2.0
.
Although it is usually a bad idea to do so, you can store an int
value such as 65
in a variable of type char
and you can store a letter such as 'Z'
in a variable of type int
. For many purposes, the C language considers the characters to be small integers; and perhaps unfortunately, C++ inherited this from C. The reason for allowing this is that variables of type char
consume less memory than variables of type int
and so doing arithmetic with variables of type char
can save some memory. However, it is clearer to use the type int
when you are dealing with integers and to use the type char
when you are dealing with characters.
The general rule is that you cannot place a value of one type in a variable of another type—though it may seem that there are more exceptions to the rule than there are cases that follow the rule. Even if the compiler does not enforce this rule very strictly, it is a good rule to follow. Placing data of one type in a variable of another type can cause problems, since the value must be changed to a value of the appropriate type and that value may not be what you would expect.
Values of type bool
can be assigned to variables of an integer type (short
, int
, long
) and integers can be assigned to variables of type bool
. However, it is poor style to do this and you should not use these features. For completeness and to help you read other people’s code, we do give the details: When assigned to a variable of type bool
, any nonzero integer will be stored as the value true
. Zero will be stored as the value false
. When assigning a bool
value to an integer variable, true
will be stored as 1
and false
will be stored as 0
.
In a C++ program, you can combine variables and/or numbers using the arithmetic operators +
for addition, − for subtraction, *
for multiplication, and /
for division. For example, the following assignment statement, which appears in the program in Display 2.1, uses the *
operator to multiply the numbers in two variables. (The result is then placed in the variable on the left-hand side of the equal sign.)
totalWeight = oneWeight * numberOfBars;
All of the arithmetic operators can be used with numbers of type int
, numbers of type double
, and even with one number of each type. However, the type of the value produced and the exact value of the result depends on the types of the numbers being combined. If both operands (that is, both numbers) are of type int
, then the result of combining them with an arithmetic operator is of type int
. If one, or both, of the operands is of type double
, then the result is of type double
. For example, if the variables baseAmount
and increase
are of type int
, then the number produced by the following expression is of type int
:
baseAmount + increase
However, if one or both of the two variables is of type double
, then the result is of type double
. This is also true if you replace the operator +
with any of the operators −, *
, or /
.
The type of the result can be more significant than you might suspect. For example, 7.0/2
has one operand of type double
, namely 7.0
. Hence, the result is the type double
number 3.5
. However, 7/2
has two operands of type int
and so it yields the type int
, which is the result 3
. Even if the result “comes out even,” there is a difference. For example, 6.0/2
has one operand of type double
, namely 6.0
. Hence, the result is the type double
number 3.0
, which is only an approximate quantity. However, 6/2
has two operands of type int
, so it yields the result 3
, which is of type int
and so is an exact quantity. The division operator is the operator that is affected most severely by the type of its arguments.
When used with one or both operands of type double
, the division operator, /
, behaves as you might expect. However, when used with two operands of type int
, the division operator, /
, yields the integer part resulting from division. In other words, integer division discards the part after the decimal point. So, 10/3
is 3
(not 3.3333
), 5/2
is 2
(not 2.5
), and 11/3
is 3
(not 3.6666
). Notice that the number is not rounded; the part after the decimal point is discarded no matter how large it is.
The operator %
can be used with operands of type int
to recover the information lost when you use /
to do division with numbers of type int
. When used with values of type int
, the two operators/
and %
yield the two numbers produced when you perform the long division algorithm you learned in grade school. For example, 17 divided by 5 yields 3 with a remainder of 2. The /
operation yields the number of times one number “goes into” another. The %
operation gives the remainder. For example, the statements
cout << "17 divided by 5 is " << (17/5) << endl;
cout << "with a remainder of " << (17%5) << endl;
yield the following output:
17 divided by 5 is 3
with a remainder of 2
Display 2.6 illustrates how /
and %
work with values of type int
.
When used with negative values of type int
, the result of the operators /
and %
can be different for different implementations of C++. Thus, you should use /
and %
with int
values only when you know that both values are nonnegative.
Any reasonable spacing will do in arithmetic expressions. You can insert spaces before and after operations and parentheses, or you can omit them. Do whatever produces a result that is easy to read.
You can specify the order of operations by inserting parentheses, as illustrated in the following two expressions:
(x + y) * z
x + (y * z)
To evaluate the first expression, the computer first adds x
and y
and then multiplies the result by z
. To evaluate the second expression, it multiplies y
and z
and then adds the result to x
. Although you may be used to using mathematical formulas that contain square brackets and various other forms of parentheses, that is not allowed in C++. C++ allows only one kind of parentheses in arithmetic expressions. The other varieties are reserved for other purposes.
If you omit parentheses, the computer will follow rules called precedence rules that determine the order in which the operators, such as +
and *
, are performed. These precedence rules are similar to rules used in algebra and other mathematics classes. For example,
x + y * z
is evaluated by first doing the multiplication and then the addition. Except in some standard cases, such as a string of additions or a simple multiplication embedded inside an addition, it is usually best to include the parentheses, even if the intended order of operations is the one dictated by the precedence rules. The parentheses make the expression easier to read and less prone to programmer error. A complete set of C++ precedence rules is given in Appendix 2.
Display 2.7 shows some examples of common kinds of arithmetic expressions and how they are expressed in C++.
Mathematical Formula | C++ Expression |
---|---|
b2 −; 4ac | b*b −; 4*a*c |
x(y + z) | x*(y + z) |
1/(x*x + x + 3) | |
(a + b)/(c −; d) |
Convert each of the following mathematical formulas to a C++ expression:
What is the output of the following program lines when embedded in a correct program that declares all variables to be of type char
?
a = 'b';
b = 'c';
c = a;
cout << a << b << c << 'c';
What is the output of the following program lines when embedded in a correct program that declares number
to be of type int
?
number = (1/3) * 3;
cout << "(1/3) * 3 is equal to " << number;
Write a complete C++ program that reads two whole numbers into two variables of type int
and then outputs both the whole-number part and the remainder when the first number is divided by the second. This can be done using the operators /
and %
.
Given the following fragment that purports to convert from degrees Celsius to degrees Fahrenheit, answer the following questions:
double c = 20;
double f;
f = (9/5) * c + 32.0;
What value is assigned to f?
Explain what is actually happening, and what the programmer likely wanted.
Rewrite the code as the programmer intended.
What is the output of the following program lines when embedded in a correct program that declares month
, day
, year
, and date
to be of type string
?
month = "03";
day = "04";
year = "06";
date = month + day + year;
cout << date << endl;
There is a shorthand notation that combines the assignment operator (=
) and an arithmetic operator so that a given variable can have its value changed by adding, subtracting, multiplying by, or dividing by a specified value. The general form is
Variable Op = Expression
which is equivalent to
Variable = Variable Op (Expression)
Op is an operator such as +
, *, or *
. The Expression can be another variable, a constant, or a more complicated arithmetic expression. Following are examples:
Example | Equivalent to: |
---|---|
count += 2; |
count = count + 2; |
total −= discount; |
total = total – discount; |
bonus *= 2; |
bonus = bonus * 2; |
time /= rushFactor; |
time = time / rushFactor; |
change %= 100; |
change = change % 100; |
amount *= cnt1 + cnt2; |
amount = amount * (cnt1 + cnt2); |