220 likes | 433 Views
Iteration in C (II) H&K Chapter 5. Instructor – Gokcen Cilingir Cpt S 121 ( July 5, 2011) Washington State University. Counter loops revisited (1). In the previous lecture, we considered loops whose number of iterations was known at the time the loop started
E N D
Iteration in C (II)H&K Chapter 5 Instructor – GokcenCilingir Cpt S 121 (July 5, 2011) Washington State University
Counter loops revisited (1) • In the previous lecture, we considered loops whose number of iterations was known at the time the loop started • We used a temporary variable which acts as a counter for us to be able to control how many times the iteration is being performed. int counter = 0; double sum = 0.0, number = 0.0, avg = 0.0; while (counter < 10) { scanf("%lf", &number); sum += number; counter++; } avg = sum / counter;
Conditional Loops (1) • In practice, we don’t always know in advance how many times a loop will execute! • Often, the loop body contains statements that monitors the state of the process and sets up a condition to terminate the loop. Examples: • Watching out if the stopping condition of your algorithm is reached. • Monitoring for an end-of-file marker while reading and processing data from a file. • Monitoring for a user-given cue to stop getting input from the user.
Conditional Loops (2) • Consider, for example the following extension to the averaging problem: • Problem statement:Find average of arbitrary number of floating point numbers taken from the user until their sum exceeds 100. #define SUM_LIMIT 100 … int counter = 0; double sum = 0.0, number = 0.0, avg = 0.0; while (sum < SUM_LIMIT ) { scanf("%lf", &number); sum += number; counter++; } avg = sum / counter; Loop control variable
Conditional Loops (3) • A possible sequence of questions that can guide loop design, applied to previous example
Conditional Loops (4) • A possible sequence of questions that can guide loop design, applied to previous example (cont.)
Conditional Loops (5) • 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 averaging problem slightly: • There is no maximum on the accumulated sum of the given numbers • We will read in the data interactively • The user will tell us that there are no more numbers for averaging by entering ‘n’ when asked whether there is another number user needs to submit. (‘n’ = “No” the sentinel value)
Sentinel-Controlled Loops (2) #define SENTINEL_VALUE 'n' … int counter = 0; double sum = 0.0, number = 0.0, avg = 0.0; char continue; printf(“Do you want to submit numbers for averaging? (y/n)"); scanf(" %c ",&continue); // Note blanks absorb whitespace while (continue != SENTINEL_VALUE) { printf (“Please enter a number: ”) scanf("%lf", &number); sum += number; counter++; printf(“Do you want to submit another number? (y/n) "); scanf(" %c ",&continue); //Note blanks absorb whitespace } avg = sum / counter; initialization repetition/loop condition update expression
Sentinel-Controlled Loops (3) • Note that this could also be rewritten as a for loop: #define SENTINEL_VALUE 'n' … int counter = 0; double sum = 0.0, number = 0.0, avg = 0.0; char continue; printf(“Do you want to submit numbers for averaging? (y/n)"); for( scanf(" %c ",&continue); continue != SENTINEL_VALUE; scanf(" %c",&continue) ) { printf (“Please enter a number: ”) scanf("%lf", &number); sum += number; counter++; printf(“Do you want to submit another number? (y/n) "); } avg = sum / counter; initialization repetition/loop condition update expression
Sentinel-Controlled Loops (4) • Another for application to demonstrate that parts of for can be left blank with the condition of leaving semicolons that separate the parts of for: #define SENTINEL_VALUE 'n' … int counter = 0; double sum = 0.0, number = 0.0, avg = 0.0; char continue; printf(“Do you want to submit numbers for averaging? (y/n)"); scanf(" %c ",&continue); for(; continue != SENTINEL_VALUE; ) { printf (“Please enter a number: ”) scanf("%lf", &number); sum += number; counter++; printf(“Do you want to submit another number? (y/n) "); scanf(" %c",&continue) } avg = sum / counter; Notice the need for semicolons to separate parts of for even if some parts are left blank
Endfile-Controlled Loops (1) • Often, we read input data 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 end-file-controlled loop pattern to do this
Motivation example revisited • In Lab 2 Task 1, we wrote a program that does the following: • Carries out following task 10 times: • Reads a character from the input file • Prints corresponding ASCII value to the output file • Update statistics on numLines, numAlpha, and numDigits. • Prints out the final statistics to an output file int counter = 0; while (counter < 10) { • ch = read_character(infile); • ascii = determine_ascii_value(ch); • print_int(outfile_ascii, ascii); • numLines= number_lines(ch, numLines); • numDigits = number_digits(ch, numDigits); • numAlpha = number_alphas(ch, numAlpha); • counter += 1; }
Endfile-Controlled Loops (2) • Let’s change the requirements of this problem and say we want the program to process the whole file content, not just the first 10 characters. • We will continue reading and processing characters from the file until we reach the end of the file. • We will need to re-design the read_characterfunction; now it should somehow report to the caller that EOF is reached.
Endfile-Controlled Loops (3) char read_character (FILE *infile) { char ch; intinput_status; input_status = fscanf(infile, "%c", &ch); if (input_status != EOF) return ch; else return EOF; } • 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_characterto return EOF if it encounters the end of the file:
Endfile-Controlled Loops (4) … • ch = read_character(infile); while (ch != EOF) { • ascii = determine_ascii_value(ch); • print_int(outfile_ascii, ascii); • numLines= number_lines(ch, numLines); • numDigits = number_digits(ch, numDigits); • numAlpha = number_alphas(ch, numAlpha); • ch= read_character(infile); }
Flag-Controlled Loops (1) • In our previous examples, we have assumed that input data are always in the proper format: • When we ask for an integer number, we will obtain an integer (either interactively from the user, or from the input file) • When we ask for a double number, 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 • Essentially, when a loop condition becomes complex, it’s a good idea to simplify it using a flag.
Flag-Controlled Loops (2) • Recall that the fscanf function returns EOF when the end of the file is encountered • Likewise fscanf, scanf returns 0 when at least one of the data values it reads in could not be converted to the specified type • For example, assume the following scanf statement intmy_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: intmy_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) • Given this pattern, let’s tailor interactive versions of the averaging problem so that we only accept valid input (an int or a double) from the user. Let’s define read_gradefunction for this purpose assuming the numbers we’re getting are actually grades. #define SENTINEL_VALUE 'n' … int counter = 0; double sum = 0.0, number = 0.0, avg = 0.0; char continue; printf(“Do you want to submit grades for averaging? (y/n)"); scanf(" %c ",&continue); // Note blanks absorb whitespace while (continue != SENTINEL_VALUE) { number = read_grade(); sum += number; counter++; printf(“Do you want to submit another grade? (y/n) "); scanf(" %c ",&continue); //Note blanks absorb whitespace } avg = sum / counter;
Flag-Controlled Loops (5) double read_grade (void) { int number, input_status, input_ok; char skip_ch; do { printf("Please enter a grade: "); input_status = scanf("%lf",&number); input_ok = (input_status != 0 && number >= 0 && number <=100); 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 number; } • 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 [0,100] flag that controls the loop continuation condition
References • J.R. Hanly & E.B. Koffman, Problem Solving and Program Design in C (6th Ed.), Addison-Wesley, 2010 • P.J. Deitel & H.M. Deitel, C How to Program (5th Ed.), Pearson Education , Inc., 2007.