Вопрос

This is a function that reads an unknown number of integers from a file and calculates the average. For some reason the last element in the file is being read twice. Can someone please explain why? I know how to fix it but would like to know what goes on behind the scenes.

int total = 0, count = 0, input;
FILE *filePtr;

filePtr = fopen("file.txt", "r");
if (filePtr != NULL)
    do
    {
        fscanf(filePtr, "%d", &input);
        total = total + input;
        count++;
    } while (!feof(filePtr));

printf ("%d", total);

I fixed it by putting a second if in the loop:

    do
    {
        fscanf(filePtr, "%d", &input);
        if (!feof(filePtr))
        {
            total = total + input;
            count++;
        }
    } while (!feof(filePtr));
Это было полезно?

Решение

You're not checking that fscanf actually finds a number. The last call will fail because you're most likely just reading in the last line break in the file.

Try this:

do
{
    if (fscanf(filePtr, "%d", &input)==1) {
        total = total + input;
        count++;
    }
} while (!feof(filePtr));

EDIT: @Andrew is right — you should really check for an EOF at the top of the loop:

while (!feof(filePtr)) {
    /* ... */
}

Другие советы

It looks like you shouldn't use a do-while loop. Basically, you're reading from the file THEN checking for end of file. What if there are 0 ints? You'll try reading BEFORE you check to see if the file is at the end.

Also, you're not checking the result of fscanf. It reports if it was successful or not...

The do-while structure cause this side effect, because it first reads the data, so the condition is checked just after the code inside the loop is executed. Try to use the while structure to avoid reading the last item twice, you will no longer need to do the if test inside the loop.

while (!feof(filePtr)){
    fscanf(filePtr, "%d", &input);
    total = total + input;
    count++;
}

from feof documentation: "Notice that stream's internal position indicator may point to the end-of-file for the next operation, but still, the end-of-file indicator may not be set until an operation attempts to read at that point."

So even if you read the last int in the file the pointer indicates to EOF, but because no one attempted to read again feof does not indicate that the file end is reached.

I think that the same value is 'read twice' because the variable is not changed and it holds the same value as the last one read.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top