1. Trang chủ >
  2. Công Nghệ Thông Tin >
  3. Kỹ thuật lập trình >

9 Confusing the Equality (==) and Assignment (=) Operators

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 ) can be used to cause a value to be

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 header file that indicates

“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.



Xem Thêm
Tải bản đầy đủ (.pdf) (1,105 trang)

×