1

As an exercise, I am creating a "Database" that stores data from a structure array in a .txt file. When reading the data from the file I used strtok to assign each value to the corresponding structure member since they were separated with whitespace and they are formatted in this specific way.

 #value0        #value1        #value2         #value3
 randomstring   randomstring   randomstring    random_4digit_long
 randomstring   randomstring   randomstring    random_4digit_long

This works great until strtok returns the NULL value since it reaches the end of string.The structure here is named items and is of type myStruct

long loadData(myStruct *items, long len, char *inputFile){
FILE *openedFile;
openedFile= fopen(inputFile,"r");
if (openedFile==NULL)
{
    fprintf(stderr,"No file found.\n");
    fclose(openedFile);
    return -1;
}
else
{
    fscanf(openedFile, "%*[^\n]");  //Discard first line
    getc(openedFile);               //get remaining \n character
    char * token;
    char line[80];
    char * pointer=line;
    for (int i=0; i<=len;i++)
    {
        if(NULL==fgets(pointer,80,openedFile))   //get each line and check if empty
        {
               break;
        }
        token = strtok(pointer, " ");
        if (strcmp(token,"\n")==0 || !token)   //Comparison Point
        {
                fprintf(stderr,"File has wrong format.\n");
                fclose(openedFile);
                return -1;
        }
        strcpy(items[i].value0,token);
        for(int j=0;j<=2;j++)
        {
            token = strtok(NULL," ");
            if (strcmp(token,"\n")==0 || !token)   //Comparison Point
            {
                fprintf(stderr,"File has wrong format.\n");
                fclose(openedFile);
                return -1;
            }
            if(j==0)
            {
                strcpy(items[i].value1,token);
            }
            else if(j==1)
            {
                strcpy(items[i].value2,token);
            }
            else if(j==2)
            {
                items[i].value3=atoi(token);
            }
        }
    }
fclose(openedFile);
return 0;
}

When the .txt file is formatted as intended it works perfectly. When The format is not, I've got the comparison point to check for anomalies. When the .txt file has for example two values that are empty then strtok returns NULL because it has reached the end of the string prematurely. Then when the comparison takes place, it creates a segmentation fault. I've tried many ways that I found on google about NULL checking a pointer but none seems to work. I need to make this comparison in order for the condition of the formatting to hold.

From what I've read, when the comparison takes place and the token pointer is NULL then the !token condition would be ok, but here it doesn't work, any ideas why?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 2
    `if (strcmp(token,"\n")==0 || !token)` --> `if (!token || strcmp(token,"\n")==0 )`. There should be a dup otherwise I or someone else can post an answer. – kaylum Jun 04 '20 at 01:25
  • @kaylum I can't believe I spent so much time here and that this was the problem all along. Can you please explain why is this happening or just point me to what to read in order to understand? – Konstantinos Zafeiris Jun 04 '20 at 01:29
  • 2
    1. The expressions in the conditional are evaluated from left to right. 2. "short-circuiting" results in the evaluation terminating as soon as the result is known. In your code it means originally `strcmp` part is evaluated first which would crash if `token` is NULL. By changing the order, the `strcmp` will not be evaluated if `token` is `NULL` and hence no crash. – kaylum Jun 04 '20 at 01:32
  • 1
    You may want to read this: [What is “short-circuiting” in C like languages?](https://softwareengineering.stackexchange.com/questions/201896/what-is-short-circuiting-in-c-like-languages) – Andreas Wenzel Jun 04 '20 at 01:33
  • @kaylum in fact it causes undefined behaviour, not necessarily a crash. E.g. the optimizer might remove the whole thing as an undefined path . – M.M Jun 04 '20 at 02:20
  • @M.M Yes agreed. I just didn't want to go there so as not to confuse the original issue – kaylum Jun 04 '20 at 02:49

0 Answers0