Debugging a Sentinel-Controlled Marks Average
An HSC practical group writes this C program to average marks entered by a teacher:
#include <stdio.h>
int main(void) {
int m, sum = 0, count = 0;
float avg;
printf("Enter marks (-1 to stop): ");
scanf("%d", &m);
while (m != -1) {
sum = sum + m;
count++;
scanf("%d", &m);
}
avg = sum / count;
printf("Average = %.2f\n", avg);
return 0;
}
With input 40 55 60 -1 it prints Average = 51.00, but the teacher expects 51.67. With -1 as the first input it terminates abnormally. The teacher also wants marks outside 0–100 to be rejected and not counted. The group has one lab period to fix the program and must keep the sentinel-controlled loop. No arrays are allowed.
1. Trace the program for inputs 40, 55, 60, -1. Show the values of sum, count, and avg at each stage, and explain why 51.00 is printed instead of 51.67.
Read the worked answer
Trace:
| Input | sum before | count before | Action | sum after | count after |
|---|---|---|---|---|---|
| 40 | 0 | 0 | add 40, count | 40 | 1 |
| 55 | 40 | 1 | add 55, count | 95 | 2 |
| 60 | 95 | 2 | add 60, count | 155 | 3 |
| -1 | 155 | 3 | loop ends | 155 | 3 |
Then avg = sum / count divides two int values. Integer division truncates 155 / 3 to 51 before the result is stored in the float. The printed value is therefore 51.00, not 51.67. The exact average is 51.666…, which rounds to 51.67 at two decimal places. The fix is to force floating-point division, for example avg = (float) sum / count;.
2. Identify the cause of the abnormal termination when -1 is the first input, and rewrite the input/loop section so that the sentinel stops the loop, out-of-range marks are rejected and not counted, and the average is correct. Use no arrays.
Read the worked answer
When the first input is -1, the loop body never runs, so count remains 0. The statement avg = sum / count; then divides by zero. Integer division by zero is undefined behaviour and commonly causes the program to crash.
A corrected input/loop section:
scanf("%d", &m);
while (m != -1) {
if (m >= 0 && m <= 100) {
sum = sum + m;
count++;
}
scanf("%d", &m);
}
if (count > 0)
avg = (float) sum / count;
else
avg = 0.0f;
printf("Average = %.2f\n", avg);
The if rejects invalid marks before they affect either sum or count. The count > 0 guard prevents division by zero. Casting sum to float before division preserves the fractional part.
3. The group changes only `avg = sum / count;` to `avg = (float) sum / count;`. Does this fix all three symptoms? Justify your answer.
Read the worked answer
No. It fixes only the wrong average for a non-empty valid input set, because the cast forces floating-point division. It does not fix the other two defects.
First, if the first input is -1, count is still 0, and (float) sum / count still divides by zero. The cast changes the type of the numerator, not the zero denominator. A guard such as if (count > 0) is still required.
Second, marks outside 0–100 are still added to sum and counted. For example, input 40 105 -1 would produce an average involving 105. The validation test must be added inside the loop. The cast is necessary but not sufficient.