user3126322
user3126322

Reputation: 23

strtok() skips first token

Can't seem to work out why this code is not working. It should be really straight forward. From what I have troubleshooted, in the while(token) block the id array is assigned but then when I go to print all the char array's outside the while(token) block the id array displays nothing but all the other array's display their contents.

int loadCatData(char* menuFile) {
   char line[MAX_READ];
   char id[ID_LEN];
   char hotCold[MIN_DESC_LEN];
   char name[MAX_NAME_LEN];
   char description[MAX_DESC_LEN];
   char delim[2] = "|";
   char lineTemp[MAX_READ];
   int count;
   FILE *mfMenu = fopen(menuFile, "r");

   while (fgets(line, sizeof(line), mfMenu)!=NULL) {
      count = 0;
      printf(line);

      strcpy(lineTemp,line);

      char* token = strtok(lineTemp, delim);

      while (token) {
         printf(token);
         if (count == 0) {
            strcpy(id, token);
         }
         if (count == 1) {
            strcpy(hotCold, token);
         }
         if (count == 2) {
            strcpy(name, token);
         }
         if (count == 3) {
            strcpy(description, token);
         }
         printf("\n");
         token = strtok(NULL, delim);
         count = count + 1;
      }
      printf(id);
      printf(hotCold);
      printf(name);
      printf(description);

   }
   fclose(mfMenu);
   return true;
}

Upvotes: 1

Views: 1010

Answers (2)

John Zwinck
John Zwinck

Reputation: 249153

int loadCatData(const char* menuFile) {
    char id[ID_LEN];
    char hotCold[MIN_DESC_LEN];
    char name[MAX_NAME_LEN];
    char description[MAX_DESC_LEN];
    FILE *mfMenu = fopen(menuFile, "r");

    while (fscanf(mfMenu, "%*s|%*s|%*s|%*s",
            sizeof(id), id, sizeof(hotCold), hotCold,
            sizeof(name), name, sizeof(description), description) == 4) {
        printf("%s %s %s %s\n", id, hotCold, name, description);
    }

    fclose(mfMenu);
    return true;
}

You should never pass input from outside the program to printf as the first argument. Imagine if one of the tokens is "%s" and you say printf(token)--that's undefined behavior because you didn't pass a second string to print, and your program will crash if you're lucky.

Upvotes: 1

randomusername
randomusername

Reputation: 8097

You are the victim of a buffer overflow error caused by strcpy.

What is happening is that the hotCold array is too small to hold the data you're filling it with, but strcpy doesn't care, nor does it know that there isn't enough room. So it keeps on writing data into hotCold and then runs out of room, then fills up the padding bytes, then fills up id. You just have the unfortunate luck of having the terminating null byte of hotCold sitting at the start of id.

Switch from using strcpy to strncpy or strncat (which I think is better than strncpy). If you're skeptical of what I'm saying, add a line of code at the end that goes like this:

assert (strlen (hotCold) < MIN_DESC_LEN);

The other alternative is that the id field is being interpreted as a special printf-format specifier. Just in case, replace printf(id) with printf("%s", id).

Upvotes: 1

Related Questions