0

I have a simple file formatted as such

NAME|VALUE
NAME|VALUE
NAME|VALUE

I am trying to read these in, and store them in an array of structs, the struct is this

struct data
{
    char* name;
    char* value;
};

For now, I know the size of the array will be 3, so I did this:

struct data pairs[3];

Here is my code as I am trying to read it in from the file:

char *tempVal;
int i =0;
    if(file != NULL)
        {
            char curLine [128];
            while(fgets(curLine, sizeof curLine, stockFile) != NULL)
            {   

                tempVal = strtok(curLine,"|");
                printf("i:%i\n",i);
                pairs[i].name= tempVal;
                printf("name at pos %i is %s\n",i, pairs[i].name);
                tempVal = strtok(NULL,"|");
                pairs[i].value= tempVal;
                printf("value at pos %i is %s\n",i, pairs[i].value);
                ++i;
            }
            fclose(file);
        }

and each of those printf statments prints the correct thing along the way, then I try to print the array with this

int j
for(j = 0; j < 3; j++)
    {   

        printf("ENTRY# %i\NAME:%s\VALUE:%s\n\n",j,pairs[j].name, pairs[j].value);
    }

Sorry the indentation is a little weird, tried messing with the code blocks but couldn't get it quite perfect. However, I am wondering why it shows the correct thing during the while loop as it goes along, but then after it is complete the for loop shows all three of the array entries having the same name(the value is correct for the third entry but for the first and second entries the value field contains half of the correct value for the third entry)

Thanks!

1 Answer 1

1

The value returned from strtok() will be pointing to an element in curLine, so all entries in the array of structs will be pointing to an element in curLine which is overwritten with each call to fgets() (and will only be valid for the current iteration).

You should make a copy of the value returned from strtok() during the while, possibly using strdup():

while(fgets(curLine, sizeof curLine, stockFile) != NULL)
{   
    tempVal = strtok(curLine,"|");
    printf("i:%i\n",i);
    pairs[i].name = strdup(tempVal);
    printf("name at pos %i is %s\n",i, pairs[i].name);
    tempVal = strtok(NULL,"|");
    pairs[i].value = strdup(tempVal);
    printf("value at pos %i is %s\n",i, pairs[i].value);
    ++i;
}

free() them later when no longer required:

for (j = 0; j < 3; j++)
{
    free(pairs[j].name);
    free(pairs[j].value);
}
Sign up to request clarification or add additional context in comments.

13 Comments

Updated answer for free(). You need to copy the values so that the pairs in the array are not referencing curLine, which is changing with each call to fgets().
Okay, that makes sense because the curLine pointer is changing with each call and I can't have the struct value referencing that pointer. Freeing them will do what exactly?
strdup() allocates memory (using malloc()), which must be free()d to avoid a memory leak.
Makes sense, I'm using gcc and when I try to run the program with the for loop at the end to free the memory, it gives me a warning: "incompatible implicit declaration of built-in function 'free' [enabled by default]"
@Andrew, can you post another question for that? Is is different from the title of this question and will attract attentions from other people on SO and would be more useful.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.