cs1ch3sec5.htm
 

CHAPTER THREE

Analysis and Design : First Steps

 


Section V: The Counter Pattern Section I : Problem Analysis Section II: Problem Analysis Section III: Patterns Section IV:The While Loop With Priming Read Pattern
Section VI: The Sum Pattern Section VII: The Average Pattern Section VIII: The Salary Problem Revisited Section IX: Taking Advantage of Patterns

  


Table of Contents

Learning C++:
An Index of Entry Points


2. The

of C++

A reference document on the basic elements of C++.



3. The Patterns



Index!



Section V. The Counter Pattern
Now suppose the manager wants to know just how many items were discounted. Again, you could physically count them or you could have the computer do the work for you. We noted above that humans do not need to be told to initialize their variables but that in certain circumstances computers do need to be told. A counter is a good example of a variable that needs to be initialized. (Actually, this does sometimes happen in the 'real world'. Imagine that you have been given one of those 'clicker counters', the kind where you push a little button every time you want to increment the counter. Imagine further that you are employed at a large discount store and told to stand in front all day using your 'clicker' to count the number of customers that enter during the day. What should you do first thing in the morning before you start counting? Reset your counter to zero, of course!)

Anyway, computer counters need to be set to zero and the counter itself needs to be incremented inside some kind of loop. Aha, another pattern! And, here it is - in its most general form.


