tonymiao
tonymiao

Reputation: 305

Trouble with fscanf() in c programming

I am trying to read some data in a file called "data" with specific format. The data in this file is:

0 mpi_write() 100
1 mpi_write() 200
2 mpi_write() 300
4 mpi_write() 400
5 mpi_write() 1000

then code is as follow:

#include<stdlib.h>
#include<stdio.h>

typedef struct tracetype{
    int pid;
    char* operation;
    int size;
}tracetyper;

void main(){
    FILE* file1;
    file1=fopen("./data","r");
    if(file1==NULL){
        printf("cannot open file");
        exit(1);
    }else{
        tracetyper* t=(tracetyper*)malloc(sizeof(tracetyper));
        while(feof(file1)!=EOF){
            fscanf(file1,"%d %s %d\n",&t->pid,t->operation,&t->size);

            printf("pid:%d,operation:%s,size:%d",t->pid,t->operation,t->size);
        }
        free(t);
    }
    fclose(file1);
}

When running with gdb, I found fscanf doesn't write data to t->pid,t->operation and t->size. Any thing wrong with my code or what? Please help me!

Upvotes: 2

Views: 110

Answers (2)

aoak
aoak

Reputation: 1013

You should loop with something like:

while ( (fscanf(file1,"%d %s %d\n",&t->pid,t->operation,&t->size)) != EOF) {
   printf("pid:%d,operation:%s,size:%d",t->pid,t->operation,t->size);
}

You also need to add malloc for char array in the structure. Also, insert a check for t as

if (t == NULL)
   cleanup();

Upvotes: -1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

Your program has undefined behavior: you are reading %s data into an uninitialized char* pointer. You need to either allocate operation with malloc, or if you know the max length is, say, 20 characters, you can put a fixed string for it into the struct itself:

typedef struct tracetype{
    int pid;
    char operation[21]; // +1 for null terminator
    int size;
} tracetyper;

When you read %s data, you should always tell fscanf the limit on the length, like this:

fscanf(file1,"%d %20s %d\n",&t->pid,t->operation,&t->size);

Finally, you should remove \n at the end of the string, and check the count of returned values instead of checking feof, like this:

for (;;) { // Infinite loop
    ...
    if (fscanf(file1,"%d %20s %d",&t->pid,t->operation,&t->size) != 3) {
        break;
    }
    ...
}

Upvotes: 5

Related Questions