Joe Lewis
Joe Lewis

Reputation: 978

Reading a C file, read an extra line, why?

I don't know exactly why a file pointer reads an extra line from a file, specifically the last line, here is the code:

FILE *fp ;
fp = fopen ("mac_ip.txt", "r") ;
int mac;
char *ip = (char *) malloc(15);

while(!feof(fp)){
    fscanf(fp,"%i",&mac);
    fscanf(fp,"%s",ip);

    printf("MAC: %i\n",mac);
    printf("IP: %s\n",ip);  
}

and the file has exactly 20 lines, but the line 20, is printed twice.

Which is the error?

Thanks in advance.

Upvotes: 4

Views: 5257

Answers (6)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726987

feof does not "know" it's at the end of file until you try to read some more. Since fscanf tells you how many items it got, you can use this simple trick:

for(;;){
    if (fscanf(fp,"%i%s", &mac, ip) != 2) break;
    printf("MAC: %i\n",mac);
    printf("IP: %s\n",ip);  
}

Upvotes: 5

Skippy Fastol
Skippy Fastol

Reputation: 1775

Your code resembles to the following example

#include <stdio.h>

int main(void)
{
    char buffer[256];
    FILE * myfile;

    myfile = fopen("some.txt","r");

    while (!feof(myfile))
    {
        fgets(buffer,256,myfile);
        printf("%s",buffer);
    }

    fclose(myfile);

    return 0;
}

from

http://www.friedspace.com/feof.html

Upvotes: 1

wildplasser
wildplasser

Reputation: 44250

FILE *fp ;
int mac;
char ip[15];

fp = fopen ("mac_ip.txt", "r") ;
if (!fp) return;

while(1){
    if (fscanf(fp,"%i",&mac) < 1) break;
    if (fscanf(fp,"%s",ip) < 1) break;

    printf("MAC: %i\n",mac);
    printf("IP: %s\n",ip);  
}
fclose (fp);

fscanf() returns the number of assignments it mad (or -1 on eof). By using the return value, you don't need the eof() function. BTW I don't think you can read a MAC address into an int. Maybe you need to read that into a string, too ?

Explanation: feof() does not do what the OP expects. feof() should only be inspected after one of the file operations failed. In most cases you don't need feof().

Upvotes: 0

Nicolas Repiquet
Nicolas Repiquet

Reputation: 9265

You better test for fscanf return value before printing result. I bet that in the last iteration of your loop, fscanf calls fail and you print the last returned results.

Upvotes: 0

Neil Townsend
Neil Townsend

Reputation: 6084

After you have done the two reads on the twentieth line, you have got to the end of the file but the system doesn't know this. feof will only trigger when you try to get past the end of the file, not when you are exactly on it ...

Also, you may have a line-end (CR or CR-LF) on the 20th line which it will only get past with another attempted read.

The solution is to read the line in one go (there is a specific C command for this) and then parse that to get your data. If the whole-line read fails, then you've got to the end.

Upvotes: 2

svinja
svinja

Reputation: 5576

Because after reading the last two values, you still haven't hit EOF. So the loop goes on. In the next pass of the loop, fscanf actually does not read the last line for the second time like it appears, the fscanfs fail, but the printfs print out the values from the previous pass of the loop.

Upvotes: 6

Related Questions