Programming and Software Development: Question 4
Syllabus 11.2
A self-service checkout scans the items a customer buys, one at a time. The price of each item is entered as a REAL number, and the customer finishes scanning by entering 0 instead of a price. The pseudocode below reads in each price, adds it to a running total, and counts how many items were scanned, ignoring the terminating value 0 itself.
DECLARE Price : REAL
DECLARE Total : REAL
DECLARE ItemCount : INTEGER
Total ← 0
ItemCount ← 0
REPEAT
INPUT Price
IF Price > 0
THEN
Total ← Total + Price
ItemCount ← ItemCount + 1
ENDIF
UNTIL Price = 0
OUTPUT "Number of items: ", ItemCount
OUTPUT "Total cost: ", Total
(a) The pseudocode above uses a REPEAT ... UNTIL loop rather than a WHILE ... DO loop. State
whether REPEAT ... UNTIL is a pre-condition or a post-condition loop, referring to when its
condition is tested, and explain why this makes it a sensible choice for reading in the first
price scanned by a customer who always scans at least one item. [2]
(b) A customer scans three items, entering the prices 12.50, 8.00 and 5.50 in that order, then
finishes scanning by entering 0. Trace the execution of the REPEAT ... UNTIL loop for this
customer by copying and completing a trace table showing, for each pass through the loop, the
value read into Price, whether the condition Price > 0 is true, the resulting values of
Total and ItemCount, and whether the condition Price = 0 is true. State the two values
output once the loop has finished. [4]
(c) Rewrite the loop above as an equivalent WHILE ... DO ... ENDWHILE loop that produces exactly
the same output for the same four values entered, and explain why the IF Price > 0 check used
inside the REPEAT ... UNTIL loop is no longer needed once the loop is rewritten using WHILE.
[2]
Show worked solution Hide worked solution
Worked solution
Part (a): Post-condition loops and why REPEAT suits this task
A REPEAT ... UNTIL loop is a post-condition loop: its condition (UNTIL Price = 0) is tested
after the loop body has already run, not before. This means the loop body. Here, INPUT Price
followed by the IF check. Always executes at least once, however many prices are eventually
entered. [1 mark] for correctly identifying REPEAT ... UNTIL as a post-condition loop and
stating that its condition is tested after the body runs.
This suits the self-checkout scenario well: a customer who is scanning items always has at least
one real price to enter before scanning can possibly finish, so there is no need to test any
condition before the very first price has even been read. A WHILE ... DO loop, by contrast, tests
its condition before the body runs, so it would need some value already available in Price
before the loop even starts. [1 mark] for explaining that the loop body must run at least once
regardless of the first value, matching how a WHILE loop would need a value to test before it
could even begin.
Part (b): Tracing the REPEAT… UNTIL loop
Before the loop starts, Total ← 0 and ItemCount ← 0. The loop then runs once for every value
entered, including the terminating 0:
| Pass | Price read | Price > 0 ? | Total | ItemCount | Price = 0 ? (loop test) |
|---|---|---|---|---|---|
| 1 | 12.50 | Yes | 12.50 | 1 | No. Loop repeats |
| 2 | 8.00 | Yes | 20.50 | 2 | No. Loop repeats |
| 3 | 5.50 | Yes | 26.00 | 3 | No. Loop repeats |
| 4 | 0.00 | No | 26.00 | 3 | Yes. Loop stops |
[2 marks]: [1] for correctly building up Total (12.50, 20.50, 26.00) and ItemCount (1, 2,
3) across the first three passes, [1] for correctly tracing the fourth pass, showing that
Price = 0.00 fails Price > 0 (so Total and ItemCount are unchanged) and that this same value
then makes the UNTIL Price = 0 condition true, stopping the loop.
Once the loop has finished, the two OUTPUT statements display:
Number of items: 3
Total cost: 26.00
[2 marks]: [1] for the correct item count (3), [1] for the correct total cost (26.00).
Part (c): Rewriting as an equivalent WHILE… DO loop
DECLARE Price : REAL
DECLARE Total : REAL
DECLARE ItemCount : INTEGER
Total ← 0
ItemCount ← 0
INPUT Price
WHILE Price <> 0 DO
Total ← Total + Price
ItemCount ← ItemCount + 1
INPUT Price
ENDWHILE
OUTPUT "Number of items: ", ItemCount
OUTPUT "Total cost: ", Total
Two changes are needed compared with the REPEAT ... UNTIL version: a priming INPUT Price
statement is added before the loop starts, so that WHILE Price <> 0 has a value to test on its
first pass, and a second INPUT Price is placed at the end of the loop body, so the next value
is ready to be tested the next time WHILE Price <> 0 is checked. [1 mark] for a correctly
structured WHILE ... DO ... ENDWHILE loop with both the priming read before the loop and the
repeated read at the end of the loop body.
Tracing the same four values (12.50, 8.00, 5.50, 0) confirms the loops are equivalent: the priming
read sets Price ← 12.50, and the loop body runs for Price = 12.50, then 8.00, then 5.50
(building Total to 26.00 and ItemCount to 3, exactly as in part (b)), reading 0 at the end of
the third pass through the body. On the next test, WHILE Price <> 0 is now false, since Price is
0, so the loop body does not run a fourth time. The value 0 is never added to Total and never
increments ItemCount.
This is exactly why the IF Price > 0 check inside the REPEAT ... UNTIL version is no longer
needed: in that version, the loop body always ran once for every value read, including 0, so the
IF was needed to stop the terminator being treated as a real price. In the WHILE version, the
condition is tested before the body runs, so Price = 0 is caught by WHILE Price <> 0 itself,
and the loop body, the code that adds to Total and increments ItemCount, simply never executes
for it. [1 mark] for explaining that WHILE’s pre-condition test intercepts the value 0 before
the loop body can run, making the internal IF check unnecessary.
Final answers
- (a)
REPEAT ... UNTILis a post-condition loop (tested after the body runs), which suits this task because a customer always has at least one real price to enter before scanning can finish. - (b)
Pricepasses through 12.50, 8.00, 5.50, then 0.00;Totalreaches 26.00 andItemCountreaches 3 after the third pass and are unchanged on the fourth; output isNumber of items: 3andTotal cost: 26.00. - (c) Add a priming
INPUT Pricebefore the loop and a furtherINPUT Priceat the end of the loop body; the internalIF Price > 0check is no longer needed becauseWHILE Price <> 0already tests for the terminator before the loop body runs.