Title: CptS 121 Fall 09 Lecture 71
1CptS 121 Fall 09 Lecture 7-1
- HK Chapter 5 More Iteration
- Lecture Outline
- Sentinel-controlled loops
- Endfile-controlled loops
- Flag-controlled loops
2Sentinel-Controlled Loops
- Often we want to continue looping until a certain
value, called a sentinel, is encountered - For example, suppose we change the requirements
of the Tollbooth application slightly - There is no maximum on the total weight of the
vehicles that cross the bridge on a given day - We will read in vehicle data interactively
- The user will tell us that there are no more
vehicles for the day by entering n when asked
whether there is another vehicle that needs to
cross (n No the sentinel value)
3Sentinel-Controlled Loop in the Tollbooth
Application
- include ltstdio.hgt
- define SENTINEL_VALUE 'n'
- define POUNDS_PER_TON 2000
-
- void main()
- int count, axles
- char continue
- double weight, tons, toll, total_tolls
- count tons total_tolls 0
- printf("Did at least one car cross the bridge?
(y/n) ") - scanf(" c ",continue) / Note blanks absorb
whitespace / - while (continue ! SENTINEL_VALUE)
- axles read_num_axles() / assume these
two functions read / - weight read_weight(infile) / prompt
user interactively / - toll compute_toll(axles,weight)
- count / Another car has crossed. /
- total_tolls toll / Another toll has been
collected. / - tons weight/2000.0 / Add weight of this
car to total/ - printf("Did another car cross the bridge?
(y/n) ")
4Sentinel-Controlled Loop in the Tollbooth
Application (cont.)
- Note that this could also be rewritten as a for
loop -
- printf("Did at least one car cross the bridge?
(y/n) ") - for (scanf(" c ",continue)
- continue ! SENTINEL
- scanf(" c ",continue))
-
- axles read_num_axles() / assume these
two functions read / - weight read_weight(infile) / prompt
user interactively / - toll compute_toll(axles,weight)
- count / Another car has crossed. /
- total_tolls toll / Another toll has been
collected. / - tons weight/2000.0 / Add weight of this
car to total/ - printf("Did another car cross the bridge?
(y/n) ") -
-
5Endfile-Controlled Loops
- Often, as in the original toll booth application,
we read input data in from a file - We want to continue processing data until there
is no more data to process - In other words, we want to continue processing
data until the end of the file is encountered - We can use the endfile-controlled loop pattern to
do this
6Endfile-Controlled Loops in the Tollbooth
Application
- For example, suppose that we change the
requirements of the tollbooth application again - We will read the input values from a text file,
as before - We will continue reading axle/weight pairs until
we reach the end of the file - We will need to redesign two functions we wrote
in class a couple of weeks ago - read_num_axles
- read_weight
- Let's look at the implementation
7Endfile-Controlled Loops (cont.)
- fscanf actually returns a value indicating the
number of items it successfully reads in - If it encounters the end of the file, it returns
as its result the value of the standard constant
EOF (which is a negative integer) - We can thus redesign read_num_axles to return EOF
if it encounters the end of the file -
- int read_num_axles(FILE infile)
- int num_axles, input_status
- input_status fscanf(infile,d,num_axles
) - if (input_status ! EOF)
- return (num_axles) else return
input_status -
8Endfile-Controlled Loops (cont.)
- For the sake of simplicity, we will assume that
data always come in pairs, so we won't check for
EOF in read_weight - Challenge question Do you see another problem
with adding EOF-checking to read_weight? Explain. - The next slide puts the solution together
-
-
9Endfile-Controlled Loops (cont.)
- include ltstdio.hgt
- define POUNDS_PER_TON 2000
-
- void main()
- int count, test_axles, axles
- double weight, tons, toll, total_tolls
- FILE infile
- infile get_and_open_file()
- count tons total_tolls 0
- test_axles read_num_axles(infile)
- while (test_axles ! EOF)
- axles test_axles / We can accept this
value as valid. / weight read_weight(infile)
/ Assume EOF won't be seen. / toll
compute_toll(axles,weight) count / Another
car has crossed. / - total_tolls toll / Another toll has been
collected. / - tons weight/2000.0 / Add weight of this
car to total/ - test_axles read_num_axles(infile) /
Prepare for next / - / iteration. /
-
-
10Flag-Controlled Loops
- In the previous examples, we have assumed that
input data are always in the proper format - When we ask for the number of axles, we will
obtain an integer (either interactively from the
user, or from the input file) - When we ask for the weight, we will obtain a
double (either interactively from the user, or
from the input file) - In the real world, this assumption is faulty
- People enter invalid data all the time
- Files contain invalid data all the time
- Flag-controlled loops ensure that valid data are
read in
11Flag-Controlled Loops (cont.)
- Recall that the fscanf function returns EOF when
the end of the file is encountered - Likewise fscanf and scanf return the value 0 when
at least one the data values it reads in could
not be converted to the specified type - For example, assume the following scanf statement
- int my_int, input_status
- printf("Please enter an integer ")
- input_status scanf("d",my_int)If the user
were to type in "wow" here, input_status would be
assigned the value 0, since "wow" cannot be
converted to an int
12Do-while Can Be Used to Implement Flag-Controlled
Loops
- The final C interative construct, the do-while
loop, can be used to trap this situation and
re-prompt the user - int my_int, input_status
- char skip_ch
- do
- printf("Please enter an integer ")
- input_status scanf("d",my_int)
- do / nested do-while skips rest of data
line / - scanf("c", skip_ch)
- while (skip_ch ! '\n')
- while (input_status 0)
- Notice that, unlike the while and for loop
constructs, the do-while loop construct is
guaranteed to execute at least once.
13You Try It
- Given this pattern, tailor interactive versions
of read_num_axles so that they only accept valid
input (an int or a double) from the user (work
with a partner for 5 minutes) -
- int read_num_axles()
- int num_axles, input_status
- / your code goes here /
-
- double read_weight()
- double weight
- int input_status
- / your code goes here /
-
-
-
14Ensuring Inputted Data is within Acceptable Range
- Now let's go one step further. Let's do a reality
check on each input value to make sure it's not
only of the correct type, but within an
acceptable range - Num_axles should be between 2 and 5 (no unicycles
allowed!) -
- int read_num_axles()
- int num_axles, input_status, input_ok
- char skip_ch
- do
- printf("Please enter the number of axles
") - input_status scanf("d",num_axles)
- input_ok (input_status ! 0 num_axles
gt 1 - num_axles lt 6) / status flag
/ - if (!input_ok)
- printf("The value you entered is
invalid.") - do / skip rest of data line /
- scanf("c", skip_ch)
- while (skip_ch ! '\n')
- while (!input_ok)
- return num_axles
-
15Ensuring Inputted Data is within Acceptable Range
(cont.)
- Now let's go one step further (cont.).
- Weight should be between 200.0 and 4000.0
-
- double read_weight()
- int input_status, input_ok
- char skip_ch
- double weight
- do
- printf("Please enter the vehicle weight
") - input_status scanf("lf",weight)
- input_ok (input_status ! 0
- weight gt 200.0
- weight lt 4000.0)
- if (!input_ok)
- printf("The value you entered is
invalid.") - do / skip rest of data line /
- scanf("c", skip_ch)
- while (skip_ch ! '\n')
- while (!input_ok)
16Next Lecture
- Functions with output parameters
- Scope