ADVANCED DECISIONS

advertisement
ADVANCED DECISIONS
In this topic, we will cover more advanced ways for a program to choose
between different actions: the else if construction, the powerful switch
statement, and the weird but compact conditional operator. I'll also apply the
switch statement to the hot dog stand program to enhance its functionality.
The else if Construction
In the previous topic, we looked at an example of an if...else statement that
displayed "am" or "pm" for hour values less than and greater than 12. We also
acknowledged that this statement didn't handle the occasions when hour was 0
or 12. How can we fix this? We can check for these specific values of hour and
respond accordingly. Here's how that looks with an if...else ladder:
if(hours == 0) // first-level indent
cout << "Midnight";
else
if(hours == 12) // second-level indent
cout << "Noon";
else
if(hours < 12) // third-level indent
cout << hours << " am";
else
cout << hours-12 << " pm";
If the hours is 0, it's midnight, so the program displays an appropriate message
and exits from the entire if...else ladder. If it isn't 0, the program goes on to
the next if...else. It keep moving to more deeply nested if...else
statements until it finds one whose test expression is true or it runs out of
possibilities.
This arrangement does what I want, but it's hard for humans to read the multiple
indentations. Here's a somewhat more easily understood way to rewrite the
same code:
if(hours == 0)
cout << "Midnight";
else if(hours == 12)
cout << "Noon";
else if(hours < 12)
cout << hours << " am";
else
cout << hours-12 << " pm";
The if that follows each else is simply moved up onto the same line, thus
creating a sort of artificial else if construction and removing the multiple
levels of indentation. This arrangement not only saves space, it presents a
clearer picture of the program's logic (at least, after you've gotten used to it).
Notice that the else if construction is not really a part of the syntax of the
C++ language; it's merely a way to rewrite an if...else ladder by
rearranging the whitespace on the page. You can do this because--as you
know--the compiler doesn't care about whitespace.
Fine-Tuning Loops
This is a good place to introduce the break and continue statements, even
though they pertain to loops, because they are used most effectively in
conjunction with decisions. Also, break is an important feature in the switch
statement, which I'll demonstrate next.
Usually loops work well with the straightforward syntax I showed in the last
session. However, sometimes you need to fudge things a bit to make a loop
behave as you want. The break and continue statements provide this added
flexibility.
The break Statement
The break statement causes you to exit immediately from a loop, as shown in
Figure 2-3.
Figure 2-3 Operation of the break statement
The break statement is often used to handle unexpected or nonstandard
situations that arise within a loop. For example, here's a code fragment that sets
the variable isPrime to 1 if an integer n is a prime number or to 0 if n is not a
prime number. (A prime number is divisible only by itself and 1.) To tell if n is
prime, I use the straightforward approach of trying to divide it by all the
numbers up to n-1. If any of them divide evenly (with no remainder), then it's
not prime.
isPrime = 1; // assume n is prime
for(j=2; j<n; ++j) // divide by all integers from 2 to n-1
{
if(n%j == 0) // if evenly divisible,
{
isPrime = 0; // n is not a prime
break; // no point in looping again
}
}
I want to divide by all the numbers up to n-1, so I use a for loop with
appropriate expressions. However, if one of the j values does divide evenly,
there's no use remaining in the loop and dividing by the remaining the j values.
As soon as the program finds the first number that divides evenly, it should set
isPrime to 0 and then immediately exit from the loop. The break statement
allows you to exit from the loop at any time.
The continue Statement
The continue statement is similar to the break statement in that it is usually
activated by an unexpected condition in a loop. However, it returns control to
the top of the loop--causing the loop to continue--rather than causing an exit
from the loop. Figure 2-4 shows how this looks.
Figure 2-4 Operation of the continue statement
Whereas the break statement causes an exit from a loop, the continue
statement causes part of the loop to be "short-circuited" or bypassed while the
loop keeps running. That is, following a continue, control goes back to the top
of the loop. Here's an example:
do
{
cout << "Enter dividend: ";
cin >> dividend;
cout << "Enter divisor: ";
cin >> divisor;
if(divisor == 0) // if user error,
{
cout << "Divisor can't be zero\n";
continue; // go back to top of loop
}
cout << "Quotient is " << dividend / divisor;
cout "\nDo another (y/n)? ";
cin >> ch;
} while(ch != 'n');
Division by zero is illegal, so if the user enters 0 for the divisor, control goes
back to the top of the loop and the program prompts for a new dividend and
divisor so the user can try again. To exit from the loop, the user must answer
'n' to the "Do another" question.
The switch Statement
Now you're ready for perhaps the most powerful decision-making construction
in C++. The switch statement checks a variable and routes program control to
any of a number of different sections of code, depending on the value of the
variable. Here's an example:
switch(diskSpeed)
{
case 33: // if diskSpeed is 33
cout << "Long-playing album";
break;
case 45: // if diskSpeed is 45
cout << "Single-selection";
break;
case 78: // if diskSpeed is 78
cout << "Old single-selection";
break;
default: // if nothing matches
cout << "Unknown format";
}
The switch statement consists of the keyword switch followed by a variable
name in parentheses. The body of the switch statement, enclosed in braces,
follows. Within the body are a number of labels, which are names followed by
a colon. In a switch statement, these labels consist of the keyword case
followed by a constant and then the colon. When the value of the switch
variable is equal to the constant following a particular case, control will go to
the statements following this case label.
The above section of code prints different messages depending on the value of
the diskSpeed variable. If diskSpeed is 33, control jumps to the label case
33. If diskSpeed is 45, control jumps to the label case 45, and so on. If
diskSpeed doesn't match any of the cases, control jumps to the default
label (or, if there is no default, falls through the bottom of the switch).
Figure 2-5 shows the syntax of the switch statement and Figure 2-6 shows
its operation.
Figure 2-5 Syntax of the switch statement
Figure 2-6 Operation of the switch statement
The variable or expression used to determine which label is jumped to
(diskSpeed, in this example) must be an integer or a character or must
evaluate to an integer or a character. The values following the cases must
be--or must evaluate to--integer or character constants. That is, you can use
variable names or expressions, such as alpha, j+20, and ch+'0', as long as
alpha, j, and ch already have appropriate values.
Once control gets to a label, the statements following the label are executed one
after the other from the label onward. In this example, the cout statement will
be executed. Then what? If the break weren't there, control would continue
down to the next cout statement, which is not what you want. Labels don't
delimit a section of code, they merely name an entry point. The break causes
control to break out of the switch entirely.
Here's another example that gives the user the choice of three hot dog stands for which to
record the sale of a hot dog. The user types a digit from '1' to '3', which is then used as the
switch
variable.
cin >> choice;
switch(choice)
{
case '1':
stand1; // hot dog stand 1 sold a hot dog
break;
case '2':
stand2; // hot dog stand 2 sold a hot dog
break;
case '3':
stand3; // hot dog stand 3 sold a hot dog
break;
}
The Conditional Operator
The conditional operator was invented because a particular construction occurs
often in C++ programs and it is nice to shorten it. Here's an example of the
lengthy version of the code:
if(alpha<beta)
min = alpha;
else
min = beta;
I have a variable min and I want to set it to alpha or beta, whichever is
smaller. This if...else statement requires four lines of code. (I could put it all
on one line, of course, but it would still be long and complicated.) However,
using the conditional operator, I can shorten it to
min = (alpha<beta) ? alpha : beta;
The conditional operator is the only C++ operator that operates on three
operands. It consists of two symbols: a question mark and a colon. First comes
a test expression (with optional parentheses), then the question mark, then two
values separated by the colon. If the test expression is true, the entire
expression takes on the value before the colon (here it's alpha); if the test
expression is false, the entire expression takes on the value following the colon
(beta). Figure 2-7 shows the syntax of the conditional operator and Figure
2-8 shows its operation.
Figure 2-7 Syntax of the conditional operator
Figure 2-8 Operation of the conditional operator
Here's another example. The statement
absvalue = (n<0) ? -n : n;
imitates an absolute value function. (The absolute value of a number is simply
the number with any negative sign removed.) The result is -n if n is less than 0
and +n otherwise.
Download