Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (6.41 MB, 1,105 trang )
192
Chapter 5 Control Statements: Part 2
The first if statement properly awards a bonus to the person whose payCode is equal to 4.
The second one—with the error—evaluates the assignment expression in the if condition
to the constant 4. Any nonzero value is interpreted as true, so this condition is always true
and the person always receives a bonus regardless of what the actual paycode is! Even
worse, the paycode has been modified when it was only supposed to be examined!
Common Programming Error 5.14
Using operator == for assignment and using operator = for equality are logic errors.
Error-Prevention Tip 5.3
Programmers normally write conditions such as x == 7 with the variable name on the left
and the constant on the right. By placing the constant on the left, as in 7 == x, you’ll be
protected by the compiler if you accidentally replace the == operator with = . The compiler
treats this as a compilation error, because you can’t change the value of a constant. This
will prevent the potential devastation of a runtime logic error.
Variable names are said to be lvalues (for “left values”) because they can be used on
the left side of an assignment operator. Constants are said to be rvalues (for “right values”)
because they can be used on only the right side of an assignment operator. Lvalues can also
be used as rvalues, but not vice versa.
There is another equally unpleasant situation. Suppose you want to assign a value to
a variable with a simple statement like
x = 1;
but instead write
x == 1;
Here, too, this is not a syntax error. Rather, the compiler simply evaluates the conditional
expression. If x is equal to 1, the condition is true and the expression evaluates to the value
true. If x is not equal to 1, the condition is false and the expression evaluates to the value
false. Regardless of the expression’s value, there is no assignment operator, so the value
simply is lost. The value of x remains unaltered, probably causing an execution-time logic
error. Unfortunately, we do not have a handy trick available to help you with this problem!
Error-Prevention Tip 5.4
Use your text editor to search for all occurrences of = in your program and check that you
have the correct assignment operator or logical operator in each place.
5.10 Structured Programming Summary
Just as architects design buildings by employing the collective wisdom of their profession,
so should programmers design programs. Our field is younger than architecture is, and our
collective wisdom is sparser. We’ve learned that structured programming produces programs that are easier than unstructured programs to understand, test, debug, modify, and
even prove correct in a mathematical sense.
Figure 5.20 uses activity diagrams to summarize C++’s control statements. The initial
and final states indicate the single entry point and the single exit point of each control
5.10 Structured Programming Summary
Sequence
193
Selection
if statement
switch statement with breaks
(multiple selection)
(single selection)
[t]
[t]
break
[f]
[f]
...
[t]
break
[f]
if…else statement
(double selection)
...
[f]
[t]
[t]
break
[f]
default processing
Repetition
while statement
do…while statement
for statement
initialization
[t]
[f]
[t]
[f]
[t]
body
increment
[f]
Fig. 5.20 | C++’s single-entry/single-exit sequence, selection and repetition statements.
194
Chapter 5 Control Statements: Part 2
statement. Arbitrarily connecting individual symbols in an activity diagram can lead to
unstructured programs. Therefore, the programming profession uses only a limited set of
control statements that can be combined in only two simple ways to build structured programs.
For simplicity, only single-entry/single-exit control statements are used—there is only
one way to enter and only one way to exit each control statement. Connecting control
statements in sequence to form structured programs is simple—the final state of one control statement is connected to the initial state of the next—that is, they’re placed one after
another in a program. We’ve called this “control-statement stacking.” The rules for
forming structured programs also allow for control statements to be nested.
Figure 5.21 shows the rules for forming structured programs. The rules assume that
action states may be used to indicate any action. The rules also assume that we begin with
the so-called simplest activity diagram (Fig. 5.22), consisting of only an initial state, an
action state, a final state and transition arrows.
Rules for forming structured programs
1)
2)
3)
4)
Begin with the “simplest activity diagram” (Fig. 5.22).
Any action state can be replaced by two action states in sequence.
Any action state can be replaced by any control statement (sequence,
if, if…else, switch, while, do…while or for).
Rules 2 and 3 can be applied as often as you like and in any order.
Fig. 5.21 | Rules for forming structured programs.
action state
Fig. 5.22 | Simplest activity diagram.
Applying the rules of Fig. 5.21 always results in an activity diagram with a neat,
building-block appearance. For example, repeatedly applying Rule 2 to the simplest
activity diagram results in an activity diagram containing many action states in sequence
(Fig. 5.23). Rule 2 generates a stack of control statements, so let’s call Rule 2 the stacking
rule. [Note: The vertical dashed lines in Fig. 5.23 are not part of the UML. We use them
to separate the four activity diagrams that demonstrate Rule 2 of Fig. 5.21 being applied.]
Rule 3 is the nesting rule. Repeatedly applying Rule 3 to the simplest activity diagram
results in one with neatly nested control statements. For example, in Fig. 5.24, the action
state in the simplest activity diagram is replaced with a double-selection (if…else) state-
5.10 Structured Programming Summary
apply
Rule 2
action state
apply
Rule 2
195
apply
Rule 2
action state
action state
action state
action state
action state
...
action state
action state
Fig. 5.23 | Repeatedly applying Rule 2 of Fig. 5.21 to the simplest activity diagram.
ment. Then Rule 3 is applied again to the action states in the double-selection statement,
replacing each with a double-selection statement. The dashed action-state symbols around
each of the double-selection statements represent an action state that was replaced in the
preceding activity diagram. [Note: The dashed arrows and dashed action state symbols
shown in Fig. 5.24 are not part of the UML. They’re used here as pedagogic devices to
illustrate that any action state may be replaced with a control statement.]
Rule 4 generates larger, more involved and more deeply nested statements. The diagrams that emerge from applying the rules in Fig. 5.21 constitute the set of all possible
activity diagrams and hence the set of all possible structured programs. The beauty of the
structured approach is that we use only seven simple single-entry/single-exit control statements and assemble them in only two simple ways.
If the rules in Fig. 5.21 are followed, an activity diagram with illegal syntax (such as
that in Fig. 5.25) cannot be created. If you are uncertain about whether a particular diagram is legal, apply the rules of Fig. 5.21 in reverse to reduce the diagram to the simplest
activity diagram. If it’s reducible to the simplest activity diagram, the original diagram is
structured; otherwise, it isn’t.
Structured programming promotes simplicity. Böhm and Jacopini have given us the
result that only three forms of control are needed:
•
Sequence
•
Selection
•
Repetition
The sequence structure is trivial. Simply list the statements to execute in the order in which
they should execute.
196
Chapter 5 Control Statements: Part 2
apply
Rule 3
action state
apply
Rule 3
action state
action state
action state
apply
Rule 3
action state
action state
action state
Fig. 5.24 | Applying Rule 3 of Fig. 5.21 to the simplest activity diagram several times.
action state
action state
action state
Fig. 5.25 | Activity diagram with illegal syntax.
action state
5.11 Wrap-Up
197
Selection is implemented in one of three ways:
•
if
•
if…else
•
switch
statement (single selection)
statement (double selection)
statement (multiple selection)
It’s straightforward to prove that the simple if statement is sufficient to provide any
form of selection—everything that can be done with the if…else statement and the
switch statement can be implemented (although perhaps not as clearly and efficiently) by
combining if statements.
Repetition is implemented in one of three ways:
• while statement
•
do…while
•
for
statement
statement
It’s straightforward to prove that the while statement is sufficient to provide any form of
repetition. Everything that can be done with the do…while statement and the for statement can be done (although perhaps not as smoothly) with the while statement.
Combining these results illustrates that any form of control ever needed in a C++ program can be expressed in terms of the following:
•
sequence
•
if
•
while
statement (selection)
statement (repetition)
and that these control statements can be combined in only two ways—stacking and nesting. Indeed, structured programming promotes simplicity.
5.11 Wrap-Up
We’ve now completed our introduction to control statements, which enable you to control the flow of execution in functions. Chapter 4 discussed the if, if…else and while
statements. This chapter demonstrated the for, do…while and switch statements. We
showed that any algorithm can be developed using combinations of the sequence structure, the three types of selection statements—if, if…else and switch—and the three
types of repetition statements—while, do…while and for. We discussed how you can
combine these building blocks to utilize proven program construction and problem-solving techniques. You used the break and continue statements to alter a repetition statement’s flow of control. This chapter also introduced logical operators, which enable you
to use more complex conditional expressions in control statements. Finally, we examined
the common errors of confusing the equality and assignment operators and provided suggestions for avoiding these errors. In Chapter 6, we examine functions in greater depth.
Summary
Section 5.2 Essentials of Counter-Controlled Repetition
• In C++, it’s more precise to call a declaration that also reserves memory a definition.
198
Chapter 5 Control Statements: Part 2
Section 5.3 for Repetition Statement
• The for repetition statement handles all the details of counter-controlled repetition.
• The general format of the for statement is
initialization; loopContinuationCondition; increment )
statement
for (
•
•
•
•
•
where initialization initializes the control variable, loopContinuationCondition determines whether
the loop should continue executing and increment increments or decrements the control variable.
Typically, for statements are used for counter-controlled repetition and while statements are
used for sentinel-controlled repetition.
The scope of a variable specifies where it can be used in a program.
The comma operator has the lowest precedence of all C++ operators. The value and type of a
comma-separated list of expressions is the value and type of the rightmost expression in the list.
The initialization, loop-continuation condition and increment expressions of a for statement
can contain arithmetic expressions. Also, the increment of a for statement can be negative.
If the loop-continuation condition in a for header is initially false, the body of the for statement is not performed. Instead, execution proceeds with the statement following the for.
Section 5.4 Examples Using the for Statement
• Standard library function pow( x, y ) calculates the value of x raised to the yth power. Function
pow takes two arguments of type double and returns a double value.
• Parameterized stream manipulator setw specifies the field width in which the next value output
should appear. The value is right justified in the field by default. If the value to be output is larger
than the field width, the field width is extended to accommodate the entire value. Nonparameterized stream manipulator left (found in header
left justified in a field and right can be used to restore right justification.
• Sticky settings are those output-formatting settings that remain in effect until they’re changed.
Section 5.5 do…while Repetition Statement
• The do…while repetition statement tests the loop-continuation condition at the end of the loop,
so the body of the loop will be executed at least once. The format for the do…while statement is
do
{
statement
condition
} while (
);
Section 5.6 switch Multiple-Selection Statement
• The switch multiple-selection statement performs different actions based on the possible values
of a variable or expression. Each action is associated with the value of a constant integral expression that the variable or expression on which the switch is based may assume.
• The switch statement consists of a series of case labels and an optional default case.
• Function cin.get() reads one character from the keyboard. Characters normally are stored in
variables of type char. A character can be treated either as an integer or as a character.
• The end-of-file indicator is a system-dependent keystroke combination that specifies that there
is no more data to input. EOF is a constant defined in the
“end-of-file.”
• The expression in the parentheses following keyword switch is called the controlling expression.
The switch statement compares the value of the controlling expression with each case label.
Summary
199
• Listing cases consecutively with no statements between them enables the cases to perform the
same set of statements.
• Each case can have multiple statements. The switch selection statement differs from other control statements in that it does not require braces around multiple statements in each case.
• Each case can be used only to test only a constant integral expression. A character constant is
represented as the specific character in single quotes, such as 'A'. An integer constant is simply
an integer value. Also, each case label can specify only one constant integral expression.
• C++ provides several data types to represent integers—int, char, short and long. The range of
integer values for each type depends on the particular computer’s hardware.
Section 5.7 break and continue Statements
• The break statement, when executed in one of the repetition statements (for, while and
do…while), causes immediate exit from the statement.
• The continue statement, when executed in one of the repetition statements (for, while and
do…while), skips any remaining statements in the body of the repetition statement and proceeds
with the next iteration of the loop. In a while or do…while statement, execution continues with
the next evaluation of the condition. In a for statement, execution continues with the increment
expression in the for statement header.
Section 5.8 Logical Operators
• Logical operators enable you to form complex conditions by combining simple conditions. The
logical operators are && (logical AND), || (logical OR) and ! (logical negation).
• The && (logical AND) operator ensures that two conditions are both true.
• The || (logical OR) operator ensures that either or both of two conditions are true.
• An expression containing && or || operators evaluates only until the truth or falsehood of the expression is known. This performance feature for the evaluation of logical AND and logical OR
expressions is called short-circuit evaluation.
• The ! (logical NOT, also called logical negation) operator enables a programmer to “reverse” the
meaning of a condition. The unary logical negation operator is placed before a condition to
choose a path of execution if the original condition (without the logical negation operator) is
false. In most cases, you can avoid using logical negation by expressing the condition with an
appropriate relational or equality operator.
• When used as a condition, any nonzero value implicitly converts to true; 0 (zero) implicitly converts to false.
• By default, bool values true and false are displayed by cout as 1 and 0, respectively. Stream manipulator boolalpha (a sticky manipulator) specifies that the value of each bool expression should
be displayed as either the word “true” or the word “false.”
Section 5.9 Confusing the Equality (==) and Assignment (=) Operators
• Any expression that produces a value can be used in the decision portion of any control statement. If the value of the expression is zero, it’s treated as false, and if the value is nonzero, it’s
treated as true.
• An assignment produces a value—namely, the value assigned to the variable on the left side of
the assignment operator.
Section 5.10 Structured Programming Summary
• Any form of control can be expressed in terms of sequence, selection and repetition statements,
and these can be combined in only two ways—stacking and nesting.
200
Chapter 5 Control Statements: Part 2
Terminology
!,
logical NOT operator 189
logical AND operator 187
||, logical OR operator 188
ASCII (American Standard Code for
Information Interchange) character set 180
boolalpha stream manipulator 190
break statement 185
case label 181
char fundamental type 179
comma operator 168
constant integral expression 176
continue statement 186
controlling expression of a switch 181
decrement a control variable 164
default case in switch 181
definition 165
field width 173
final value of a control variable 164
for repetition statement 166
increment a control variable 164
initial value of a control variable 164
left justified 174
left stream manipulator 174
&&,
logical AND (&&) 187
logical negation (!) 189
logical NOT (!) 189
logical operator 187
logical OR (||) 188
loop-continuation condition 164
lvalue (“left value”) 192
name of a control variable 164
nesting rule 194
off-by-one error 167
pow standard library function 173
right justified 173
right stream manipulator 174
rvalue (“right value”) 192
scope of a variable 168
setw stream manipulator 173
short-circuit evaluation 189
simple condition 187
stacking rule 194
sticky setting 174
switch multiple-selection statement 176
truth table 188
zero-based counting 167
Self-Review Exercises
5.1
State whether the following are true or false. If the answer is false, explain why.
a) The default case is required in the switch selection statement.
b) The break statement is required in the default case of a switch selection statement to
exit the switch properly.
c) The expression ( x > y && a < b ) is true if either the expression x > y is true or the
expression a < b is true.
d) An expression containing the || operator is true if either or both of its operands are true.
5.2
Write a C++ statement or a set of C++ statements to accomplish each of the following:
a) Sum the odd integers between 1 and 99 using a for statement. Assume the integer variables sum and count have been declared.
b) Print the value 333.546372 in a 15-character field with precisions of 1, 2 and 3. Print each
number on the same line. Left-justify each number in its field. What three values print?
c) Calculate the value of 2.5 raised to the power 3 using function pow. Print the result with
a precision of 2 in a field width of 10 positions. What prints?
d) Print the integers from 1 to 20 using a while loop and the counter variable x. Assume
that the variable x has been declared, but not initialized. Print only 5 integers per line.
[Hint: When x % 5 is 0, print a newline character; otherwise, print a tab character.]
e) Repeat Exercise 5.2(d) using a for statement.
5.3
Find the errors in each of the following code segments and explain how to correct them.
a) x = 1;
while ( x <= 10 );
x++;
}
Answers to Self-Review Exercises
b)
for ( y = .1; y != 1.0; y += .1 )
c)
201
switch ( n )
cout << y << endl;
{
case 1:
cout << "The number is 1" << endl;
case 2:
cout << "The number is 2" << endl;
break;
default:
cout << "The number is not 1 or 2" << endl;
break;
}
d) The following code should print the values 1 to 10.
n = 1;
while ( n < 10 )
cout << n++ << endl;
Answers to Self-Review Exercises
5.1
5.2
a) False. The default case is optional. Nevertheless, it’s considered good software engineering to always provide a default case.
b) False. The break statement is used to exit the switch statement. The break statement is
not required when the default case is the last case. Nor will the break statement be required if having control proceed with the next case makes sense.
c) False. When using the && operator, both of the relational expressions must be true for
the entire expression to be true.
d) True.
a) sum = 0;
for ( count = 1; count <= 99; count += 2 )
sum += count;
b)
cout << fixed << left
<< setprecision( 1 ) << setw( 15 ) << 333.546372
<< setprecision( 2 ) << setw( 15 ) << 333.546372
<< setprecision( 3 ) << setw( 15 ) << 333.546372
<< endl;
Output is:
c)
333.5
333.55
333.546
cout << fixed << setprecision( 2 )
<< setw( 10 ) << pow( 2.5, 3 )
<< endl;
Output is:
d)
15.63
x = 1;
while ( x <= 20 )
{
if ( x % 5 == 0 )
cout << x << endl;
else
cout << x << '\t';
x++;
}
202
Chapter 5 Control Statements: Part 2
e)
5.3
for ( x = 1; x <= 20; x++ )
{
if ( x % 5 == 0 )
cout << x << endl;
else
cout << x << '\t';
}
a) Error: The semicolon after the while header causes an infinite loop.
Correction: Replace the semicolon by a {, or remove both the ; and the }.
b) Error: Using a floating-point number to control a for repetition statement.
Correction: Use an int and perform the proper calculation to get the values you desire.
for ( y = 1; y != 10; y++ )
cout << ( static_cast< double >( y ) / 10 ) << endl;
c) Error: Missing break statement in the first case.
Correction: Add a break statement at the end of the first case. This is not an error if you
want the statement of case 2: to execute every time the case 1: statement executes.
d) Error: Improper relational operator used in the loop-continuation condition.
Correction: Use <= rather than <, or change 10 to 11.
Exercises
5.4
Find the error(s), if any, in each of the following:
a) For ( x = 100, x >= 1, x++ )
cout << x << endl;
b) The following code should print whether integer value is odd or even:
switch ( value % 2 )
{
case 0:
cout << "Even integer" << endl;
case 1:
cout << "Odd integer" << endl;
}
c) The following code should output the odd integers from 19 to 1:
for ( x = 19; x >= 1; x += 2 )
cout << x << endl;
d) The following code should output the even integers from 2 to 100:
counter = 2;
do
{
cout << counter << endl;
counter += 2;
} While ( counter < 100 );
5.5
(Summing Integers) Write a program that uses a for statement to sum a sequence of integers. Assume that the first integer read specifies the number of values remaining to be entered. Your
program should read only one value per input statement. A typical input sequence might be
5 100 200 300 400 500
where the 5 indicates that the subsequent 5 values are to be summed.
5.6
(Averaging Integers) Write a program that uses a for statement to calculate the average of
several integers. Assume the last value read is the sentinel 9999. A typical input sequence might be
10 8 11 7 9 9999
indicating that the program should calculate the average of all the values preceding 9999.