Karnataka KSEAB SSLC JTS Programming in ANSI C study materials
Karnataka KSEAB SSLC JTS Programming in ANSI C study resources

The Last Record Printed Twice

Karnataka KSEAB SSLC JTS Programming in ANSI C · Put your knowledge to work in context.

All case studies

The Last Record Printed Twice

A student in Mangaluru writes a program to store five student marks in a text file. Each record is written with fprintf(fp, "%d %s\n", marks, name); and the file is opened with fopen("marks.txt", "w"). The next day the student re-runs the program and finds only the new five records, because the old ones disappeared. Reading is done with: while (!feof(fp)) { fscanf(fp, "%d %s", &marks, name); printf("%d %s\n", marks, name); } The last record is printed twice. A classmate opens the file in a text editor and sees five normal records and a final newline, but no duplicate. The student also allocates a 20-byte buffer with malloc inside the loop and never calls free. The teacher wants the file-mode, loop and memory issues separated.

1. Why did the previous day's records disappear, and what file mode should be used?

Read the worked answer

Opening with mode "w" truncates the file to zero length as soon as fopen succeeds. Re-running the program therefore destroys the previous day's records before writing the new five. This is the documented meaning of "w" - write, creating the file if needed and discarding existing contents.

Use "a" to append new records to the end of the file, or "r+"/"a+" if reading and updating are both required. If the file must be replaced, that should be an explicit decision, preferably with a backup or a temporary file and rename. The mode is the whole explanation for the vanished records; the writing code itself is fine.

2. Why is the last record printed twice even though the file contains only five records? Rewrite the loop correctly.

Read the worked answer

feof becomes true only after a read has already failed at end-of-file. When fscanf reaches EOF it returns EOF (or a short item count) and does not update marks or name, but those variables still hold the values from the previous successful read. The loop body then prints that stale record one more time. The text editor shows no duplicate because the file itself is fine - the duplicate exists only in the program's variables.

Check the conversion count instead:

while (fscanf(fp, "%d %s", &marks, name) == 2) {
    printf("%d %s\n", marks, name);
}

Here the loop stops as soon as the read fails, before printing. Checking fscanf's return value is the reliable pattern; feof is best used to distinguish EOF from a matching error after a read has failed.

3. The 20-byte buffer is allocated with malloc inside the loop and never freed. Explain the consequence and the fix.

Read the worked answer

Each malloc(20) returns a new block; without free, the program leaks 20 bytes per iteration. For five records this is harmless, but in a long-running loop, or with a larger record size, it steadily consumes memory until allocation fails. The program does not check whether malloc returned NULL, so it would then dereference a null pointer and crash.

Two fixes:

  1. Free at the end of each iteration after the buffer is no longer needed: free(name); name = NULL;.
  2. Better, allocate once outside the loop, reuse the buffer for every record, and free it after the loop. Also check the result: if (name == NULL) { /* handle */ }.

Finally, close the file with fclose(fp) on every path, including error exits, so buffered data is flushed and the file descriptor is released.