CSC 101 Lecture Notes Week 4
Details of Program Input/Output;
Introduction to Looping




  1. Quiz Alert:
    1. There's a 20-minute quiz at the beginning of lecture this Wednesday.
    2. It will cover material from the first two programming assignments and Chapters 1 through 3 of the Dale textbook (not Chapter 4).
    3. It will not cover any UNIX topics or any specific topics from the Dale lab book.
    4. It is an open-book, open-note quiz.

  2. Note the following update to the class schedule and reading assignment for this week.
    1. This week we will cover part of Chapter 4 and most of Chapter 6 in the Dale textbook.
    2. The revised reading assignment for this week is as follows:
      1. Chapter 4, pages 134-152 (this covers details of program input/output.
      2. All of Chapter 6, except for the case studies (this covers looping).
  3. Some details of input with cin (pp. 134-140)
    1. The cin statement processes input based on the type of each variable in its list.
      1. Here is the table from page 135 of the book that shows exactly how input is processed:
        Data Type
        of Variable
        Value Input
        char A single character except a blank, tab, or newline
        int An integer literal constant, optionally signed
        float A floating point literal constant, in decimal or floating point notation, optionally signed
      2. When reading input, cin skips over all whitespace characters, that is blanks, tabs, and newlines.
      3. When scanning input for a particular type of data, it stops scanning when it reaches the first character that is not legal for the type of data it's looking for.
      4. E.g., if it is scanning for an integer, it stops scanning and performs the input when it encounters the first non-digit character in the input stream.
    2. The newline character (pp 136-138)
      1. The newline character is the character read by cin when the user types the Enter or Return key on the keyboard.
      2. In C++, a newline character is denoted explicitly as the character '\n'.
      3. This character may appear in output strings, and produces the same effect as an endl, e.g.,
        cout << "0
        
        has exactly the same effect as
        cout << endl;
        
    3. The reading marker (pp 136-138)
      1. When a cin statement executes, it moves an invisible reading marker along the input stream.
      2. The table in Figure 1 shows by example exactly how input processing proceeds for three sample inputs (from pp 137-138 of the book).


        Figure 1: Details of cin behavior.




    4. Reading raw character data with the cin.get function (pp 138-140)
      1. As noted above, cin skips over whitespace, and automatically reads all legal characters of each numeric input.
      2. To have fine-grain control over input, i.e., to read in whitespace characters or individual numeric digits, the cin.get function is used.
      3. Note that cin.get is called as a function, without the normal << operator used in cin.
      4. We will see examples of using cin.get in the looping examples coming up.

  4. Noninteractive input/output (pp 144-151)
    1. Up to now, all input to our C++ programs has been entered interactively by a human user typing on a terminal.
    2. C++ provides the means to read input and write output noninteractively, to and from data files.
    3. Here is a modified version of the statistics program from Week 2, where input and output are read from and written to data files:

         1  ////
         2  //
         3  // This program computes simple statistics for five real numbers input from a
         4  // data file named "stats_in.dat".  The statistics computed are the sum of the
         5  // numbers, the arithmetic mean, and the standard deviation.  The results of
         6  // the computation are output to a data file named "stats_out.dat".
         7  //
         8  // Author: Gene Fisher (gfisher@calpoly.edu)
         9  // Created: 18apr99
        10  // Last Modified: 18apr99
        11  //
        12  ////
        13
        14  #include <fstream.h>                    // File input library
        15  #include <math.h>
        16
        17  const int NUM_DATA_POINTS = 5;          // Fixed number of data points
        18
        19  int main () {
        20
        21      float i1, i2, i3, i4, i5;           // Input variables
        22      float sum;                          // Computed sum
        23      float mean;                         // Computed mean
        24      float std_dev;                      // Computed standard deviation
        25      ifstream in_file;                   // File input stream
        26      ofstream out_file;                  // File output stream
        27
        28      //
        29      // Open the input and output files, named "stats_in.dat" and
        30      // "stats_out.dat", respectively.
        31      //
        32      in_file.open("stats_in.dat");
        33      out_file.open("stats_out.dat");
        34
        35      //
        36      // Read in the five numbers from the input file.
        37      //
        38      in_file >> i1 >> i2 >> i3 >> i4 >> i5;
        39
        40      //
        41      // Compute the sum.
        42      //
        43      sum = i1 + i2 + i3 + i4 + i5;
        44
        45      //
        46      // Compute the mean.
        47      //
        48      mean = sum / NUM_DATA_POINTS;
        49
        50      //
        51      // Compute the standard deviation.
        52      //
        53      std_dev = sqrt((pow(i1 - mean, 2) +
        54                      pow(i2 - mean, 2) +
        55                      pow(i3 - mean, 2) +
        56                      pow(i4 - mean, 2) +
        57                      pow(i5 - mean, 2)) / (NUM_DATA_POINTS - 1));
        58
        59      //
        60      // Output the results to the output file.
        61      //
        62      out_file << "Sum = " << sum << ", "
        63               << "Mean = " << mean << ", "
        64               << "Standard deviation = " << std_dev
        65               << endl;
        66  }
      

    4. Observations comparing this version of the program to the original interactive version from Week 2:
      1. Lines 1-6: The top-level program description has been changed to reflect the new mode of input/output.
      2. Line 14: Instead of including the iostream library (for interactive i/o), this program includes the fstream library (for file i/o).
      3. Lines 25-26: In order to use i/o files, variables of type ifstream and ofstream must be declared to refer to the files in the program.
      4. Line 38: To input from a file, the name of the input file variable is used in place of cin.
      5. Lines 35-57: Once the input has been accepted, the computation portion of this program proceeds exactly the same as it did in the interactive version.
      6. Lines 62-65: To output to a file, the name of the output file variable is used in place of cout.

  5. Input failure (pp 151-152)
    1. C++ input processing is not particularly robust.
      1. When there are erroneous values in an input stream, either from a file or interactively, a C++ program does not normally issue an error, or even stop program execution.
      2. Rather, the program continues execution, silently ignoring all attempts to input from the stream on which the error occurred.
    2. Consider the following example (from pg 151 of the book):
         #include <iostream.h>
      
         main() {
      
             int i, j, k;                // Three input variables
      
             i = 10;  j = 20;  k = 30;
      
             cin >> i >> j >> k;
             cout << "i: " << i << "  j: " << j << "  k: " << k << endl;
      
         }
         
    3. When given the following input
         1234.56 7 89
         
      the program outputs
         i: 1234  j: 20  k: 30
         
    4. The reason is as follows:
      1. Upon encountering the '.' after the 1234 in the input, the value of 1234 is assigned to i.
      2. When the input to j is to happen next, the input marker is still at the '.' character, and since it is an invalid integer digit, the cin operation fails.
      3. At this point, the input stream is in a fail state, so that all attempts at further input will silently fail, but the program will keep running.
      4. Hence, input fails for both variables j and k, as the output results reflect.
    5. We will consider how properly to deal with such input failures in upcoming lectures.

    End of Topics Related to Program Input from Chapter 4;
    Now on to Topics of Program Looping from Chapter 6.



  6. The basic idea of a program loop (pp 253-256).
    1. A loop is a programming construct that allows a section of program code to be executed repeatedly.
      1. The primary C++ looping statement is named while.
      2. Here is the syntax:



      3. Like an if statement, the while starts with a logical condition that is checked for a value of true or false.
      4. The difference between the while and the if is that the while executes its statement zero or more times, whereas the if executes its statement zero or one time.
      5. As with the if, the body of the while can be a block, which allows multiple statements to be executed repeatedly.

  7. An initial while loop example.
    1. Given below is a modified version of the solution to programming assignment 1.
    2. In this modified version, a while loop is used to allow multiple change-making transactions to be processed, without having to rerun the program each time a new pair of purchase amount and tendered inputs are to be entered.
    3. Here is the program:

      ////
      //
      // 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 performs multiple change-making transactions by continuing to
      // accept input until the user enters zero for the amount of purchase.
      //
      // Author: Gene Fisher (gfisher@calpoly.edu)
      // Created: 21mar99
      // Modified: 2apr99
      //
      ////
      
      #include <iostream.h>
      
      int main() {
      
          //
          // Declare program variables to hold the purchase amount, amount tendered,
          // total change amount, and the amounts of each denomination of change,
          // from dollars to pennies.
          //
          int purchase;                       // Amount of purchase
          int tendered;                       // Amount tendered
          int change;                         // Total change due
          int dollars;                        // Number of dollars  in change
          int quarters;                       //   "    "  quarters "    "
          int dimes;                          //   "    "  dimes    "    "
          int nickels;                        //   "    "  nickels  "    "
          int pennies;                        //   "    "  pennies "    "
      
          //
          // Prompt for and input the amount of purchase, for the first transaction.
          //
          cout << "Input the amount of the purchase, in cents (enter 0 to stop): ";
          cin >> purchase;
      
          //
          // Continue processing transactions until a purchase amount of 0 is
          // entered.
          //
          while (purchase != 0) {
      
              //
              // Prompt for and input the amount tendered.
              //
              cout << "Input the amount tendered, in cents: ";
              cin >> tendered;
              cout << endl;
      
              //
              // 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.
              //
              cout << "Total change due = " << change << endl
                   << endl;
      
              //
              // Compute the number of dollars in change by dividing the total change
              // by 100.
              //
              dollars = change / 100;
      
              //
              // Compute the remaining amount of change by subtracting the amount of
              // change in dollars from the total change.
              //
              change = change - (dollars * 100);
      
              //
              // Proceed in the same way as for dollars with quarters, dimes,
              // nickels, and pennies.
              //
              quarters = change / 25;
              change = change - (quarters * 25);
              dimes = change / 10;
              change = change - (dimes * 10);
              nickels = change / 5;
              pennies = change - (nickels * 5);
      
              //
              // Output the results of the pieces of change computations.
              //
              cout << "Change in dollars through pennies is:" << endl
                   << "    " << dollars << " dollars" << endl
                   << "    " << quarters << " quarters" << endl
                   << "    " << dimes << " dimes" << endl
                   << "    " << nickels << " nickels" << endl
                   << "    " << pennies << " pennies" << endl << endl;
      
              //
              // Prompt for and input the amount of purchase for the next
              // transaction.
              //
              cout << "Input the amount of the purchase, in cents (enter 0 to stop): ";
              cin >> purchase;
          }
      
          return 0;
      }
      
  8. Phases of loop execution (pp. 256-257)
    1. Loop entry -- the point at which the flow of control enters the loop
    2. Iteration -- one time through the loop body
    3. Loop test -- the point at which the while expression is evaluated
    4. Loop exit -- the point at which control flow exits the loop
    5. Termination condition -- the condition within the loop that will cause the loop to exit (i.e., the loop test to become false)

  9. Major types of loops (pp. 257-265)
    1. Count-controlled
      1. Executes a specific number of times
      2. Controlled by a counting variable.
    2. Event-controlled
      1. Executes an indefinite number of times
      2. Controlled by some general computation within the loop

  10. Count-controlled loops
    1. Uses a variable called the loop control or loop counter.
    2. Here is a template for a count-controlled loop that executes 10 times:
         loop_counter = 1;                       //Initialization
         while (loop_counter <= 10) {            //Test
             .
             .                                 //Repeated body
             .
             loop_counter = loop_counter + 1;    //Test
         }
         
    3. Observations
      1. As noted in Week 3 Notes, the increment statement
           loop_counter++
           
        can be used in place of (and means exactly the same thing as) the incrementing assignment statement
           loop_counter = loop_counter + 1
           
      2. The presence of each loop component is critical for correct loop operation:
        1. If the initialization is missing or incorrect, then the loop may never be executed or execute the incorrect number of times.
        2. If the test is incorrect, the loop will not execute the number of times the programmer expects.
        3. If the increment statement is missing, and no other statement changes the value of the loop_counter, then we have an infinite loop.

  11. Event-controlled loops (pp. 259-265)
    1. There are several types of event-controlled loops that can execute an indefinite number of times.
    2. Such loops contrast to the above counter-counter loops, which execute a fixed number of times.
    3. In an event-controlled loop, some event within the loop body, say a particular user input, controls when the loop exits.

  12. Sentinel-controlled event loops (pp. 259-263)
    1. A distinguished sentinel value is used to designate the end of loop, such as the purchase price of zero in the change making example above.
    2. This sentinel value must be value that is not in the range of normal values that the loop is processing.
    3. Sometimes, there is no such value, such as in the statistics program example we've been examining in the lecture notes.
    4. In the stats program, any real number is a legal input, so there is no way to distinguish a legal input of, say zero, from a sentinel value of zero.
    5. In such cases, a separate sentinel value must be used.
    6. Here is an example of using a char variable as a sentinel in the stats program
         ////
         //
         // This program computes simple statistics for five real numbers entered from
         // the terminal.  The statistics computed are the sum of the numbers, the
         // arithmetic mean, and the standard deviation.
         //
         // At the end of one computation, the program inputs a char sentinal value.  If
         // the sentinel is 'y' (for yes) the program continues execution, otherwise it
         // stops.
         //
         // Author: Gene Fisher (gfisher@calpoly.edu)
         // Created: 23apr99
         // Last Modified: 23apr99
         //
         ////
      
         #include <iostream.h>
         #include <math.h>
      
         const int NUM_DATA_POINTS = 5;          // Fixed number of data points
      
         int main () {
      
             float i1, i2, i3, i4, i5;           // Input variables
             float sum;                          // Computed sum
             float mean;                         // Computed mean
             float std_dev;                      // Computed standard deviation
      
             char continue_loop = 'y';           // Loop sentinel
      
             //
             // Excute the loop while the sentinel says yes.
             //
             while (continue_loop == 'y') {
      
                 //
                 // Prompt and input the five numbers.
                 //
                 cout << "Enter five real numbers, separated by spaces: ";
                 cin >> i1 >> i2 >> i3 >> i4 >> i5;
      
                 //
                 // Compute the sum.
                 //
                 sum = i1 + i2 + i3 + i4 + i5;
      
                 //
                 // Compute the mean.
                 //
                 mean = sum / NUM_DATA_POINTS;
      
                 //
                 // Compute the standard deviation.
                 //
                 std_dev = sqrt((pow(i1 - mean, 2) +
                                 pow(i2 - mean, 2) +
                                 pow(i3 - mean, 2) +
                                 pow(i4 - mean, 2) +
                                 pow(i5 - mean, 2)) / (NUM_DATA_POINTS - 1));
      
                 //
                 // Output the results.
                 //
                 cout << endl
                      << "Sum = " << sum << ", "
                      << "Mean = " << mean << ", "
                      << "Standard deviation = " << std_dev << ", "
                      << endl << endl;
      
                 //
                 // Prompt for and input the sentinel value.
                 //
                 cout << "Continue? (enter y for yes, n for no): ";
                 cin >> continue_loop;
                 cout << endl;
             }
         }
         
    7. A sentinel value of type Boolean is also common, as illustrated on pp. 264-265 of the book.

  13. End-of-file-controlled loops (pp. 263-264)
    1. When reading from a file, it is often the case that the program cannot know in advance how many data items are in the file.
    2. In such cases, the file variable itself can be used to test when the end-of-file condition is reached.
    3. Specifically, a file variable value of zero signals end-of-file.
    4. Here is an example that simply reads and echos integers from an input data file.
         #include <fstream.h>
      
         int main() {
             ifstream in_file;           // Input file
             int i;                      // Integer input from the file
      
             //
             // Open the file.
             //
             in_file.open("infile.dat");
      
             //
             // Read the first item, if any.
             //
             in_file >> i;
      
             //
             // Continue reading until end-of-file is reached.
             //
             while (in_file) {
                 //
                 // Echo the most recent input.
                 //
                 cout << i << endl;
      
                 //
                 // Input the next value.
                 //
                 in_file >> i;
             }
         }
         

  14. Counting and summing (pp. 265-268)
    1. Counting and summing values are very common programming tasks.
    2. The looping stats program above computes statistics repeatedly, but only for a fixed number of values (five) in each separate computation.
    3. Here is a modified version of the stats program that reads an indefinite number of data inputs from a file.
    4. In this case, the loop controls the number of data points to be computed rather than the number of times a five-datum computation is performed.
         ////
         //
         // This program computes simple statistics for real numbers input from a data
         // file named "stats_in.dat".  The statistics computed are the number of data
         // points, the sum of the numbers, and the arithmetic mean.  The results of the
         // computation are output to the terminal.
         //
         // Author: Gene Fisher (gfisher@calpoly.edu)
         // Created: 23apr99
         // Last Modified: 23apr99
         //
         ////
      
         #include <fstream.h>                    // File input library
         #include <math.h>
      
         int main () {
      
             float i;                            // Input from file
             int num_data_points;                // Number of inputs read
             float sum;                          // Computed sum
             float mean;                         // Computed mean
             float std_dev;                      // Computed standard deviation
             ifstream in_file;                   // File input stream
             ofstream out_file;                  // File output stream
      
             //
             // Open the input file.
             //
             in_file.open("stats_in.dat");
      
             //
             // Initialize the sum and number of data points to zero.
             //
             sum = 0;
             num_data_points = 0;
      
             //
             // Read the first item, if any.
             //
             in_file >> i;
      
             //
             // Count and sum file data until end-of-file is reached.
             //
             while (in_file) {
      
                 //
                 // Increment the number of data points.
                 //
                 num_data_points = num_data_points + 1;
      
                 //
                 // Add in the input value to the running sum.
                 //
                 sum = sum + i;
      
                 //
                 // Input the next value.
                 //
                 in_file >> i;
             }
      
             //
             // Compute the mean.
             //
             mean = sum / num_data_points;
      
             //
             // If any inputs were read, output the results.
             //
             if (num_data_points != 0) {
                 cout << "Number of data points = " << num_data_points << ", "
                      << "Sum = " << sum << ", "
                      << "Mean = " << mean << ", "
                      << endl;
             }
             else {
                 cout << "The input file contained no data or was not found." << endl;
             }
         }
         

    5. Observations
      1. The number of data points has changed from a constant to a variable.
      2. The while loop tests both for failed input file opening, as well as end of file (this is a bit subtle).
      3. The sum computation is in the form of a running sum that we've seen before.
      4. The computation of the mean is outside of the loop; it would be a waste of time to have it inside the loop, given the program specification as it is.
      5. Notice that the computation for the standard deviation is gone.
        1. Why?
        2. How could we get it back?
    6. Can you find the flaw in the program?
      1. On some computers, it will go unnoticed.
      2. On other computers, it could cause a runtime warning message or even cause abnormal program termination.
      3. Hint: look for something that should happen mathematically.

  15. Loop design guidelines (pp. 273-277)

  16. Nested loops (pp. 277-283)




index | lectures | labs | handouts | assignments | solutions | grades | help