strtok()跳过第一个令牌

时间:2014-08-24 01:04:01

标签: c strtok

似乎无法解决为什么此代码无法正常工作。 它应该是非常直截了当的。 根据我的故障排除,在while(标记)块中分配了id数组,但是当我去打印while(token)块之外的所有char数组时,id数组只显示所有其他数组显示其内容。

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;
}

2 个答案:

答案 0 :(得分:1)

您是由strcpy引起的缓冲区溢出错误的受害者。

正在发生的事情是,hotCold数组太小而无法容纳您填写的数据,但strcpy并不关心,也不知道那里没有足够的空间。因此,它继续将数据写入hotCold,然后耗尽空间,然后填充填充字节,然后填满id。你只是幸运地将hotCold的终止空字节放在id的开头。

使用strcpy切换为strncpystrncat(我认为优于strncpy)。如果您对我所说的内容持怀疑态度,请在最后添加一行代码:

assert (strlen (hotCold) < MIN_DESC_LEN);

另一种选择是id字段被解释为特殊的printf - 格式说明符。为了以防万一,请将printf(id)替换为printf("%s", id)

答案 1 :(得分:1)

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;
}

您永远不应该将程序外部的输入作为第一个参数传递给printf。想象一下,如果其中一个代币是&#34;%s&#34;并且你说printf(令牌) - 这是未定义的行为,因为你没有传递第二个字符串进行打印,如果你很幸运,你的程序会崩溃。