63 }
A sample run of Listing 5.14 (datetransformer.cpp) is shown here:
Please enter the month and day as numbers: 5 20 May 20 or 20 mayo
5.9
Errors in Conditional Statements
Consider Listing 5.15 (badequality.cpp).Listing 5.15: badequality.cpp 1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 int input;
8 cout << "Please enter an integer:"; 9 cin >> input;
10 if ( input = 2 )
11 cout << "two" << endl;
12 cout << "You entered " << input << endl;
13 }
Listing 5.15 (badequality.cpp) demonstrates a common mistake—using the assignment operator where the equality operator is intended. This program, when run, always prints the message “two” and insists the user entered 2 regardless of the actual input. Recall from Section 4.3 that the assignment expression has a value. The value of an assignment expression is same as the value that is assigned; thus, the expression
input = 2
has the value 2. When you consider also that every integer can be treated as a Boolean value (see Sec- tion 5.1) and any non-zero value is interpreted astrue, you can see that the condition ofifstatement
if ( input = 2 )
cout << "two" << endl;
is always true. Additionally, the variable input is always assigned the value 2.
Because it is such a common error, most C++compilers can check for such misuse of assignment. At warning Level 4, for example, Visual C++will issue a warning when assignment appears where a conditional expression is expected:
warning C4706: assignment within conditional expression
This check is not performed by default because sometimes the use of assignment within a conditional expression is warranted. We have no reason to do so, however, so it is a good idea to allow the Visual C++ compiler to perform the extra check.
5.10. SUMMARY 102
Carefully consider each compound conditional used, such as
value > 0 && value <= 10
found in Listing 5.7 (newcheckrange.cpp). Confusing logical and and logical or is a common programming error. The Boolean expression
x > 0 || x <= 10
is always true, no matter what value is assigned to the variable x. A Boolean expression that is always true is known as a tautology. Think about it. If x is anint, what value could the variable x assume that would make this Boolean expression false? Regardless of its value, one or both of the subexpressions will be true, so the compound logical or expression is always true. This particular or expression is just a complicated way of expressing the value true.
Another common error is contriving compound Boolean expressions that are always false, known as contradictions. Suppose you wish to exclude values from a given range; for example, reject values in the range 0...10 and accept all other numbers. Is the Boolean expression in the following code fragment up to the task?
// All but 0, 1, 2, ..., 10
if ( value < 0 && value > 10 )
/* Code to execute goes here . . . */
A closer look at the condition reveals it can never be true. What number can be both less than zero and greater than ten at the same time? None can, of course, so the expression is a contradiction and a compli- cated way of expressing false. To correct this code fragment, replace the && operator with ||.
5.10
Summary
• Thebooldata type represents the values true and false.
• The nameboolcomes from Boolean algebra, the mathematical study of operations on truth values. • In C++the valuetrueis represented by the integer one, andfalseis represented by zero. • Any integer value except zero is treated as true.
• Integers andbools are interchangeable and can be assigned to each other.
• Expressions involving the relational operators (==, !=, <, >, <=, and >=) evaluate to Boolean values. • ! is the unary not operator.
• Boolean expressions can be combined via && (logical AND) and || (logical OR). • Theifstatement can be used to optionally execute statements.
• A compound statement is a sequence of statements within a pair of curly braces.
• Theifstatement has an optionalelseclause to require the selection between two alternate paths of execution.
5.11. EXERCISES 103
• The bodies ofif/elsestatements should be indented to aid human readers. Indentation doe not affect the logic of the program; when multiple statements are to be part of the body of aniforelse, the statements must be part of a compound statement.
• Beware placing a semicolon immediately after the close parenthesis of anifstatement’s condition. • Complex Boolean expressions require special attention, as they are easy to get wrong.
• • •
5.11
Exercises
1. What values can a variable of typeboolassume? 2. Where does the termbooloriginate?
3. What is the integer equivalent totruein C++? 4. What is the integer equivalent tofalsein C++? 5. Is the value -16 interpreted as true or false?
6. May an integer value be assigned to aboolvariable? 7. Cantruebe assigned to anintvariable?
8. Given the following declarations:
int x = 3, y = 5, z = 7;
bool b1 = true, b2 = false, b3 = x == 3, b4 = y < 3;
evaluate the following Boolean expressions: (a) x == 3 (b) x < y (c) x >= y (d) x <= y (e) x != y - 2 (f) x < 10 (g) x >= 0 && x < 10 (h) x < 0 && x < 10 (i) x >= 0 && x < 2 (j) x < 0 || x < 10 (k) x > 0 || x < 10 (l) x < 0 || x > 10 (m) b1
5.11. EXERCISES 104
(n) !b1 (o) !b2 (p) b1 && b2
9. Express the following Boolean expressions in simpler form; that is, use fewer operators. x is anint. (a) !(x == 2) (b) x < 2 || x == 2 (c) !(x < y) (d) !(x <= y) (e) x < 10 && x > 20 (f) x > 10 || x < 20 (g) x != 0 (h) x == 0
10. What is the simplest tautology? 11. What is the simplest contradiction?
12. Write a C++program that requests an integer value from the user. If the value is between 1 and 100 inclusive, print “OK;” otherwise, do not print anything.
13. Write a C++program that requests an integer value from the user. If the value is between 1 and 100 inclusive, print “OK;” otherwise, print “Out of range.”
14. Write a C++program that requests an integer value from the user. If the value is between 1 and 100 inclusive,
15. The following program attempts to print a message containing the the English word correspond- ing to a given integer input. For example, if the user enters the value 3, the program should print
"You entered a three". In its current state, the program contains logic errors. Locate the problems and repair them so the program will work as expected.
#include <iostream>
using namespace std;
int main() {
cout << "Please in value in the range 1...5: ";
int value; cin >> value;
// Translate number into its English word
if ( month == 1 )
cout << "You entered a"; cout << "one";
cout << endl;
else if ( month == 2 )
cout << "You entered a"; cout << "two";
5.11. EXERCISES 105
else if ( month == 3 )
cout << "You entered a"; cout << "three";
cout << endl;
else if ( month == 4 )
cout << "You entered a"; cout << "four";
cout << endl;
else if ( month == 5 )
cout << "You entered a"; cout << "five";
cout << endl;
else // Value out of range cout << "You entered a"; cout << "value out of range"; cout << endl;
}
16. Consider the following section of C++code:
// i, j, and k are ints
if ( i < j ) { if ( j < k ) i = j; else j = k; } else { if ( j > k ) j = i; else i = k; }
cout << "i = " << i << " j = " << j << " k = " << k << endl;
What will the code print if the variables i, j, and k have the following values? (a) i is 3, j is 5, and k is 7 (b) i is 3, j is 7, and k is 5 (c) i is 5, j is 3, and k is 7 (d) i is 5, j is 7, and k is 3 (e) i is 7, j is 3, and k is 5 (f) i is 7, j is 5, and k is 3
17. Consider the following C++program that prints one line of text: #include <iostream>
5.11. EXERCISES 106 int main() { int input; cin >> input; if ( input < 10 ) { if ( input != 5 ) cout << "wow "; else input++; } else { if ( input == 17 ) input += 10; else cout << "whoa "; }
cout << input << endl; }
What will the program print if the user provides the following input? (a) 3
(b) 21 (c) 5 (d) 17 (e) -5
18. Why does the following section of code always print"ByeHi"? int x;
cin >> x;
if ( x < 0 ); cout << "Bye"; cout << "Hi" << endl;
19. Write a C++program that requests five integer values from the user. It then prints the maximum and minimum values entered. If the user enters the values 3, 2, 5, 0, and 1, the program would indicate that 5 is the maximum and 0 is the minimum. Your program should handle ties properly; for example, if the user enters 2, 4 2, 3 and 3, the program should report 2 as the minimum and 4 as maximum. 20. Write a C++ program that requests five integer values from the user. It then prints one of two
things: if any of the values entered are duplicates, it prints "DUPLICATES"; otherwise, it prints
"ALL UNIQUE".
107
Chapter 6
Iteration
Iteration repeats the execution of a sequence of code. Iteration is useful for solving many programming problems. Iteration and conditional execution form the basis for algorithm construction.
6.1
The while Statement
Listing 6.1 (counttofive.cpp) counts to five by printing a number on each output line.
Listing 6.1: counttofive.cpp 1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 cout << 1 << endl; 8 cout << 2 << endl; 9 cout << 3 << endl; 10 cout << 4 << endl; 11 cout << 5 << endl; 12 }
When compiled and run, this program displays
1 2 3 4 5
How would you write the code to count to 10,000? Would you copy, paste, and modify 10,000 printing statements? You could, but that would be impractical! Counting is such a common activity, and computers
6.1. THE WHILE STATEMENT 108
routinely count up to very large values, so there must be a better way. What we really would like to do is print the value of a variable (call it count), then increment the variable (count++), and repeat this process until the variable is large enough (count == 5 or count == 10000). This process of executing the same section of code over and over is known as iteration, or looping, and C++can accomplish it in several different ways.
Listing 6.2 (iterativecounttofive.cpp) uses awhilestatement to count to five:
Listing 6.2: iterativecounttofive.cpp 1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 {
7 int count = 1; // Initialize counter
8 while ( count <= 5 )
9 {
10 cout << count << endl; // Display counter, then
11 count++; // Increment counter
12 }
13 }
Listing 6.2 (iterativecounttofive.cpp) uses a while statement to display a variable that is counting up to five. Unlike the approach taken in Listing 6.1 (counttofive.cpp), it is trivial to modify Listing 6.2 (iterativecounttofive.cpp) to count up to 10,000—just change the literal value 5 to 10000.
The line
while ( count <= 5 )
begins thewhilestatement. The expression within the parentheses must be a Boolean expression. If the Boolean expression is true when thewhilestatement is executed, the body of thewhilestatement is executed, and the body is executed repeatedly as long as the Boolean expression remains true.
The statements
cout << count << endl; count++;
constitute the body of thewhilestatement. The curly braces are necessary since more than one statement makes up the body.
Thewhilestatement has the general form:
while
(
condition )
statement ;
• The reserved wordwhilebegins thewhilestatement.
• The Boolean expression condition determines whether the body will be (or will continue to be) exe- cuted. The expression must be enclosed within parentheses as shown.
6.1. THE WHILE STATEMENT 109
• The statement is the statement to be executed while the Boolean expression is true. The statement makes up the body of thewhilestatement. The statement may be a compound statement (multiple statements enclosed within curly braces, see Section 5.4).
Except for the reserved wordwhileinstead ofif,whilestatements look identical toifstatements. Sometimes beginning programmers confuse the two or accidentally typeifwhen they meanwhileor vice-versa. Usually the very different behavior of the two statements reveals the problem immediately; however, sometimes, especially in nested complex logic, this mistake can be hard to detect.
Figure 6.1 shows how program execution flows through Listing 6.2 (iterativecounttofive.cpp).
Figure 6.1: while flowchart for Listing 6.2 (iterativecounttofive.cpp)
The condition is checked before the body is executed, and then each time after the body has been executed. If the condition is initially false the body is not executed. If the condition is initially true, the body is executed repeatedly until the condition becomes false, at which point the loop terminates. Observe that the body may never be executed if the Boolean expression in the condition is initially false.
6.1. THE WHILE STATEMENT 110
Listing 6.3: countup.cpp
1 /*
2 * Counts up from zero. The user continues the count by entering
3 * 'Y'. The user discontinues the count by entering 'N'.
4 */ 5 6 #include <iostream> 7 8 using namespace std; 9 10 int main() 11 {
12 char input; // The users choice
13 int count = 0; // The current count
14 bool done = false; // We are not done
15
16 while ( !done )
17 {
18
19 // Print the current value of count
20 cout << count << endl;
21 cout << "Please enter \"Y\" to continue or \"N\" to quit: "; 22 cin >> input;
23 // Check for "bad" input
24 if ( input != 'Y' && input != 'y' && input != 'N' && input != 'n' ) 25 cout << "\"" << input << "\""
26 << " is not a valid choice" << endl; 27 else if ( input == 'Y' || input == 'y' )
28 count++; // Keep counting
29 else if ( input == 'N' || input == 'n' )
30 done = true; // Quit the loop
31 }
32 }
6.1. THE WHILE STATEMENT 111
0
Please enter "Y" to continue or "N" to quit: y 1
Please enter "Y" to continue or "N" to quit: y 2
Please enter "Y" to continue or "N" to quit: y 3
Please enter "Y" to continue or "N" to quit: q "q" is not a valid choice
3
Please enter "Y" to continue or "N" to quit: r "r" is not a valid choice
3
Please enter "Y" to continue or "N" to quit: W "W" is not a valid choice
3
Please enter "Y" to continue or "N" to quit: Y 4
Please enter "Y" to continue or "N" to quit: y 5
Please enter "Y" to continue or "N" to quit: n
In Listing 6.3 (countup.cpp) the expression
input != 'Y' && input != 'y' && input != 'N' && input != 'n'
is true if the character variable input is not equal to one of the listed character literals. The Boolean variable done controls the loop’s execution. It is important to note that the expression
!done
inside thewhile’s condition evaluates to the opposite truth value of the variable done; the expression does not affect the value of done. In other words, the ! operator applied to a variable does not modify the variable’s value. In order to actually change the variable done, you would need to reassign it, as in
done = !done; // Invert the truth value
For Listing 6.3 (countup.cpp) we have no need to invert its value. We ensure that its value isfalseinitially and then make ittruewhen the user enters a capital or lower-case N.
Listing 6.4 (addnonnegatives.cpp) is a program that allows a user to enter any number of non-negative integers. When the user enters a negative value, the program no longer accepts input, and it displays the sum of all the non-negative values. If a negative number is the first entry, the sum is zero.
Listing 6.4: addnonnegatives.cpp
1 /*
2 * Allow the user to enter a sequence of non-negative
3 * integers. The user ends the list with a negative
4 * integer. At the end the sum of the non-negative
5 * integers entered is displayed. The program prints
6.1. THE WHILE STATEMENT 112 7 */ 8 9 #include <iostream> 10 11 using namespace std; 12 13 int main() 14 {
15 int input = 0, // Ensure the loop is entered
16 sum = 0; // Initialize sum
17
18 // Request input from the user
19 cout << "Enter numbers to sum, negative number ends list:"; 20
21 while ( input >= 0 ) // A negative number exits the loop
22 {
23 cin >> input; // Get the value
24 if ( input >= 0 )
25 sum += input; // Only add it if it is non-negative
26 }
27 cout << "Sum = " << sum << endl; // Display the sum
28 }
The initialization of input to zero coupled with the condition input >= 0 of thewhileguarantees that the body of thewhileloop will be executed at least once. Theifstatement ensures that a negative entry will not be added to sum. (Could the condition have used > instead of >= and achieved the same results?) Upon entry of a negative value, sum will not be updated and the condition of thewhilewill no longer be true. The loop then terminates and the print statement is finally executed.
Listing 6.4 (addnonnegatives.cpp) shows that awhileloop can be used for more than simple counting. The program does not keep track of the number of values entered. The program simply accumulates the entered values in the variable named sum.
It is a little awkward in Listing 6.4 (addnonnegatives.cpp) that the same condition appears twice, once in thewhileand again in theif. Furthermore, what if the user wishes to enter negative values along with non-negative values? The code can be simplified with a common C++idiom that uses cin and the extraction operator as a condition within anwhilestatement.
If x is an integer, the expression
cin >> x
evaluates tofalseif the user does not enter a valid integer literal. Armed with this knowledge we can simplify and enhance Listing 6.4 (addnonnegatives.cpp) as shown in Listing 6.5 (addnumbers.cpp).
Listing 6.5: addnumbers.cpp 1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 {
7 int input, sum = 0;
8 cout << "Enter numbers to sum, type 'q' to end the list:"; 9 while ( cin >> input )
6.1. THE WHILE STATEMENT 113
10 sum += input;
11 cout << "Sum = " << sum << endl;
12 }
The condition reads a value from the input stream and, if it is successful, it is interpreted as true. When the user enters'q', the loop is terminated. If the user types'q'at the beginning, the loop is not entered. Theifstatement is no longer necessary, since the statement
sum += input;
can be executed only if input has been legitimately assigned. Also, the variable input no longer needs to initialized with a value simply so the loop is entered the first time; now it is assigned and then checked within the condition of thewhile.
In Listing 6.5 (addnumbers.cpp), the program’s execution will terminate with any letter the user types; an entry of'x'or Ctrl-Z will terminate the sequence just as well as'q'.
If you use the
while ( cin >> x ) {
// Do something . . . }
idiom, be aware that when the loop is exited due to the input stream being unable to read a value of the type of variable x, the cin input stream object is left in an error state and cannot be used for the rest of the program’s execution. It you wish to use this technique and reuse cin later, you must reset cin and extract and discard keystrokes entered since the last valid use of the extractor operator. This recovery process is covered in Section 13.3, but, for now, use this idiom to control a loop only if the program does not require additional user input later during its execution.
Listing 6.6 (powersof10.cpp) prints the powers of 10 from 1 to 1,000,000,000 (the next power of ten, 10,000,000,000, is outside the range of theinttype).
Listing 6.6: powersof10.cpp 1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 int power = 1; 8 while ( power <= 1000000000 ) 9 {
10 cout << power << endl;
11 power *= 10;
12 }
13 }
6.1. THE WHILE STATEMENT 114 1 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000
It is customary to right justify a column of numbers, but Listing 6.6 (powersof10.cpp) prints the powers of ten with their most-significant digit left aligned. We can right align the numbers using a stream object called a steam manipulator. The specific stream manipulator we need is named setw. setw means “set width.” It can be used as
cout << setw(3) << x << endl;
This statement prints the value of x right justified within a three character horizontal space on the screen.