JoGe
JoGe

Reputation: 126

Strange input with fscanf

I am trying to read in a text file using fscanf. The input file looks like this:

1
Test
0
32.1

Everything is read fine except the first integer which gets read as some random value.

My code:

while((fgets(string,64,fp) != NULL)){
    fscanf(fp, "%i\n", &tid);
    fscanf(fp, "%s\n", name);
    fscanf(fp, "%d\n", &stat);
    fscanf(fp, "%f\n", &per);
    printf("%d %s %d %f", tid, name, stat, per);
    }

Output:

11281472 Test 0 32.0999982

Does anyone know what I do wrong?

Entire function for reference:

Task *readData(Task *strt, char *fname){
    #ifdef DEBUG
        fprintf(stderr, "Entered Data import method\n");
    #endif
    char name[30];
    int tid, stat;
    float per;

    FILE *fp;
    fp= fopen(fname, "r");

    if(fgetc(fp) == EOF){
        printf("File is empty");
    }
    else{
    while(!feof(fp)){

        fscanf(fp, "%i\n", &tid);
        fscanf(fp, "%s\n", name);
        fscanf(fp, "%d\n", &stat);
        fscanf(fp, "%f\n", &per);
        printf("%d %s %d %f", tid, name, stat, per);
        strt = AddB(strt, tid, name, stat, per);
        }
    }
    return (strt);
}

Upvotes: 1

Views: 550

Answers (2)

osgx
osgx

Reputation: 94175

fgets does a reading (consuming) of first string in the input file and then first fscanf tries to parse "Test" as "%i" format and fails.

You may use feof as condition in while loop, but (thnx to John Bode) it is better to check every fscanf and use a flag or break.

Every fscanf returns a value. As stated in 1:

RETURN VALUE

Upon successful completion, these functions shall return the number of successfully matched and assigned input items; this number can be zero in the event of an early matching failure. If the input ends before the first matching failure or conversion, EOF shall be returned. If a read error occurs, the error indicator for the stream is set, EOF shall be returned, and errno shall be set to indicate the error.

So, you may want to check the return value of every fscanf to know that something goes (reads) wrong.

UPDATE: You should never use fgets/fgetc to check something (without rewinding back with fseek or undoing with ungetc), because every file read function will CONSUME data from file (current position in file will be incremented). To check errors, just look at return value of usual fscanf/other function you used to parse input.

Upvotes: 2

dave
dave

Reputation: 131

you failed to check for failure of each call, so you can't know what happened.

(I edited this to remove the assertion that %i was invalid, sorry)

Upvotes: 0

Related Questions