Difficulty: Medium
Correct Answer: Using while (!feof(fp)) is incorrect; the loop should instead test the result of fgets directly
Explanation:
Introduction / Context:
This question tests understanding of how end-of-file (EOF) is detected when reading from files in C. A frequently seen but incorrect idiom is while (!feof(fp)) { fgets(...); ... }. This pattern can lead to using invalid data or printing the last line twice. The correct way is to check the return value of the input function itself.
Given Data / Assumptions:
Concept / Approach:
The feof function only reports the end-of-file condition after an attempt has been made to read past the end of the file. In the while (!feof(fp)) pattern, the loop continues even after the last successful read. On the final iteration, fgets fails and returns NULL, but the loop body still executes and may print stale data from the previous iteration. The proper approach is to use fgets return value in the loop condition: while (fgets(str, 80, fp) != NULL) { puts(str); }.
Step-by-Step Solution:
Step 1: Start reading lines using fgets. As long as data is available, fgets returns str; when there is no more data, it returns NULL.Step 2: Note that feof(fp) does not become true until after a read attempt fails at EOF.Step 3: With the pattern while (!feof(fp)), the loop condition is checked before attempting the read, so the loop runs one extra time after the last successful read.Step 4: On this extra iteration, fgets returns NULL, but puts(str) is still called, potentially printing the last line twice or using uninitialized data.Step 5: The correct pattern is: while (fgets(str, 80, fp) != NULL) { puts(str); }, which stops as soon as no more data can be read.
Verification / Alternative check:
Many C programming references explicitly warn against the while (!feof(fp)) idiom. Sample code and best practice guides show loop conditions based on the return value of fgets, scanf, or fread. Testing the original code with a small file often reveals an extra blank line or duplicated output at the end, confirming the logical error.
Why Other Options Are Wrong:
Option B is incorrect because fgets is perfectly suitable for reading lines; there is no requirement to use scanf. Option C is wrong; fclose is necessary to release file resources properly. Option D is incorrect because the pattern shown is widely recognized as a flawed way to read until EOF.
Common Pitfalls:
A common trap is to think that feof predicts the future end-of-file condition before reading. Instead, it only reports EOF after a read fails. Another pitfall is ignoring the return value of input functions, which is the primary indicator of success or failure of the read operation. Using proper loop conditions avoids these subtle bugs.
Final Answer:
The logical error is that using while (!feof(fp)) is incorrect; the loop should test the return value of fgets instead.
Discussion & Comments