250 likes | 365 Views
(6-2) Iteration in C II H&K Chapter 5. Instructor - Andrew S. O’Fallon CptS 121 (October 1, 2014) Washington State University. Don’t Forget About Flowcharts!. Recall: flowcharts provide visual representations of algorithms and/or processes Excellent tool for verifying logical flow.
E N D
(6-2) Iteration in C II H&K Chapter 5 Instructor - Andrew S. O’Fallon CptS 121 (October 1, 2014) Washington State University
Don’t Forget About Flowcharts! • Recall: flowcharts provide visual representations of algorithms and/or processes • Excellent tool for verifying logical flow
General Structure of Flowchart for Loops Condition? No or F Yes or T Process body of loop
Conditional Loops (1) • In the previous lecture, we considered loops whose number of iterations was known at the time the loop started • In practice, we don’t always know in advance how many times a loop will execute! • Often, the loop body itself determines whether another execution is necessary
Conditional Loops (2) • Consider, for example, the following extension to the Tollbooth application: • Suppose that, for safety reasons, the tollbooth limits the number of vehicles that can cross the bridge on a given day to a certain tonnage. • Suppose that you want to read in vehicle data from a file to simulate cars crossing the bridge. • When the maximum tonnage has been reached, not more data are read from file.The program prints out a message reporting • the revenues collected for the day • the number and total weight of all cars that crossed for the day • See next slide for a possible solution
Conditional Loops (3) #include <stdio.h> #define MAX_TONS_PER_DAY 20 #define POUNDS_PER_TON 2000 … void main(void) { int vehicle_count, axles; double weight, tons, toll, total_tolls; FILE *infile; infile = get_and_open_file(); count = tons = total_tolls = 0; while (tons < MAX_TONS_PER_DAY) { axles = read_num_axles(infile); weight = read_weight(infile); toll = compute_toll(axles,weight); count++; /* Another car has crossed. */ tolls += toll; /* Another toll has been collected */ tons += weight/2000.0; /* Add weight of this car */ /* to running total*/ } printf("%d cars, weighing %.2f tons, crossed the bridge today.", count, tons); printf("$%.2f in tolls was collected today.",total_tolls); }
Conditional Loops (4) • A possible sequence of questions that can guide loop design, applied to previous example
Conditional Loops (5) • A possible sequence of questions that can guide loop design, applied to previous example (cont.)
Conditional Loops (6) • A possible sequence of questions that can guide loop design, applied to previous example (cont.)
Sentinel-Controlled Loops (1) • 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)
Sentinel-Controlled Loops (2) #include <stdio.h> #define SENTINEL_VALUE 'n' #define POUNDS_PER_TON 2000 … void main(void) { 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) "); scanf(" %c ",&continue); /* Note blanks absorb whitespace */ } …
Sentinel-Controlled Loops (3) • 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) "); } …
Endfile-Controlled Loops (1) • 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
Endfile-Controlled Loops (2) • 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…
Endfile-Controlled Loops (3) • 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; }
Endfile-Controlled Loops (4) • 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
Endfile-Controlled Loops (5) #include <stdio.h> #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. */ } … }
Flag-Controlled Loops (1) • 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
Flag-Controlled Loops (2) • 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
Flag-Controlled Loops (3) • 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.
Flag-Controlled Loops (4) • You 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 */ }
Flag-Controlled Loops (5) • 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 > 1 && num_axles < 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; }
Flag-Controlled Loops (6) • 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 >= 200.0 && weight <= 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); return weight; }
References • J.R. Hanly & E.B. Koffman, Problem Solving and Program Design in C (7th Ed.), Addison-Wesley, 2013 • P.J. Deitel & H.M. Deitel, C How to Program (5th Ed.), Pearson Education , Inc., 2007.
Collaborators • Chris Hundhausen