Kerala Plus Two Computer Applications (DHSE) study materials
Kerala Plus Two Computer Applications (DHSE) study resources

Debugging a Marks-Averaging Program Before the Practical Examination

Kerala Plus Two Computer Applications (DHSE) · Put your knowledge to work in context.

All case studies

Debugging a Marks-Averaging Program Before the Practical Examination

A Plus Two student submits the following C program for the practical examination. It should read the marks of n students (n ≤ 10), print their average, and count how many scored above the average.

#include <stdio.h>
int main() {
    int n, i, sum = 0, count = 0;
    int marks[10];
    float avg;
    scanf("%d", &n);
    for (i = 1; i <= n; i++) {
        scanf("%d", &marks[i]);
        sum = sum + marks[i];
    }
    avg = sum / n;
    for (i = 1; i <= n; i++)
        if (marks[i] > avg) count++;
    printf("%f %d", avg, count);
    return 0;
}

The examiner runs it with n = 5 and the marks 45, 62, 78, 51, 70 and obtains 61.000000 3. The next candidate runs the same compiled program with n = 10 and it crashes. The examiner asks the student to justify every output value and to repair the program without changing its intended behaviour.

1. Trace the program for n = 5 and marks 45, 62, 78, 51, 70. Explain exactly why the average prints as 61.000000 instead of 61.200000, and does the count change because of this error?

Read the worked answer

Trace. Sum = 45 + 62 + 78 + 51 + 70 = 306. avg = sum / n = 306 / 5.

Why the average is truncated. Both sum and n are int, so the / operator performs integer division: the fractional part is discarded before the assignment, giving 61. Only then is 61 stored into the float variable avg, so the variable holds exactly 61.0 and %f prints 61.000000. The conversion to float happens too late; the precision was already lost. Casting either operand forces real division: avg = (float) sum / n; or avg = sum / (float) n;. Note (float)(sum / n) is still wrong - the cast would happen after the integer division.

Does the count change? In this run, no: marks above 61 are 62, 78 and 70, and marks above 61.2 are also 62, 78 and 70, so the output 3 is correct by luck. The reasoning matters: a mark exactly equal to 61 would be counted the same way in both cases, so the truncation here corrupts only the printed average. A marker looking for understanding expects the student to say that the count is coincidentally correct, not that it is guaranteed correct.

2. Explain why the program crashes when n = 10, and state the general rule about array subscripts illustrated here.

Read the worked answer

The declaration. int marks[10] creates ten elements with valid subscripts 0 to 9.

The loop. It runs i = 1 to i = n, so with n = 10 it writes marks[10] - one element past the end of the array. At the same time marks[0] is never written but is read in the second loop, so an uninitialised value takes part in the comparison.

Why writing one past the end is so dangerous in C. Unlike Java or Python, C performs no bounds checking. marks[10] overwrites whatever happens to follow the array in memory - typically another local variable or the saved return address on the stack. The result is undefined behaviour: the program may print nonsense, may appear to work, and may crash with a segmentation fault, depending on the compiler and the run. Here it crashed. That unpredictability is the point an examiner wants to hear; 'it gives a garbage value' is only one of the possible outcomes.

The rule. Array subscripts in C begin at 0 and end at size − 1. A loop over n elements must be written for (i = 0; i < n; i++), never i = 1; i <= n. The safest fix is to declare int marks[10]; and loop 0 to n−1, or to size the array n at runtime after validating n.

3. Rewrite the corrected program, and add one input-validation step that the original lacks. Explain what your validation prevents.

Read the worked answer
#include <stdio.h>
int main() {
    int n, i, sum = 0, count = 0;
    int marks[10];
    float avg;
    scanf("%d", &n);
    if (n < 1 || n > 10) {          /* validation */
        printf("n must be between 1 and 10\n");
        return 1;
    }
    for (i = 0; i < n; i++) {
        scanf("%d", &marks[i]);
        sum = sum + marks[i];
    }
    avg = (float) sum / n;          /* real division */
    for (i = 0; i < n; i++)
        if (marks[i] > avg) count++;
    printf("%.2f %d\n", avg, count);
    return 0;
}

The three repairs, and why each is needed. (1) Subscripts now run 0 to n−1, so nothing is written outside the array. (2) (float) sum / n forces floating-point division, so n = 5 with sum 306 gives 61.20. (3) %.2f prints money-like precision instead of six trailing zeros.

What the validation prevents. Without it, n = 0 makes sum / n a division by zero (undefined behaviour, usually a crash or a random value), a negative n makes the loop never execute and prints a bogus zero average, and n = 12 writes past marks[10]. Checking the range before any use of n converts all three failures into one clear message. A second, optional check - rejecting marks outside 0–100 - protects the meaning of the average, not the memory.