2

I'm trying to write a function in C which reads from a file some values separated by commas, on each line there are 4 values, the last one is an integer and I want to put them in a allocated space. When I'm trying to read them from the memory in while loop they are just fine but from the for loop or from outside of the function I get just the last line of the file multiple times in few cases they miss some characters. I'm new to C but I assume that it has something to do with strtok() function.

Here is my code:

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

    typedef struct {
        char * foo;
        char * bar;
        char * baz;
        int qux;
    }structure;

    char * readFile(const char * filename, structure * array){
        const int maxstring=100;
        FILE * fr=fopen(filename,"r");
        char * rc;
        char buf[maxstring];
        while(( rc = fgets(buf, maxstring, fr) )) {
            array->foo=strtok (buf,",");
            array->bar=strtok (NULL,",");
            char *aux=strtok (NULL,",");
            array->qux=atol(strtok (buf,","));
            array->baz=strtok(aux,"\n");
            printf("%s,%s,%s,%d\n",array->foo,array->bar,
            array->baz,array->qux);
            array++;
        }
        array=array-9;
        for (int i=0;i<10;i++){
            printf("%s,%s,%s,%d\n",array->foo,array->bar,
            array->baz,array->qux);
            array++;
        }
        return "Success";
    }


    int main(){
        structure * array=malloc(100*sizeof(structure));
        readFile("repository.txt",array);
        free(array);
        return 0;
    }

1 Answer 1

5

The problem is you're storing pointers returned by strtok. The function strtok returns pointer in the memory of the original buffer, that is, pointers inside buf. And you overwrite buf at each iteration (via fgets).

The simplest way to fix the problem is to strdup the value returned by strotk:

char * p = strtok (buf,",");
if (p)
    array->foo = strdup(p);

Same goes for the other stuff you're storing. Don't forget to call free when you're done with them.

Sign up to request clarification or add additional context in comments.

4 Comments

You may also end up with a repeat final line if there is stuff in the file after the end of the data. In fact, it is almost inevitable you will get at least one duplicate because after at the final <data>\n it will return a line, you will call it again, it will return a line of zero length (which will look very like your previous line in buf) and only when you call it again will it have got to EOF.
@NeilTownsend Good observation, never thought of that really.
Thank you :-) but your answer got to the root issue, which I thought was rather perceptive.
Thank you! It works, now I have to make some tweaks as @NeilTownsend said.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.