| |
Main Menu | Next Section |
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 :
It must appear outside the loop or the output will be:
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
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;
}
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:
Likewise a line that might be written:
could also be written as:
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:
Note that both "&&" and "||" occur
below "==" in precedence. In other words, in a line
such as:
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.
Initialize the Counter Variable to 0
Counter Variable++
int itemCount = 556;
| |
Main Menu | Next Section |