CSC 101 Lecture Notes Week 4
Looping


Relevant Reading: Chapters 5 and 6




  1. Introduction to Program Loops

    1. Chapter 5 of the book does a good job of presenting the concepts of program loops.

    2. It explains the fundamental idea of a loop as a repetitive form of computation.

      1. The repetition can happen a certain number of times, in a counting loop.

      2. The repetition can also happen while some condition remains true, in a conditional loop.

    3. The book provides a number of useful examples for each of these looping forms.

    4. These notes will present looping concepts through a series of additional example programs.

    5. The code for all of the examples is available online, in the examples pages of the CSC 101 website --

      http://users.csc.calpoly.edu/~gfisher/classes/101/examples/week4
      


  2. Yet Further Refinement of the Stats Program.

    1. Notes 2 and 3 discussed variants of a statistics program.

    2. In all of the variants, the program could only process a fixed number of data values.

    3. Using a program loop allows the statistics program to read in an indefinite number of data values, which is a fundamental improvement to how the program operates.

    4. Here is a version of the stats program that uses a while loop.

      1. We'll walk through the program in detail during lecture.

      2. Pay particular attention to the questions at the end of the program.

      3. You should be able to answer these questions, and one or more of them might well show up on an upcoming quiz or exam.


      /****
       *
       * This program computes simple statistics for numbers read from standard
       * input.  The program first asks for the number of values that the statistics
       * will be computed for.  The program then reads in that many values.
       *
       * The statistics computed are the sum of the numbers and the arithmetic mean.
       * The results are printed to standard output, in the following form:
       *
       * Sum =
       * Mean =
       *
       * The precise formula for the mean is defined here:
       *
       *    http://www.gcseguide.co.uk/statistics_and_probability.htm
       *
       *
       * Author: Gene Fisher (gfisher@calpoly.edu)
       * Created: 14apr11
       * Last Modified: 14apr11
       *
       */
      
      #include <stdio.h>
      #include <math.h>
      
      int main () {
      
          int n;                      /* Number of values to compute stats for */
          double x;                   /* Input value read from the terminal */
          double sum;                 /* Computed sum */
          int i;                      /* Loop counter variable */
      
          /*
           * Input the number of values, and prompt for the rest of the data values.
           */
          printf("Input the number of values you want to compute stats for: ");
          scanf("%d", &n);
          printf("Input the values, separated by whitespace: ");
      
          /*
           * Initialize the sum to 0.
           */
          sum = 0;
      
          /*
           * Initialize the loop counter to the number of data points.
           */
          i = n;
      
          /*
           * Loop until all the values are read in, accumulating the sum as we go.
           * Note that the loop will not go at all if the user enters a non-positive
           * value for the number of data points.
           */
          while (i > 0) {
      
              /*
               * Input the next value.
               */
              scanf("%lf", &x);
      
              /*
               * Increment the sum.
               */
              sum = sum + x;
      
               /*
                * Decrement the loop counter, so we'll stop after n inputs.
                */
              i = i - 1;
      
          }
      
          /*
           * Output the results.
           */
           printf("Sum = %f\n", sum);
           printf("Mean = %f\n", sum / n);
      
          return 0;
      
      }
      
      /***
       *
       * QUESTIONS:
       *
       *   1. Do we really need the loop counter variable i?  Couldn't we just
       *      decrement the value of variable n to know when to stop the loop?
       *
       *   2. How come we didn't use the function version of the stats program, i.e.,
       *      the version with compute_sum and compute_mean?
       *
       *   3. Why didn't we compute the standard deviation?  What would it take to do
       *      this?
       *
       */
      

  3. Version of Stats Program that Counts Up Instead of Down
    (Three small program changes shown in red; look closely.)

    /****
     *
     * This program computes simple statistics for numbers read from standard
     * input.  The program first asks for the number of values that the statistics
     * will be computed for.  The program then reads in that many values.
     *
     * The statistics computed are the sum of the numbers and the arithmetic mean.
     * The results are printed to standard output, in the following form:
     *
     * Sum =
     * Mean =
     *
     * The precise formula for the mean is defined here:
     *
     *    http://www.gcseguide.co.uk/statistics_and_probability.htm
     *
     *
     * Author: Gene Fisher (gfisher@calpoly.edu)
     * Created: 14apr11
     * Last Modified: 14apr11
     *
     */
    
    #include <stdio.h>
    #include <math.h>
    
    int main () {
    
        int n;                      /* Number of values to compute stats for */
        double x;                   /* Input value read from the terminal */
        double sum;                 /* Computed sum */
        int i;                      /* Loop counter variable */
    
        /*
         * Input the number of values, and prompt for the rest of the data values.
         */
        printf("Input the number of values you want to compute stats for: ");
        scanf("%d", &n);
        printf("Input the values, separated by whitespace: ");
    
        /*
         * Initialize the sum to 0.
         */
        sum = 0;
    
        /*
         * Initialize the loop counter to 0.
         */
        i = 0;
    
        /*
         * Loop until all the values are read in, accumulating the sum as we go.
         * Note that the loop will not go at all if the user enters a non-positive
         * value for the number of data points.
         */
        while (i < n ) {
    
            /*
             * Input the next value.
             */
            scanf("%lf", &x);
    
            /*
             * Increment the sum.
             */
            sum = sum + x;
    
             /*
              * Increment the loop counter, so we'll stop after n inputs.
              */
            i = i + 1;
    
        }
    
        /*
         * Output the results.
         */
         printf("Sum = %f0, sum);
         printf("Mean = %f0, sum / n);
    
        return 0;
    
    }
    

  4. Program 1 Solution, with a Loop

    1. Here's a version of the solution to program 1 that uses a loop.

    2. This looping version allows a user to keep performing change transactions until the user enters a negative value for the amount of purchase.

    3. This program uses a sentinel type of loop, in contrast to the preceding program examples that use the counting type of loop.

    4. Chapter 5 of the book does a good job explaining the differences between these two different loop types.

    5. In the following program code, differences are shown red between this program and the original non-looping solution to make_change.

      /****
       *
       * This program makes change, given an amount of purchase and an amount
       * tendered.  The output is a total amount of change, followed by change in five
       * denominations of money: dollars, quarters, dimes, nickels, and pennies.  All
       * inputs and outputs are in integer cents.
       *
       * The program processes multiple transactions, until the user inputs a
       * negative value for the amount of purchase.
       *
       * Author: Gene Fisher (gfisher@calpoly.edu)
       * Created: 15apr11
       * Modified: 19apr11
       *
       */
      
      #include <stdio.h>
      
      /**
       * Return the correct number of dollars in change for the given amount of
       * cents.
       */
      int get_dollars(int cents) {
          return cents / 100;
      }
      
      /**
       * Return the correct number of quarters in change for the given amount of
       * cents.
       */
      int get_quarters(int cents) {
          return cents % 100 / 25;
      }
      
      /**
       * Return the correct number of dimes in change for the given amount of
       * cents.
       */
      int get_dimes(int cents) {
          return cents % 100 % 25 / 10;
      }
      
      /**
       * Return the correct number of nickels in change for the given amount of
       * cents.
       */
      int get_nickels(int cents) {
          return cents % 100 % 25 % 10 / 5;
      }
      
      /**
       * Return the correct number of pennies in change for the given amount of
       * cents.
       */
      int get_pennies(int cents) {
          return cents % 100 % 25 % 10 % 5;
      }
      
      int main() {
      
          /*
           * Declare program variables to hold the purchase amount, amount tendered,
           * and total amount of change.
           */
          int purchase;                       /* Amount of purchase */
          int tendered;                       /* Amount tendered */
          int change;                         /* Total change due */
      
          /*
           * Prompt the user for the amount of purchase, for the first transaction.
           */
          printf("Input the amount of the purchase, in cents (negative value quits): ");
      
          /*
           * Input the amount of the first purchase.
           */
          scanf("%d", &purchase);
      
          /*
           * Loop through transactions, while the user enters non-negative values for
           * the amount purchased.  Note that the first time through the loop, the
           * purchase amount is entered before the loop starts.  At the end of the
           * loop, the purchase amount is input again, and the loop continues.
           */
          while (purchase >= 0) {
      
              /*
               * Prompt for the amount tendered.
               */
              printf("Input the amount tendered, in cents: ");
      
              /*
               * Input the amount tendered.
               */
              scanf("%d", &tendered);
      
              /*
               * Output a blank line, for nice formatting.
               */
              printf("\n");
      
              /*
               * Compute the total amount of change due, in cents.  Assume that this
               * value is non-negative.
               */
              change = tendered - purchase;
      
              /*
               * Output the total change amount, followed by a blank line.
               */
              printf("Total change due = %d\n\n", change);
      
              /*
               * Compute and print the correct change for each denomination.
               */
              printf("Change in dollars through pennies is:\n");
              printf("    %d dollars\n", get_dollars(change));
              printf("    %d quarters\n", get_quarters(change));
              printf("    %d dimes\n", get_dimes(change));
              printf("    %d nickels\n", get_nickels(change));
              printf("    %d pennies\n", get_pennies(change));
      
              /*
               * Input the amount of purchase again.
               */
              printf("\nInput the amount of the purchase, in cents (negative value quits): ");
              scanf("%d", &purchase);
          }
      
          return 0;
      }
      

  5. Program 1 Solution, with a Loop Using a Character Sentinel

    1. Here's a version of the immediately preceding example that uses a character value for the loop sentinel, instead of a negative numeric value.

    2. As it turns out, this version is a bit tricky to get right, since the scanf gets finicky when you mix numeric and character inputs.

    3. We'll discuss this issue further in upcoming weeks.

    4. Differences are shown red between this program and the immediately preceding example.

      /****
       *
       * This program makes change, given an amount of purchase and an amount
       * tendered.  The output is a total amount of change, followed by change in five
       * denominations of money: dollars, quarters, dimes, nickels, and pennies.  All
       * inputs and outputs are in integer cents.
       *
       * The program processes multiple transactions, until the user inputs 'q' to
       * quit.
       *
       * Author: Gene Fisher (gfisher@calpoly.edu)
       * Created: 15apr11
       * Modified: 19apr11
       *
       */
      
      #include <stdio.h>
      
      /**
       * Return the correct number of dollars in change for the given amount of
       * cents.
       */
      int get_dollars(int cents) {
          return cents / 100;
      }
      
      /**
       * Return the correct number of quarters in change for the given amount of
       * cents.
       */
      int get_quarters(int cents) {
          return cents % 100 / 25;
      }
      
      /**
       * Return the correct number of dimes in change for the given amount of
       * cents.
       */
      int get_dimes(int cents) {
          return cents % 100 % 25 / 10;
      }
      
      /**
       * Return the correct number of nickels in change for the given amount of
       * cents.
       */
      int get_nickels(int cents) {
          return cents % 100 % 25 % 10 / 5;
      }
      
      /**
       * Return the correct number of pennies in change for the given amount of
       * cents.
       */
      int get_pennies(int cents) {
          return cents % 100 % 25 % 10 % 5;
      }
      
      int main() {
      
          /*
           * Declare program variables to hold the purchase amount, amount tendered,
           * and total amount of change.
           */
          int purchase;                       /* Amount of purchase */
          int tendered;                       /* Amount tendered */
          int change;                         /* Total change due */
          char quit_char = ' ';               /* Loop sentinel */
      
      
          /*
           * Loop through transactions, while the user doesn't type 'q'.  Compared to
           * make_change_with_loop.c, there is only once place in the code where the
           * purchase amount is entered -- at the top of the loop.  Think about
           * what's going on here compared to make_change_with_loop.c
           */
          while (quit_char != 'q') {
      
              /*
               * Prompt the user for the amount of purchase.
               */
              printf("Input the amount of the purchase, in cents: ");
      
              /*
               * Input the amount of purchase.
               */
              scanf("%d", &purchase);
      
              /*
               * Prompt for the amount tendered.
               */
              printf("Input the amount tendered, in cents: ");
      
              /*
               * Input the amount tendered.
               */
              scanf("%d", &tendered);
      
              /*
               * Output a blank line, for nice formatting.
               */
              printf("\n");
      
              /*
               * Compute the total amount of change due, in cents.  Assume that this
               * value is non-negative.
               */
              change = tendered - purchase;
      
              /*
               * Output the total change amount, followed by a blank line.
               */
              printf("Total change due = %d\n\n", change);
      
              /*
               * Compute and print the correct change for each denomination.
               */
              printf("Change in dollars through pennies is:\n");
              printf("    %d dollars\n", get_dollars(change));
              printf("    %d quarters\n", get_quarters(change));
              printf("    %d dimes\n", get_dimes(change));
              printf("    %d nickels\n", get_nickels(change));
              printf("    %d pennies\n", get_pennies(change));
      
              /*
               * Ask the user whether or not to quit.  Note well that the message
               * tells the user to input a non-whitespace character to continue.
               * This means that the user cannot just type the Enter key on a blank
               * line to continue, but must type some non-blank character.  It would
               * take some more work to write the program to allow a single press of
               * the Enter key to be considered an input.  This is because scanf is a
               * rather finicky function.
               */
              printf("Type 'q' to quit, any other non-whitespace character to continue: ");
      
              /*
               * Getting the following scanf to work properly is a bit tricky.  The
               * rule for the scanf %c conversion is that it does not automatically
               * skip leading whitespace.  The trouble is, the newline character that
               * the user typed to enter the most recent numeric input is still
               * sitting on the input stream.  So, the scanf format string needs to
               * have the \n before the %c, in order to tell scanf to skip the
               * lingering newline char in the input stream.  Again, scanf is quite
               * the finicky little bugger.
               */
              scanf("\n%c", &quit_char);
          }
      
          return 0;
      }
      

  6. Using for Loops

    1. Section 5.4 of the book introduces C for loops, and compares them with while loops.

    2. The following is a version of the stats program with a for loop instead of a while loop.

      1. The for loop example below is a version of the up-counting while loop above.

      2. It is important to note that the for and while versions of the program behave exactly the same.

      3. The for loop simply makes the program shorter, and for many people, a bit easier to read.

    3. Differences are shown red between this program and the up-counting while loop.

      /****
       *
       * This program computes simple statistics for numbers read from standard
       * input.  The program first asks for the number of values that the statistics
       * will be computed for.  The program then reads in that many values.
       *
       * The statistics computed are the sum of the numbers and the arithmetic mean.
       * The results are printed to standard output, in the following form:
       *
       * Sum =
       * Mean =
       *
       * The precise formula for the mean is defined here:
       *
       *    http://www.gcseguide.co.uk/statistics_and_probability.htm
       *
       *
       * Author: Gene Fisher (gfisher@calpoly.edu)
       * Created: 14apr11
       * Last Modified: 14apr11
       *
       */
      
      #include <stdio.h>
      #include <math.h>
      
      int main () {
      
          int n;                      /* Number of values to compute stats for */
          double x;                   /* Input value read from the terminal */
          double sum;                 /* Computed sum */
          int i;                      /* Loop counter variable */
      
          /*
           * Input the number of values, and prompt for the rest of the data values.
           */
          printf("Input the number of values you want to compute stats for: ");
          scanf("%d", &n);
          printf("Input the values, separated by whitespace: ");
      
          /*
           * Initialize the sum to 0.
           */
          sum = 0;
      
          /*
           * Compared to the while loop version of the program, the statement to
           * initialize the loop counter is missing here.  This is because the
           * initialization happens in for loop initialization expression, i.e., the
           * first part of the for loop heading.
           */
      
          /*
           * Loop until all the values are read in, accumulating the sum as we go.
           * Note that the loop will not go at all if the user enters a non-positive
           * value for the number of data points.
           */
          for (i = 0; i < n; i++) {
      
              /*
               * Input the next value.
               */
              scanf("%lf", &x);
      
              /*
               * Increment the sum.
               */
              sum = sum + x;
      
              /*
               * Compared to the while loop version of the program, the statement to
               * increment the loop counter is missing here.  This is because the
               * incrementing happens in for loop update expression, i.e., the third
               * part of the for loop heading.
               */
      
          }
      
          /*
           * Output the results.
           */
           printf("Sum = %f\n", sum);
           printf("Mean = %f\n", sum / n);
      
          return 0;
      
      }
      


  7. A Yet Shorter Version of the Looping Stats Program

    1. Here's one more example of the stats program that uses a shortened version of the for loop, and the += assignment operator.

    2. It is again important to note that this version of the program behaves exactly the same as the preceding for loop version, as well as the preceding up-counting while loop version.

    3. This shorter for loop version reflects a typical style of C programming, where it is common practice to make C programs as short and sweet as possible.

    4. Differences are shown red between this program and the immediately preceding example.

      /****
       *
       * This program computes simple statistics for numbers read from standard
       * input.  The program first asks for the number of values that the statistics
       * will be computed for.  The program then reads in that many values.
       *
       * The statistics computed are the sum of the numbers and the arithmetic mean.
       * The results are printed to standard output, in the following form:
       *
       * Sum =
       * Mean =
       *
       * The precise formula for the mean is defined here:
       *
       *    http://www.gcseguide.co.uk/statistics_and_probability.htm
       *
       *
       * Author: Gene Fisher (gfisher@calpoly.edu)
       * Created: 14apr11
       * Last Modified: 14apr11
       *
       */
      
      #include <stdio.h>
      #include <math.h>
      
      int main () {
      
          int n;                      /* Number of values to compute stats for */
          double x;                   /* Input value read from the terminal */
          double sum;                 /* Computed sum */
          int i;                      /* Loop counter variable */
      
          /*
           * Input the number of values, and prompt for the rest of the data values.
           */
          printf("Input the number of values you want to compute stats for: ");
          scanf("%d", &n);
          printf("Input the values, separated by whitespace: ");
      
          /*
           * Compared to the longer for loop version of the program, the statement to
           * initialize the sum is missing here.  This is because this initialization
           * happens in for loop initialization expression, by separating multiple
           * initialization expressions with commas.
           */
      
          /*
           * Compared to the while loop version of the program, the statement to
           * initialize the loop counter is missing here.  This is because the
           * initialization happens in for loop initialization expression, i.e., the
           * first part of the for loop heading.
           */
      
          /*
           * Loop until all the values are read in, accumulating the sum as we go.
           * Note that the loop will not go at all if the user enters a non-positive
           * value for the number of data points.
           */
          for (i = 0, sum = 0; i < n; i++) {
      
              /*
               * Input the next value.
               */
              scanf("%lf", &x);
      
              /*
               * Increment the sum, using the sweet little incrementing assignment
               * statement.
               */
              sum += x;
      
          }
      
          /*
           * Output the results.
           */
           printf("Sum = %f\n", sum);
           printf("Mean = %f\n", sum / n);
      
          return 0;
      
      }
      


  8. A Short and Ugly Version

    1. To illustrate the kind of C code that one may frequently see out in the world, here is a hyper-shortened version of the stats program.

    2. Yes, it does in fact behave the same as the preceding versions (as long as you compile without all of the gcc switches we're required to use in CSC 101).

    3. And it is, alas, typical of the kind of C code that's out there.

    4. HOWEVER:

      1. It certainly does not meet CSC 101 programming conventions.

      2. It sacrifices understandability for the sake of brevity.

      3. I'd rate it as pretty ugly, and it's not the kind of code you should turn in for your programs.

      #include <stdio.h>
      int main() {
          int n,i;
          double x,sum;
          printf("Input the number of values you want to compute stats for: ");
          scanf("%d",&n);
          printf("Input the values, separated by whitespace: ");
          for (i=0,sum=0; i<n && scanf("%lf",&x)!=EOF; i++,sum+=x) ;
          printf("Sum = %f\nMean = %f\n", sum, sum/n);
      }
      


  9. Highlights of Chapter 5 in the Book

    1. Sections 5.1 and 5.2

      1. Covers the basics, as in the preceding examples.

      2. Discusses different kinds of loops, including in particular these:

        1. Counting loops, as in examples II. and III

        2. Sentinel loops, as in examples IV and V.

    2. Section 5.3

      1. Covers details introduced in example II on summing values in a loop.

      2. Covers compound assignment operators, like +=.

    3. Section 5.4.

      1. Covers details introduced in example for_loops on for loops.

      2. Discusses prefix increment and prefix decrement operators.

      3. Discusses nested loops.

    4. Sections 5.5 and 5.6

      1. These sections present more details on implementation and design of loops.

      2. They have further discussion on counting and sentinel-controlled loops.

    5. Section 5.7

      1. Covers the topic of nested loops

      2. We'll see more of this in coming weeks.

    6. Section 5.8

      1. Covers the do-while statement.

      2. A do-while loop that executes its body one or more time, whereas a regular while loop executes zero or more times.

      3. Your instructor is not a huge fan of do-while loops, but feel free to use them in the appropriate circumstances.

    7. Section 5.9 presents an extended example.

    8. Section 5.10 has some tips on debugging that are potentially helpful for 101 lab 4.




index | lectures | handouts | programs | labs | examples | solutions | grades