Pattern Name: The Counter Pattern Using a Loop
    Purpose: To count the number of times a loop repeats; to implement a counter.
    Pattern: Initialize the Counter Variable to 0 Use some loop pattern - see Sections 'B' and 'C' above Inside the loop pattern add the following code: Counter Variable++

    Using this pattern we can modify the above algorithm to include a counter

      Set Item Count to 0
      Get Price
      while Price != -1
      {          Discounted Price = Price * Discount  
      	   Output Discounted Price
                 Item Count++
                 Get Price
      }
      Output Item Count
      

    There are a number of important points to pay attention to here. First, note that we are really using two patterns in this program - the "While loop with a priming read" pattern and the counter pattern. A number of the programs in chapter two, for example, ch2prg7.cpp, took advantage of these] two patterns although at the time we did not discuss it. Once you learn other looping patterns you will also be able to use them with the counter pattern. In any case, the mixing of patterns is part of the creativity of the programming process. And, the more patterns you are comfortable with, the more creative mixing you are capable of. But there are important issues in pattern mixing. For example, note how part of the counter pattern (the initialization phase) exists outside the loop while the increment phase is inside the loop. You can't just mix the elements of two patterns in any old way.

    The second point to notice about this program is the placement of :

    Output Item Count

    It must appear outside the loop or the output will be:

    1,2,3,4,........ up to the number of items in the list.

    If you do not see this, as usual, TRACE it

    And now that you are comfortable with the algorithm, here is the code:

      // A program to calculate a sale prices based 
      on a single discount percentage and count the // number of items discounted // File: ch3prg2.cpp // USE THE SPECIFICATIONS FROM THE PREVIOUS VERSION AND ADD A // DESCRIPTION OF THE COUNTER #include <iostream.h> const double DISCOUNT = .87; void main() // Purpose: to calculate sale prices based on a single discount percentage and count the // number of items discounted // Receives: NONE // Returns: NONE { double price; double discountedPrice; int itemCount = 0; cout << "Please enter an item's original price (Enter -1 to Stop) "; cin >> price; while (price != -1) { discountedPrice = price * DISCOUNT; cout << "The New Price is: $" << discountedPrice << endl; itemCount++; cout << "Please enter an item's original price (Enter -1 to Stop) "; cin >> price; } cout << itemCount; }

    One question you might have is why didn't we initialize or somehow place a value into the variable 'discountedPrice' before beginning the loop? (If you observe, it is the only variable still holding garbage at this point.) Well, suppose we had set it to 0 before the 'while' loop. Would that 0 value ever have been used? If you study a trace of this code (with this variable initialized), you will see that the answer is no! In essence the 'discountedPrice' is not used on the right side of a calculation, as part of a test, or as an output before it is calculated. This being the case, any value we initialize the variable to would be lost in the calculation

    discountedPrice = price * DISCOUNT

    before it was used. In other words, we could initialize the variable but it would be a waste of time since the initializing value would be lost.

    **********************

    Here is another example using the counter loop pattern, a code fragment that could be used to count the number of times the user chooses to enter a loop. Note that we would need to add code to replace the comment line "/* other instructions inside the loop */" before this code would do anything useful. That is why it is called a code fragment- it is only part of, a fragment of, some larger program. Try to read it without worrying about the new C++ syntax that has been included.

       int count = 0;
                cout << "Enter 'Y' if you have more to do\n";
                cout << "Enter 'N' if you are finished.\n";
                cin >> answer;
                while ((answer == 'Y') || (answer == 'y'))
               {
                    count++;
                    /* other instructions inside the loop *
                    cout << "Enter 'Y' if you have more to do\n";
                    cout << "Enter 'N' if you are finished.\n";
                    cin >> answer;
                }
      
    The counter element in this code should be familiar. We are counting the number of times the person enters the loop - where entering the loop is caused by the user entering a 'Y' to indicate that he or she has more work to do. There are, however, some new aspects to the 'while' loop. First, a simple point: Notice the '\n' symbol at the end of the 'cout' lines. This is the second way to force a line return. (The directive 'endl' is the other way.) It is useful when you want a line return in a statement that does not end with a variable being output. Note that the '\n' must be inside the double quotes.

    In this case, the '\n' improves the appearance of the prompt combined with the input. The value entered by the user appears on the next line instead of being jammed up against the last letter of the input. To experience the difference for yourself, take a program you have already written and add the '\n' to the end of your prompts.

    We could also have written these lines as:

    cout << "............................." << endl;

    Likewise a line that might be written:

    cout << "......................." << someVariable << endl;

    could also be written as:

    cout << "......................." << someVariable << "\n";

    Now study the test condition:

    while ((answer == 'Y') || (answer == 'y'))

    Notice that it is clearly more complex than something like "(price != -1)". Its purpose is to handle the fact that a user can enter either an upper case or lower case 'Y'. What the test condition is saying is: "while the character entered is either an upper case 'Y' or a lower case 'y'...." continue the loop. The two vertical parallel lines (||) are the symbol for 'OR'. It is what we call a logical operator. There are two other very useful operators of this kind: '&&' is the symbol for AND while '!' is the symbol for NOT. All three of these can be used in any 'if' or 'while' test condition.

    Their meaning is the same as in English. Therefore, "||" means that if EITHER of the individual conditions ("answer == 'Y'" or "answer == 'y'", in this code) are true, then the test as a whole is true. "&&" means that both conditions must be true - which would not make sense in this case since the memory location symbolized by 'answer' cannot contain 'Y' and 'y' at the same time. '!' means Not. In other words, if "(answer == 'Y')" is True then "!( answer == 'Y')" would be False. Note one can have multiple '||' operators in an expression, in which case, if any one of them is True, the combined expression is True. Likewise, you can have multiple '&& operators in an expression, in which case, only if all of the individual expressions is True, is the whole expression True. The issue of when and how to use and combine AND,s (&&), Or's (||) and NOT's (!)is very tricky. You should avoid mixing these unless you absolutely need to and are comfortable with logic. Chapter 6 has more discussion on how to decide when to use '&&' and when to use '||'.

    Note the extra inner set of parenthesis in the test condition. They are technically not required but they do make the code easier to read. To see why they are not needed, we need to understand that logical operators (||, &&, and !) also have precedence rules just as arithmetic operators do. As a matter of fact all operators are part of the same precedence order. Here is the precedence table for all the operators we have seen so far:

    Operator Precedence
    (Highest to Lowest)

        ( )
        ++ -- ! + - (Unary Operators)
        * /
        + -
        << >>
        < <= > >=
        == !=
        &&
        ||
        = += -+ *= /=

    Note that both "&&" and "||" occur below "==" in precedence. In other words, in a line such as:

    while ((answer == 'Y') || (answer == 'y'))

    the "==" operator (in both places) is executed before the "||" operator even without the inner set of parenthesis - which is as it needs to be for this to make sense. In other words, the system determines the truth of both equality tests and then does an OR operation. If either of the tests returns True, the whole expression is True so in this case, if 'answer' contains 'Y' or 'y' the expression is True. (If the precedence of "||" was higher than "==", this code, without the extra set of parentheses, would be asking the computer to do an OR on 'Y' and 'answer' - whatever that would mean!)

    As a separate point, note that the '+' and '-' symbols appear twice in this table: in lines 2 and 4. In line 2 the '+' and '-' refer to the unary plus and the unary minus as in +5 and -5. Unary, of course, means 1 and in these two expressions there is only one value or operand. Contrast that with "3 - 5" or "value1+value2" where the '+' and '-' operators operate on two values or operands. In this case, '+' and '-' are binary operators. This particular precedence difference is rarely an issue in C++ so you can stop worrying about it but you should understand the basic difference between unary and binary operators.

    This whole discussion was related to the Counter Pattern so a brief summary is in order.

    1. The key to this pattern is contained in the two lines:

        Initialize the Counter Variable to 0
        Counter Variable++

    2. This pattern usually is related to some loop pattern with this pattern sitting half inside and half outside the loop pattern.

    3. If you had some reason to begin your counter at some value other than zero, that would be possible simply by initializing the counter variable (itemCount in the example here) to the other value. Usually counter variables are initialized to 0. However, if, for example, you already knew that 556 items had been counted and now wanted to count the rest, you might begin the above code fragment by initializing itemCount to 556 as in:

        int itemCount = 556;

    4. If you wanted to count by some value other than one, for example, if you wanted to count by 5, you would change the line:

        count++ ; (or whatever counter variable you were using)
      to:
        count += 5; (or whatever value you wanted to count by).

    Top of Section Main Menu Next Section