Other Loo p Options
Now that you have mastered the looping constructs, you should learn some loop-related statements. This chapter teaches the con- cepts of timing loops, which enable you to slow down your programs. Slowing program execution can be helpful if you want to display a message for a fixed period of time or write computer games with slower speeds so they are at a practical speed for recreational use.
You can use two additional looping commands, the br eak and cont i nue statements, to control the loops. These statements work with whil e loops and f or loops.
This chapter introduces you to the following:
-
Timing loops
-
The br eak statement with f or loops
-
The cont i nue statement with f or loops
When you master these concepts, you will be well on your way toward writing powerful programs that process large amounts of data.
Chapter 14 ♦ Other Loop Options
Timing Loop s
Computers are fast, and at times you would probably like them to be even faster. Sometimes, however, you want to slow down the computer. Often, you have to slow the execution of games because the computer’s speed makes the game unplayable. Messages that appear on-screen many times clear too fast for the user to read if you don’t delay them.
A nested loop is a perfect place for a timing loop, which simply cycles through a f or or whil e loop many times. The larger the end value of the f or loop, the longer the time in which the loop repeats. A nested loop is appropriate for displaying error messages to your user. If the user requested a report—but had not entered enough data for your program to print the report—you might print a warning message on-screen for a few seconds, telling users that they cannot request the report yet. After displaying the message for a few seconds, you can clear the message and give the user another chance. (The example program in Appendix F, “The Mailing List
Application,” uses timing loops to display error messages.)
Timing loops make the computer wait.
There is no way to determine how many iterations a timing loop takes for one second (or minute or hour) of delay because computers run at different speeds. You therefore have to adjust your timing loop’s end value to set the delay to your liking.
Examples
- Timing
loops are easy to write—simply put an empty f or loop inside the program. The following program is a rewrit- ten version of the countdown program (C13CNTD1.CPP) you saw in Chapter 13. Each number in the countdown is delayed so the countdown does not seem to take place instantly. (Adjust the delay value if this program runs too slowly or too quickly on your computer.)
Identify the program and include the input/output header file. You need a counter and a delay, so make cd and del ay integer variables. Start the counter at 10, and start the del ay at 1.
- If the del ay *is less than or equal to 30,000, add 1 to its value
and repeat step one.*
EXAMPLE
-
Print the value of the counter.
-
*If the counter is greater than or equal to 0, subtract 1 from its
value and repeat step one.*
Print a blast-off message.
/ / Fil ename: C14CNTD1. CPP
/ / Count down t o t he li ft of f wi t h a del ay. #i ncl ude <i ost r eam. h>
mai n( )
{
i nt cd, del ay;
f or ( cd=10; cd>=0; cd--)
{ { f or ( del ay=1; del ay <=30000; del ay++) ; } / / Del ay
/ / pr ogr am.
cout << cd << “ \ n” ; / / Pr i nt count down val ue.
} / / End of out er l oop
cout << “ Bl ast of f ! ! ! \ n” ; r et ur n 0;
}
- The
following program asks users for their ages. If a user enters an age less than 0, the program beeps (by printing an alarm character, \ a ), then displays an error message for a few seconds by using a nested timing loop. Because an integer does not hold a large enough value (on many computers) for a long timing loop, you must use a nested timing loop. (Depending on the speed of your computer, adjust the numbers in the loop to display the message longer or shorter.)
The program uses a rarely seen pr i ntf () conversion charac- ter, \
r , inside the loop. As you might recall from Chapter 7, “Simple Input
and Output,” \ r is a carriage-return character. This conversion
character moves the cursor to the beginning of the current line,
enabling the program to print blanks on that same line. This process
overwrites the error message and it appears as though the error
disappears from the screen after a brief pause.
Chapter 14 ♦ Other Loop Options
/ / Fil ename: C14TI M. CPP
/ / Di spl ays an err or message f or a f ew seconds. #i ncl ude <st di o. h>
mai n( )
{
i nt out er , i nner , age;
pr i ntf (“ What i s your age? “) ; scanf (“ %d” , &age) ;
whil e ( age <= 0)
{ pr i ntf (“ *** Your age cannot be t hat small ! ***”) ;
/ / Ti mi ng l oop her e
f or ( out er =1; out er <=30000; out er ++)
{ f or ( i nner =1; i nner <=500; i nner ++) ; }
/ / Er ase t he message pr i ntf (“ \ r \ n\ n”) ;
pr i ntf (“ What i s your age? “) ;
scanf (“ %d” , &age) ; / / Ask agai n
}
pr i ntf (“ \ n\ nThanks, I di d not t hi nk you woul d act uall y t ell ”) ; pr i ntf (“ me your age! ”) ;
r et ur n 0;
}
The br eak and f or Statement s
The f or loop was designed to execute for a specified number of times. On rare occasions, you might want the f or loop to quit before
EXAMPLE
the counting variable has reached its final value. As with whil e loops, you use the br eak statement to quit a f or loop early.
The br eak statement is nested in the body of the f or loop. Programmers rarely put br eak on a line by itself, and it almost always comes after an i f test. If the br eak were on a line by itself, the loop would always quit early, defeating the purpose of the f or loop.
Examples
- The following
program shows what can happen when C++ encounters an unconditional br eak statement (one not pre- ceeded by an i f statement).
Identify the program and include the input/output header files. You need a variable to hold the current number, so make num an integer variable. Print a “Here are the numbers” message.
-
Make num equal to 1. If num *is less than or equal to 20, add
one to it each time through the loop.*
-
Print the value of num*.*
-
Break out of the loop. Print a goodbye message.
/ / Fil ename: C14BRAK1. CPP
/ / A f or l oop def eat ed by t he br eak st at ement. #i ncl ude <i ost r eam. h>
mai n( )
{
i nt num;
cout << “ Her e ar e t he number s f r om 1 t o 20\ n” ; f or( num=1; num<=20; num++)
{ cout << num << “ \ n” ;
br eak; } / / Thi s li ne exi t s t he f or l oop i mmedi at el y.
cout << “ That ’ s all , f ol ks! ” ; r et ur n 0;
}
Chapter 14 ♦ Other Loop Options
The following shows you the result of running this program. Notice the br eak immediately terminates the f or loop. The f or loop might as well not be in this program.
Her e ar e t he number s f r om 1 t o 20 1
That ’ s all , f ol ks!
- The following program is an improved version of the pre- ceding
example. It asks users if they want to see another number. If they do, the f or loop continues its next iteration. If they don’t, the br eak statement terminates the f or loop.
/ / Fil ename: C14BRAK2. CPP
/ / A f or l oop r unni ng at t he user ’ s r equest. #i ncl ude <i ost r eam. h>
mai n( )
{
i nt num; / / Loop count er var i abl e char ans;
cout << “ Her e ar e t he number s f r om 1 t o 20\ n” ; f or ( num=1; num<=20; num++)
{ cout << num << “ \ n” ;
cout << “ Do you want t o see anot her ( Y/ N) ? “ ; ci n >> ans;
i f (( ans == ‘ N’ ) | | ( ans == ‘ n’ ))
{ br eak; } / / Will exi t t he f or l oop
/ / i f user want s t o.
}
cout << “ \ nThat ’ s all , f ol ks!\ n” ; r et ur n 0;
}
The following display shows a sample run of this program. The f or loop prints 20 numbers, as long as the user does not answer N to the prompt. Otherwise, the br eak terminates the f or loop early. The statement after the body of the loop always executes next if the br eak occurs.
EXAMPLE
Her e ar e t he number s f r om 1 t o 20 1
Do you want t o see anot her ( Y/ N) ? Y 2
Do you want t o see anot her ( Y/ N) ? Y 3
Do you want t o see anot her ( Y/ N) ? Y 4
Do you want t o see anot her ( Y/ N) ? Y 5
Do you want t o see anot her ( Y/ N) ? Y 6
Do you want t o see anot her ( Y/ N) ? Y 7
Do you want t o see anot her ( Y/ N) ? Y 8
Do you want t o see anot her ( Y/ N) ? Y 9
Do you want t o see anot her ( Y/ N) ? Y 10
Do you want t o see anot her ( Y/ N) ? N
That ’ s all , f ol ks!
If you nest one loop inside another, the br eak terminates the “most active” loop (the innermost loop in which the br eak statement resides).
- Use
the conditional br eak (an i f statement followed by a br eak ) when you are missing data. For example, when you process data files or large amounts of user data-entry, you might expect 100 input numbers and receive only 95. You can use a br eak to terminate the f or loop before it iterates the 96th time.
Suppose the teacher that used the grade-averaging program in the preceding chapter (C13FOR4.CPP) entered an incor- rect total number of students. Maybe she typed 16, but there are only 14 students. The previous f or loop looped 16 times, no matter how many students there are, because it relies on the teacher’s count.
Chapter 14 ♦ Other Loop Options
The following grade averaging program is more sophisti- cated than the last one. It asks the teacher for the total num- ber of students, but if the teacher wants, she can enter –99 as a student’s score. The –99 is not averaged; it is used as a trigger value to break out of the f or loop before its normal conclusion.
/ / Fil ename: C14BRAK3. CPP
/ / Comput es a gr ade aver age wi t h a f or l oop,
/ / all owi ng an ear l y exi t wi t h a br eak st at ement. #i ncl ude <i ost r eam. h>
#i ncl ude <i omani p. h> mai n( )
{
f l oat gr ade, avg; f l oat t ot al =0. 0;
i nt num, count =0; / / Tot al number of gr ades and count er i nt l oopvar ; / / Used t o cont r ol f or l oop
cout << “ \ n*** Gr ade Cal cul at i on *** \ n\ n” ; / / Ti t l e cout << “ How many st udent s ar e t her e? “ ;
ci n >> num; / / Get t ot al number t o ent er .
f or ( l oopvar =1; l oopvar <=num; l oopvar ++)
{ cout << “ \ nWhat i s t he next st udent ’ s “ << “ gr ade? (- 99 t o qui t ) “ ;
ci n >> gr ade;
i f ( gr ade < 0. 0) / / A negat i ve number
/ / t r i gger s br eak.
{ br eak; } / / Leave t he l oop ear l y. count ++;
t ot al += gr ade; } / / Keep a r unni ng t ot al .
avg = t ot al / count;
cout << “ \ n\ nThe aver age of t hi s cl ass i s “ << set pr eci si on( 1) << avg;
r et ur n 0;
}
Notice that gr ade is tested for less than 0, not –99.0. You cannot reliably use floating-point values to compare for
EXAMPLE
equality (due to their bit-level representations). Because no grade is negative, any negative number triggers the br eak statement. The following shows how this program works.
*** Gr ade Cal cul at i on ***
How many st udent s ar e t her e? 10
What |
i s |
t he |
next |
st udent ’ s |
gr ade? |
(- 99 |
t o |
qui t ) |
87 |
---|---|---|---|---|---|---|---|---|---|
What |
i s |
t he |
next |
st udent ’ s |
gr ade? |
(- 99 |
t o |
qui t ) |
97 |
What |
i s |
t he |
next |
st udent ’ s |
gr ade? |
(- 99 |
t o |
qui t ) |
67 |
What |
i s |
t he |
next |
st udent ’ s |
gr ade? |
(- 99 |
t o |
qui t ) |
89 |
What |
i s |
t he |
next |
st udent ’ s |
gr ade? |
(- 99 |
t o |
qui t ) |
94 |
What |
i s |
t he |
next |
st udent ’ s |
gr ade? |
(- 99 |
t o |
qui t ) |
- 99 |
The aver age of t hi s cl ass i s: 86. 8
Thecont i nue statement causes C++ to skip all remaining state- ments in a loop.
The cont i nue Statemen t
The br eak statement exits a loop early, but the cont i nue state- ment forces the computer to perform another iteration of the loop. If you put a cont i nue statement in the body of a f or or a whil e loop, the computer ignores any statement in the loop that follows cont i nue .
The format of cont i nue is
cont i nue;
You use the cont i nue statement when data in the body of the loop is bad, out of bounds, or unexpected. Instead of acting on the bad data, you might want to go back to the top of the loop and try another data value. The following examples help illustrate the use of the cont i nue statement.
Chapter 14 ♦ Other Loop Options
Figure 14.1 shows the difference between the br eak and cont i nue
statements.
Figure 14.1. The difference between br eak and cont i nue .
Examples
- Although
the following program seems to print the numbers 1 through 10, each followed by “C++ Programming,” it does not. The cont i nue in the body of the f or loop causes an early finish to the loop. The first cout in the f or loop executes, but the second does not—due to the cont i nue .
EXAMPLE
/ / Fil ename: C14CON1. CPP
/ / Demonst r at es t he use of t he cont i nue st at ement. #i ncl ude <i ost r eam. h>
mai n( )
{
i nt ct r ;
f or ( ct r =1; ct r <=10; ct r ++) / / Loop 10 t i mes.
{ cout << ct r << “ “ ;
cont i nue; / / Causes body t o end ear l y. cout << “ C++ Pr ogr ammi ng\ n” ;
}
r et ur n 0;
}
This program produces the following output:
1 2 3 4 5 6 7 8 9 10
On some compilers, you receive a warning message when you compile this type of program. The compiler recognizes that the second cout is unreachable code—it never executes due to the cont i nue statement.
Because of this fact, most programs do not use a cont i nue , except after an i f statement. This makes it a conditional
cont i nue statement, which is more useful. The following two examples demonstrate the conditional use of cont i nue .
- This
program asks users for five lowercase letters, one at a time, and prints their uppercase equivalents. It uses the ASCII table (see Appendix C, “ASCII Table”) to ensure that users type lowercase letters. (These are the letters whose ASCII numbers range from 97 to 122.) If users do not type a lowercase letter, the program ignores the mistake with the cont i nue statement.
/ / Fil ename: C14CON2. CPP
/ / Pr i nt s upper case equi val ent s of f i ve l ower case l ett er s. #i ncl ude <i ost r eam. h>
mai n( )
Chapter 14 ♦ Other Loop Options
{
char l ett er ; i nt ct r ;
f or ( ct r =1; ct r <=5; ct r ++)
{ cout << “ Pl ease ent er a l ower case l ett er “ ; ci n >> l ett er ;
i f (( l ett er < 97) | | ( l ett er > 122)) / / See i f
/ / out - of -r ange.
{ cont i nue; } / / Go get anot her l ett er - = 32; / / Subt r act 32 f r om ASCI I val ue.
/ / t o get upper case. cout << “ The upper case equi val ent i s “ <<
l ett er << “ \ n” ;
}
r et ur n 0;
}
Due to the cont i nue statement, only lowercase letters are converted to uppercase.
- Suppose
you want to average the salaries of employees in your company who make over $10,000 a year, but you have only their monthly gross pay figures. The following program might be useful. It prompts for each monthly employee salary, annualizes it (multiplying by 12), and computes an average. The cont i nue statement ensures that salaries less than or equal to $10,000 are ignored in the average calcu- lation. It enables the other salaries to “fall through.”
If you enter - 1 as a monthly salary, the program quits and prints the result of the average.
/ / Fil ename: C14CON3. CPP
/ / Aver age sal ar i es over $10, 000 #i ncl ude <i ost r eam. h>
#i ncl ude <i omani p. h> mai n( )
{
f l oat mont h, year ; / / Mont hl y and year l y sal ar i es f l oat avg=0. 0, t ot al =0. 0;
i nt count =0;
EXAMPLE
do
{ cout << “ What i s t he next mont hl y sal ar y (- 1) “ << “ t o qui t ) ? “ ;
ci n >> mont h;
i f (( year =mont h* 12. 00) <= 10000. 00) / / Do not add
{ cont i nue; } / / l ow sal ar i es. i f ( mont h < 0. 0)
{ br eak; } / / Qui t i f user ent er ed - 1. count ++; / / Add 1 t o vali d count er . t ot al += year ; / / Add year l y sal ar y t o t ot al .
} whil e ( mont h > 0. 0) ;
avg = t ot al / ( f l oat ) count ; / / Comput e aver age. cout << “ \ n\ nThe aver age of hi gh sal ar i es “ <<
“ i s $” << set pr eci si on( 2) << avg;
r et ur n 0;
}
Notice this program uses both a cont i nue and a br eak state- ment. The program does one of three things, depending on each user’s input. It adds to the total, continues another iteration if the salary is too low, or exits the whil e loop (and the average calculation) if the user types a - 1 .
The following display is the output from this program:
What | i s |
t he |
next |
mont hl y |
sal ar y |
(- 1 |
t o |
qui t ) ? |
500. 00 |
---|---|---|---|---|---|---|---|---|---|
What | i s |
t he |
next |
mont hl y |
sal ar y |
(- 1 |
t o |
qui t ) ? |
2000. 00 |
What | i s |
t he |
next |
mont hl y |
sal ar y |
(- 1 |
t o |
qui t ) ? |
750. 00 |
What | i s |
t he |
next |
mont hl y |
sal ar y |
(- 1 |
t o |
qui t ) ? |
4000. 00 |
What | i s |
t he |
next |
mont hl y |
sal ar y |
(- 1 |
t o |
qui t ) ? |
5000. 00 |
What | i s |
t he |
next |
mont hl y |
sal ar y |
(- 1 |
t o |
qui t ) ? |
1200. 00 |
What | i s |
t he |
next |
mont hl y |
sal ar y |
(- 1 |
t o |
qui t ) ? |
- 1 |
The aver age of hi gh sal ar i es i s $36600. 00
Chapter 14 ♦ Other Loop Options
Review Question s
The answers to the review questions are in Appendix B.
-
For
what do you use timing loops?
-
Why do timing loop ranges have to be adjusted for different types of
computers?
-
Why do cont i nue and br eak statements rarely appear without an i f
statement controlling them?
-
What
is the output from the following section of code?
f or ( i =1; i <=10; i ++)
{ cont i nue;
cout << “ ***** \ n” ;
}
- What is the output from the following section of code?
f or ( i =1; i <=10; i ++)
{ cout << “ ***** \ n” ; br eak;
}
- To perform a long timing loop, why do you generally have to use a
nested loop?
Review Exercise s
-
Write a
program that prints C++ i s f un on-screen for ten seconds. (Hint: You might have to adjust the timing loop.)
-
Make the program in Exercise 1 flash the message C++ i s f un for
ten seconds. (Hint: You might have to use several timing loops.)
-
Write a grade averaging program for a class of 20 students. Ignore
any grade less than 0 and continue until all 20 student grades are entered, or until the user types –99 to end the program early.
EXAMPLE
- Write
a program that prints the numerals from 1 to 14 in one column. To the right of the even numbers, print each number’s square. To the right of the odd numbers, print each number’s cube (the number raised to its third power).
Summary
In this chapter, you learned several additional ways to use and modify your program’s loops. By adding timing loops, cont i nue statements, and br eak statements, you can better control how each loop behaves. Being able to exit early (with the br eak statement) or continue the next loop iteration early (with the cont i nue statement) gives you more freedom when processing different types of data.
The next chapter (Chapter 15, “The swi t ch and got o State- ments”) shows you a construct of C++ that does not loop, but relies on the br eak statement to work properly. This is the swi t ch statement, and it makes your program choices much easier to write.
The swi t ch and
got o Statements
This chapter focuses on the swi t ch statement. It also improves the i f and el se- i f constructs by streamlining the multiple-choice deci- sions your programs make. The swi t ch statement does not replace the i f statement, but it is better to use swi t ch when your programs must perform one of many different actions.
The swi t ch and br eak statements work together. Almost every swi t ch statement you use includes at least one br eak statement in the body of the swi t ch . To conclude this chapter—and this section of the book on C++ constructs—you learn the got o statement, although it is rarely used.
This chapter introduces the following:
-
The swi t ch
statement used for selection
-
The got o statement used for branching from one part of your program
to another
If you have mastered the i f statement, you should have little trouble with the concepts presented here. By learning the swi t ch statement, you should be able to write menus and multiple-choice data-entry programs with ease.
Chapter 15 ♦ The switch and goto Statements
Use theswi t ch
The swi t ch Statemen t
The swi t ch statement is sometimes called the multiple-choice
statement when your program makes a multiple-choice selection.
statement. The swi t ch statement enables your program to choose from several alternatives. The format of the swi t ch statement is a little longer than the format of other statements you have seen. Here is the swi t ch statement:
swi t ch ( expr essi on )
{ case ( expr essi on1 ) : { one or mor e C++ st at ement s ; } case ( expr essi on2 ) : { one or mor e C++ st at ement s ; } case ( expr essi on3 ) : { one or mor e C++ st at ement s ; }
.
.
.
def aul t : { one or mor e C++ st at ement s ; }
}
The expr essi on can be an integer expression, a character, a
literal, or a variable. The subexpressions (expr essi on1 , expr essi on2 , and so on) can be any other integer expression, character, literal, or variable. The number of case expressions following the swi t ch line is determined by your application. The one or mor e C++ statement s is any block of C++ code. If the block is only one statement long, you do not need the braces, but they are recommended.
The def aul t line is optional; most (but not all) swi t ch statements include the default. The def aul t line does not have to be the last line of the swi t ch body.
If expr essi on matches expr essi on1 , the statements to the right of expr essi on1 execute. If expr essi on matches expr essi on2 , the statements to the right of expr essi on2 execute. If none of the expressions match the s wi t c h expr essi on , the default case block executes. The case expression does not need parentheses, but the parentheses some- times make the value easier to find.
EXAMPLE
Using the swi t ch statement is easier than its format might lead you to believe. Anywhere an i f - el se- i f combination of statements can go, you can usually put a clearer swi t ch statement. The swi t ch statement is much easier to follow than an i f -in-an-i f -in-an-i f statement, as you have had to write previously.
However, the i f and el se- i f combinations of statements are not difficult to follow. When the relational test that determines the choice is complex and contains many && and || operators, the i f statement might be a better candidate. The swi t ch statement is preferred whenever multiple-choice possibilities are based on a single literal, variable, or expression.
The following examples clarify the swi t ch statement. They compare the swi t ch statement to i f statements to help you see the difference.
Examples
- Suppose
you are writing a program to teach your child how to count. Your program will ask the child for a number. It then beeps (rings the computer’s alarm bell) as many times as necessary to match that number.
The following program assumes the child presses a number key from 1 to 5. This program uses the i f - el se- i f combina- tion to accomplish this counting-and-beeping teaching method.
Identify the program and include the necessary header file. You want to sound a beep and move the cursor to the next line, so define a global variable called BEEP that does this. You need a variable to hold the user’s answer, so make num an integer variable.
Ask the user for a number. Assign the user’s number to num*. If* num *is 1, call* BEEP *once. If* num *is 2, call* BEEP *twice. If* num *is 3, call* BEEP *three times. If* num *is 4, call* BEEP *four times. If* num *is 5, call* BEEP *five times.*
Chapter 15 ♦ The switch and goto Statements
/ / Fil ename: C15BEEP1. CPP
/ / Beeps a desi gnat ed number of t i mes. #i ncl ude <i ost r eam. h>
/ / Def i ne a beep cout t o save r epeat i ng pr i ntf () s
/ / t hr oughout t he pr ogr am. #def i ne BEEP cout << “ \ a \ n” mai n( )
{
i nt num;
/ / Request a number f r om t he chil d
/ / ( you mi ght have t o hel p) .
cout << “ Pl ease ent er a number “ ; ci n >> num;
/ / Use mul t i pl e i f st at ement s t o beep. i f ( num == 1)
{ BEEP; }
el se i f ( num == 2)
{ BEEP; BEEP; }
el se i f ( num == 3)
{ BEEP; BEEP; BEEP; }
el se i f ( num == 4)
{ BEEP; BEEP; BEEP; BEEP; }
el se i f ( num == 5)
{ BEEP; BEEP; BEEP; BEEP; BEEP; }
r et ur n 0;
}
No beeps are sounded if the child enters something other than 1 through 5. This program takes advantage of the #def i ne preprocessor directive to define a shortcut to an
alarm cout function. In this case, the BEEP is a little clearer to read, as long as you remember that BEEP is not a command, but is replaced with the cout everywhere it appears.
One drawback to this type of i f -in-an-i f program is its readability. By the time you indent the body of each i f and el se , the program is too far to the right. There is no room for more than five or six possibilities. More importantly, this
EXAMPLE
type of logic is difficult to follow. Because it involves a multiple-choice selection, a swi t ch statement is much better to use, as you can see with the following, improved version.
/ / Fil ename: C15BEEP2. CPP
/ / Beeps a cer t ai n number of t i mes usi ng a swi t ch. #i ncl ude <i ost r eam. h>
/ / Def i ne a beep cout t o save r epeat i ng cout s
/ / t hr oughout t he pr ogr am. #def i ne BEEP cout << “ \ a \ n” mai n( )
{
i nt num;
/ / Request f r om t he chil d ( you mi ght have t o hel p) . cout << “ Pl ease ent er a number “ ;
ci n >> num;
swi t ch ( num)
{ case ( 1) : { BEEP;
br eak; } case ( 2) : { BEEP; BEEP;
br eak; }
case ( 3) : { BEEP; BEEP; BEEP;
br eak; }
case ( 4) : { BEEP; BEEP; BEEP; BEEP;
br eak; }
case ( 5) : { BEEP; BEEP; BEEP; BEEP; BEEP;
br eak; }
}
r et ur n 0;
}
This example is much clearer than the previous one. The value of num controls the execution—only the case that matches num executes. The indention helps separate each case .
If the child enters a number other than 1 through 5, no beeps are sounded because there is no case expression to match any other value and there is no default case .
Chapter 15 ♦ The switch and goto Statements
Because the BEEP preprocessor directive is so short, you can put more than one on a single line. This is not a requirement, however. The block of statements following a case can also be more than one statement long.
If more than one case expression is the same, only the first expression executes.
- If the child does not enter a 1, 2, 3, 4, or 5, nothing happens in
the previous program. What follows is the same program modified to take advantage of the def aul t option. The def aul t block of statements executes if none of the previous case s match.
/ / Fil ename: C15BEEP3. CPP
/ / Beeps a desi gnat ed number of t i mes usi ng a swi t ch. #i ncl ude <i ost r eam. h>
/ / Def i ne a beep cout t o save r epeat i ng cout s
/ / t hr oughout t he pr ogr am. #def i ne BEEP cout << “ \ a \ n” mai n( )
{
i nt num;
/ / Request a number f r om t he chil d ( you mi ght have t o hel p) . cout << “ Pl ease ent er a number “ ;
ci n >> num;
swi t ch ( num)
{ case ( 1) : { BEEP;
br eak; } case ( 2) : { BEEP; BEEP;
br eak; }
case ( 3) : { BEEP; BEEP; BEEP;
br eak; }
case ( 4) : { BEEP; BEEP; BEEP; BEEP;
br eak; }
case ( 5) : { BEEP; BEEP; BEEP; BEEP; BEEP;
br eak; }
def aul t : { cout << “ You must ent er a number f r om “ << “ 1 t o 5\ n” ;
EXAMPLE
cout << “ Pl ease r un t hi s pr ogr am agai n\ n” ; br eak; }
}
r et ur n 0;
}
The br eak at the end of the def aul t case might seem redun- dant. After all, no other case statements execute by “falling through” from the default case. It is a good habit to put a
br eak after the def aul t case anyway. If you move the def aul t higher in the swi t ch (it doesn’t have to be the last swi t ch option), you are more inclined to move the br eak with it (where it is then needed).
- To show the importance of using br eak statements in each case
expression, here is the same beeping program without any br eak statements.
/ / Fil ename: C15BEEP4. CPP
/ / I ncorr ect l y beeps usi ng a swi t ch. #i ncl ude <i ost r eam. h>
/ / Def i ne a beep pr i ntf () t o save r epeat i ng cout s
/ / t hr oughout t he pr ogr am. #def i ne BEEP cout << “ \ a \ n” mai n( )
{
i nt num;
/ / Request a number f r om t he chil d
/ / ( you mi ght have t o hel p) .
cout << “ Pl ease ent er a number “ ; ci n >> num;
swi t ch ( num) / / War ni ng!
{ case ( 1) : { BEEP; } / / Wi t hout a br eak, t hi s code case ( 2) : { BEEP; BEEP; } / / f all s t hr ough t o t he case ( 3) : { BEEP; BEEP; BEEP; } / / r est of t he beeps! case ( 4) : { BEEP; BEEP; BEEP; BEEP; }
case ( 5) : { BEEP; BEEP; BEEP; BEEP; BEEP; }
def aul t : { cout << “ You must ent er a number “ <<
“ f r om 1 t o 5\ n” ;
Chapter 15 ♦ The switch and goto Statements
cout << “ Pl ease r un t hi s pr ogr am agai n\ n” ; }
}
r et ur n 0;
}
If the user enters a 1, the program beeps 15 times! The br eak is not there to stop the execution from falling through to the other cases. Unlike other programming languages such as Pascal, C++’s swi t ch statement requires that you insert br eak statements between each case if you want only one case executed. This is not necessarily a drawback. The trade-off of having to specify br eak statements gives you more control in
how you handle specific case s, as shown in the next example.
- This
program controls the printing of end-of-day sales totals. It first asks for the day of the week. If the day is Monday through Thursday, a daily total is printed. If the day is a Friday, a weekly total and a daily total are printed. If the day happens to be the end of the month, a monthly sales total is printed as well.
In a real application, these totals would come from the disk drive rather than be assigned at the top of the program.
Also, rather than individual sales figures being printed, a full daily, weekly, and monthly report of many sales totals would probably be printed. You are on your way to learning more about expanding the power of your C++ programs. For now, concentrate on the swi t ch statement and its possibilities.
Each type of report for sales figures is handled through a hierarchy of case statements. Because the daily amount is the last case , it is the only report printed if the day of the week is Monday through Thursday. If the day of the week is Friday, the second case prints the weekly sales total and then falls through to the daily total (because Friday’s daily total must be printed as well). If it is the end of the month, the first case executes, falling through to the weekly total, then to the daily sales total as well. Other languages that do not offer this “fall through” flexibility are more limiting.
EXAMPLE
/ / Fil ename: C15SALE. CPP
/ / Pr i nt s dail y, weekl y, and mont hl y sal es t ot al s. #i ncl ude <i ost r eam. h>
#i ncl ude <st di o. h>
mai n( )
{
f l oat dail y=2343. 34; / / Lat er , t hese f i gur es
f l oat weekl y=13432. 65; / / come f r om a di sk f il e
f l oat mont hl y=43468. 97; / / i nst ead of bei ng assi gned
/ / as t hey ar e her e.
char ans;
i nt day; / / Day val ue t o t r i gger corr ect case.
/ / Mont h i s assi gned 1 t hr ough 5 ( f or Monday t hr ough
/ / Fr i day) or 6 i f i t i s t he end of t he mont h. Assume
/ / a weekl y and a dail y pr i nt s i f i t i s t he end of t he
/ / mont h, no matt er what t he day i s.
cout << “ I s t hi s t he end of t he mont h? ( Y/ N) “ ; ci n >> ans;
i f (( ans==’ Y’ ) | | ( ans==’ y’ ))
{ day=6; } / / Mont h val ue
el se
{ cout << “ What day number , 1 t hr ough 5 ( f or Mon- Fr i )” << “ i s i t ? “ ;
ci n >> day; }
swi t ch ( day)
{ case ( 6) : pr i ntf (“ The mont hl y t ot al i s %. 2f \ n” , mont hl y) ;
case ( 5) : pr i ntf (“ The weekl y t ot al i s %. 2f \ n” , weekl y) ;
def aul t : pr i ntf (“ The dail y t ot al i s %. 2f \ n” , dail y) ;
}
r et ur n 0;
}
- The order of the case statements is not fixed. You can rear- range
the statements to make them more efficient. If only one or two cases are being selected most of the time, put those cases near the top of the swi t ch statement.
Chapter 15 ♦ The switch and goto Statements
For example, in the previous program, most of the company’s reports are daily, but the daily option is third in the case statements. By rearranging the case statements so the daily report is at the top, you can speed up this program because C++ does not have to scan two case expressions that it rarely executes.
/ / Fil ename: C15DEPT1. CPP
/ / Pr i nt s message dependi ng on t he depar t ment ent er ed. #i ncl ude <i ost r eam. h>
mai n( )
{
char choi ce;
do / / Di spl ay menu and ensur e t hat user ent er s a
/ / corr ect opt i on.
{ cout << “ \ nChoose your depar t ment : \ n” ; cout << “ S - Sal es \ n” ;
cout << “ A - Account i ng \ n” ; cout << “ E - Engi neer i ng \ n” ; cout << “ P - Payr oll \ n” ;
cout << “ What i s your choi ce? “ ; ci n >> choi ce;
/ / Conver t choi ce t o upper case ( i f t hey
/ / ent er ed l ower case) wi t h t he ASCI I t abl e. i f (( choi ce>=97) && ( choi ce<=122))
{ choi ce - = 32; } / / Subt r act enough t o make
/ / upper case.
} whil e (( choi ce! =’ S’ ) &&( choi ce! =’ A’ ) &&
( choi ce! =’ E’ ) &&( choi ce! =’ P’ )) ;
/ / Put Engi neer i ng f i r st because i t occur s most oft en. swi t ch ( choi ce)
{ case ( ‘ E’ ) : { cout << “ \ n Your meet i ng i s at 2: 30” ;
br eak; }
case ( ‘ S’ ) : { cout << “ \ n Your meet i ng i s at 8: 30” ;
br eak; }
case ( ‘ A’ ) : { cout << “ \ n Your meet i ng i s at 10: 00” ;
br eak; }
case ( ‘ P’ ) : { cout << “ \ n Your meet i ng has been “ <<
“ cancel ed” ;
EXAMPLE
}
r et ur n 0;
}
br eak; }
Thegot o causes
The got o Statemen t
Early programming languages did not offer the flexible con- structs that C++ gives you, such as f or loops, whil e loops, and swi t ch statements. Their only means of looping and comparing was with the got o statement. C++ still includes a got o , but the other constructs are more powerful, flexible, and easier to follow in a program.
The got o statement causes your program to jump to a different
execution to jump to some statement other than the
next one.
location, rather than execute the next statement in sequence. The format of the got o statement is
got o st at ement l abel
A st at ement l abel is named just as variables are (see Chapter 4, “Variables and Literals”). A st at ement l abel cannot have the same name as a C++ command, a C++ function, or another variable in the program. If you use a got o statement, there must be a st at ement l abel elsewhere in the program to which the got o branches. Execution then continues at the statement with the st at ement l abel .
The st at ement l abel precedes a line of code. Follow all st at ement
l abel s with a colon (: ) so C++ recognizes them as labels, not variables. You have not seen statement labels in the C++ programs so far in this book because none of the programs needed them. A st at ement l abel is optional unless you have a got o statement.
The following four lines of code each has a different st at ement
l abel . This is not a program, but individual lines that might be included in a program. Notice that the st at ement l abel s are on the left.
pay: cout << “ Pl ace checks i n t he pr i nt er \ n” ; Agai n: ci n >> name;
EndI t : cout << “ That i s all t he pr ocessi ng. \ n” ;
CALC: amount = ( t ot al / . 5) * 1. 15;
Chapter 15 ♦ The switch and goto Statements
The statement labels are not intended to replace comments, although their names reflect the code that follows. Statement labels give got o statements a tag to go to. When your program finds the got o , it branches to the statement labeled by the st at ement l abel . The program then continues to execute sequentially until the next got o changes the order again (or until the program ends).
EXAMPLE
Examples
- The
following program has a problem that is a direct result of the got o , but it is still one of the best illustrations of the
got o statement. The program consists of an endless loop (or an infinite loop). The first three lines (after the opening brace) execute, then the got o in the fourth line causes execution to loop back to the beginning and repeat the first three lines.
The got o continues to do this until you press Ctrl-Break or ask your system administrator to cancel the program.
Identify the program and include the input/output header file. You want to print a message, but split it over three lines. You want the message to keep repeating, so label the first line, then use a got o to jump back to that line.
/ / Fil ename: C15GOTO1. CPP
/ / Pr ogr am t o show use of got o. Thi s pr ogr am ends
/ / onl y when t he user pr esses Ct r l - Br eak. #i ncl ude <i ost r eam. h>
mai n( )
{
Agai n: cout << “ Thi s message \ n” ; cout << “ \ t
keeps r epeat i ng \ n” ; cout << “ \ t \ t over and over \
n” ;
got o Agai n; / / Repeat cont i nuousl y.
r et ur n 0;
}
Notice the st at ement l abel (Agai n in the previous example) has a colon to separate it from the rest of the line, but there is not a colon with the label at the got o statement. Here is the result of running this program.
Thi s message
keeps r epeat i ng
over and over
Thi s message
keeps r epeat i ng
over and over
Chapter 15 ♦ The switch and goto Statements
Thi s message
keeps r epeat i ng
over and over
Thi s message
keeps r epeat i ng
over and over
Thi s message
keeps r epeat i ng
over and over
Thi s message
keeps r epeat i ng
over and over
Thi s message
keeps r epeat i ng
over and over
Thi s message
- It is sometimes easier to read your program’s code when you write
the statement labels on separate lines. Remember that writing maintainable programs is the goal of every good programmer. Making your programs easier to read is a prime consideration when you write them. The following program is the same repeating program shown in the previ- ous example, except the statement label is placed on a separate line.
/ / Fil ename: C15GOTO2. CPP
/ / Pr ogr am t o show use of got o. Thi s pr ogr am ends
/ / onl y when t he user pr esses Ct r l - Br eak. #i ncl ude <i ost r eam. h>
mai n( )
{
Agai n:
cout << “ Thi s message \ n” ;
cout << “ \ t keeps r epeat i ng \ n” ; cout << “ \ t \ t over and over \ n” ;
got o Agai n; / / Repeat cont i nuousl y
r et ur n 0;
}
EXAMPLE
The line following the statement label is the one that ex- ecutes next, after control is passed (by the got o ) to the label.
Of course, these are silly examples. You probably don’t want to write programs with infinite loops. The got o is a statement best preceded with an i f ; this way the got o eventually stops branching without intervention from the user.
- The
following program is one of the worst-written programs ever! It is the epitome of spaghetti code! However, do your best to follow it and understand its output. By understand- ing the flow of this output, you can hone your understand- ing of the got o . You might also appreciate the fact that the rest of this book uses the got o only when needed to make the program clearer.
/ / Fil ename: C15GOTO3. CPP
/ / Thi s pr ogr am demonst r at es t he over use of got o. #i ncl ude <i ost r eam. h>
mai n( )
{
got o Her e;
Fi r st:
cout << “ A \ n” ; got o Fi nal ;
Ther e:
cout << “ B \ n” ; got o Fi r st;
Her e:
cout << “ C \ n” ; got o Ther e;
Fi nal :
r et ur n 0;
}
At first glance, this program appears to print the first three letters of the alphabet, but the got o statements make them print in the reverse order, C, B, A. Although the program is
Chapter 15 ♦ The switch and goto Statements
not a well-designed program, some indention of the lines without statement labels make it a little more readable. This enables you to quickly separate the statement labels from the remaining code, as you can see from the following program.
/ / Fil ename: C15GOTO4. CPP
/ / Thi s pr ogr am demonst r at es t he over use of got o. #i ncl ude <i ost r eam. h>
mai n( )
{
got o Her e;
Fi rst :
cout << “ A \ n” ; got o Fi nal ;
There:
cout << “ B \ n” ; got o Fi r st;
Her e:
cout << “ C \ n” ; got o Ther e;
Fi nal :
r et ur n 0;
}
This program’s listing is slightly easier to follow than the previous one, even though both do the same thing. The remaining programs in this book with statement labels also use such indention.
You certainly realize that this output is better produced by the following three lines.
cout << “ C \ n” ; cout << “ B \ n” ; cout << “ A \ n” ;
The got o warning is worth repeating: Use got o sparingly and only when its use makes your program more readable and maintainable. Usually, you can use much better commands.
EXAMPLE
Review Question s
The answers to the review questions are in Appendix B.
-
How
does got o change the order in which a program nor- mally executes?
-
What statement can substitute for an i f - el se- i f construct?
-
Which statement almost always ends each case statement in a swi t ch
?
-
True
or false: The order of your case statements has no bearing on the efficiency of your program.
-
Rewrite the following section of code using a swi t ch
statement.
i f ( num == 1)
{ cout << “ Al pha” ; } el se i f ( num == 2)
{ cout << “ Bet a” ; } el se i f ( num == 3)
{ cout << “ Gamma” ; } el se
{ cout << “ Ot her” ; }
- Rewrite the following program using a do- whil e loop.
Ask:
cout << “ What i s your f i r st name? “ ; ci n >> name;
i f (( name[ 0] < ‘ A’ ) | | ( name[ 0] > ‘ Z’ ))
{ got o Ask; } / / Keep aski ng unt il t he user
/ / ent er s a vali d l ett er .
Chapter 15 ♦ The switch and goto Statements
Review Exercise s
-
Write
a program using the swi t ch statement that asks users for their age, then prints a message saying “You can vote!” if they are 18, “You can adopt!” if they are 21, or “Are you really that young?” for any other age.
-
Write a menu-driven program for your local TV cable com- pany. Here
is how to assess charges: If you are within 20 miles outside the city limits, you pay $12.00 per month; 21 to 30 miles outside the city limits, you pay $23.00 per month; 31 to 50 miles outside the city limits, you pay $34.00. No one outside 50 miles receives the service. Prompt the users with a menu for their residence’s distance from the city limits.
-
Write
a program that calculates parking fees for a multilevel parking garage. Ask whether the driver is in a car or a truck. Charge the driver $2.00 for the first hour, $3.00 for the second, and $5.00 for more than 2 hours. If it is a truck, add
$1.00 to the total fee. (Hint: Use one swi t ch and one i f state- ment.)
-
Modify
the previous parking problem so the charge depends on the time of day the vehicle is parked. If the vehicle is parked before 8 a.m., charge the fees in Exercise 3. If the vehicle is parked after 8 a.m. and before 5 p.m., charge an extra usage fee of 50 cents. If the vehicle is parked after 5 p.m., deduct 50 cents from the computed price. You must prompt users for the starting time in a menu, as follows.
-
Bef or e 8 a. m.
-
Bef or e 5 p. m.
-
Aft er 5 p. m.
-
Summary
You now have seen the swi t ch statement and its options. With it, you can improve the readability of a complicated i f - el se- i f selection. The swi t ch is especially good when several outcomes are possible, based on the user’s choice.
EXAMPLE
The got o statement causes an unconditional branch, and can be difficult to follow at times. The got o statement is not used much now, and you can almost always use a better construct. However, you should be acquainted with as much C++ as possible in case you have to work on programs others have written.
This ends the section on program control. The next section introduces user-written functions. So far, you have been using C++’s built-in functions, such as st r cpy() and pr i ntf () . Now it’s time to write your own.