Why does my variable change after strtok() and fgets() without modifying it?

671 views Asked by At

Demonstration of the problem here: http://goo.gl/71U1xA

I am reading a file, and in that file there is a line:

SECTIE FIELD_IN #define ENDSEC

that indicates I need to store the lines following this one to a variable, but only if the line contains the part "#define".

So, I'm iterating trough the file and when the line contains "SECTIE" and "FIELD_IN", it retrieves the word with # in it and it stores it in the variable keyWord.

Now the problem is: the value in keyWord changes in the next loop without modifying it.

My textfile is:

SECTIE FIELD_IN1 #define ENDSEC
#define COL1                1,1
#define COL2                2,3
#define COL3                5,3
...etc

And the output of my code is this:

START

reading line
text=SECTIE FIELD_IN1 #define ENDSEC

keyword1=..
new sectie
keyword2=.#define.

reading line
text=#define COL1              1,1

keyword1=.            1,1
.
start = 1!
keyword3=.            1,1
.

My code:

int     x, status, start;
char    inputLine[5000 + 1];
char    copyLine[5000 + 1];
char    *keyWord = "";
FILE    *iFile;

status  = NOERROR;
x       = 0;
start   = 0;

iFile = fopen(gsz_inputFile, "r");  
if(iFile == NULL){ 
    status = ER_OPEN;
    return status;
}

while (fgets(inputLine, sizeof(inputLine), iFile) != NULL){

    printf("\n\nreading line");

    printf("\ntext=%s", inputLine);

    printf("\nkeyword1=.%s.", keyWord);

    strcpy(copyLine, inputLine);
    strlwr(copyLine);
    if(strstr(copyLine, "sectie") != NULL && strstr(copyLine, "field_in") != NULL){
        start = 1;

        printf("\nnew sectie");

        //get keyword
        keyWord = strtok(inputLine," ");
        while (keyWord != NULL)
        {
            if(strstr(keyWord, "#") != NULL){               
                break;
            }

            keyWord = strtok(NULL, " ");
        }

        printf("\nkeyword2=.%s.", keyWord); //here the keyword is correct
        continue;
    }

    if(start){
        printf("\nstart = 1!");

        printf("\nkeyword3=.%s.", keyWord);

        //status = storeString(inputLine, keyw, x); //my actual code is different
        if(status != NOERROR){ x--; }

        x++;
    }       
}

I think it has something to do with while (fgets(inputLine, sizeof(inputLine), iFile) != NULL) because after that line is executed, the value is changed.

Why is the value of keyWord changed after going into the next loop? My guess it has to do with undefined behavior, but I can't put my finger on the problem.

2

There are 2 answers

0
Eregrith On BEST ANSWER

You have inputLine which is an array. Inside it you store the string fetched by fgets():

while (fgets(inputLine, sizeof(inputLine), iFile) != NULL){

And in your loop you say keyWord points to some inputLine's token (which means it points to somewhere inside your array).

//get keyword
keyWord = strtok(inputLine," ");

When you run the second fgets() the array content's change, but not its address, so keyWord still points to inputLine content's which have changed

Example:

first fgets():
inputLine: ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
keyWord-->""
second strtok:
keyWord------------------------------------^

second fgets():
inputLine: ['T', 'h', 'i', 's', ' ', 'c', 'h', 'a', 'n', 'g', 'e']
keyword------------------------------------^ (before strtok)

You assumption "The value of keyWord changed" is false: The value of keyword is still the same, you can check it with printf("value of keyWord: %p\n", keyWord);. What changed is the value keyWordpoints to, which is what you display using %s in printf.

0
P.P On

strtok modifies the input buffer. So the keyword you get at the end of the loop is a pointer to location within the inputLine. When the loop reads another line using fgets it gets overwritten.