WBCHSE HS Modern Computer Application study materials
WBCHSE HS Modern Computer Application study resources

The Sports Day Average That Changes on Every Run

WBCHSE HS Modern Computer Application · Put your knowledge to work in context.

All case studies

The Sports Day Average That Changes on Every Run

A Class XII student volunteers to computerise the annual sports day scoreboard. Marks for seven events are stored in an integer array and the program must print the class average to two decimal places. The student writes:

int m[7] = {45, 62, 58, 71, 39, 66, 54}; int i, sum = 0; float avg; for (i = 0; i <= 7; i++) sum += m[i]; avg = sum / 7; printf("%.2f", avg);

The true average of the seven marks is 56.43. On the first run the program printed 59.00, on the second run 53.00, and once it stopped with a runtime error. The student's teacher also wants absentees (to be entered as −1) excluded from both the sum and the count; the student insists that simply adding −1 to the sum 'is close enough'.

1. Account for the three different behaviours (59.00, 53.00 and the runtime error) and explain why none of them can ever equal 56.43 as the code stands.

Read the worked answer

There are two independent defects, and the first one explains the instability.

Defect 1 - out-of-bounds access. The valid indices are 0–6, but i <= 7 makes the loop execute for i = 7 and read m[7]. That element does not exist, so the program reads whatever bytes follow the array: a leftover value, an adjacent variable, or memory the program may not own. This is undefined behaviour. A small garbage value raises the total (59.00), a different one lowers it (53.00), and an access into protected memory raises the runtime error. Different runs give different garbage, hence different answers.

Defect 2 - integer division. sum / 7 is evaluated in integer arithmetic because both operands are int. Even with the correct total, 395 / 7 yields 56, not 56.428…, and 56 is only converted to 56.00 when stored in avg. The two decimal places that are printed are always .00.

Correct total: 45 + 62 + 58 + 71 + 39 + 66 + 54 = 395; 395 / 7 = 56.4285…, which rounds to 56.43. The code cannot produce that because of Defect 2, and cannot produce a stable answer because of Defect 1. Both must be fixed; fixing only one still gives a wrong output.

2. Rewrite the loop and the average calculation so that the program reliably prints 56.43.

Read the worked answer
int m[7] = {45, 62, 58, 71, 39, 66, 54};
int i, sum = 0;
float avg;
for (i = 0; i < 7; i++)      /* read exactly the 7 valid elements */
    sum += m[i];
avg = (float) sum / 7;       /* force floating-point division */
printf("%.2f", avg);

Why each change matters:

  • i < 7 visits indices 0, 1, …, 6 only, so no out-of-bounds read occurs and the result is deterministic.
  • The cast (float) sum converts the numerator before the division, so the operation is floating-point division: 395.0 / 7 = 56.42857… Without the cast, sum / 7.0 (a double literal) would also work, but writing float avg = sum / 7; does not, because the integer division happens first.
  • %.2f rounds 56.42857… to two decimal places and prints 56.43.

A safer variant is to compute the count in a variable rather than hard-coding 7, so the same code survives if the number of events changes.

3. Why is 'just adding −1 to the sum' wrong for absentees? Write a version that skips −1 entries and averages only the students who actually scored.

Read the worked answer

Adding −1 corrupts the answer in two ways. First, an absentee contributed no marks, yet the total is reduced by 1, so the numerator is wrong. Second, the divisor is still 7, so the average no longer represents either 'average of those who appeared' or 'average over the class'. With two absentees the total becomes 393 and the printed average 56.14, whereas the correct figure for the five who appeared is 395 / 5 = 79.00. The error grows with every absentee, and if enough entries are −1 the average can even become negative.

int i, sum = 0, n = 0;
for (i = 0; i < 7; i++) {
    if (m[i] == -1) continue;   /* absentee: skip entirely */
    sum += m[i];
    n++;
}
if (n > 0)
    printf("%.2f", (float) sum / n);
else
    printf("No marks entered");

The counter n makes the divisor follow the data, so the meaning of the average is unambiguous. The n > 0 guard prevents division by zero if every student was absent - a case the original program would have crashed on. If the school also wants a zero-scored absentee figure, it must be computed as a separate, clearly labelled quantity rather than by silently subtracting 1.