为什么strtok()拆分我甚至没有传递给它的字符串?

时间:2017-01-12 00:40:40

标签: c string split linked-list strtok

我需要将字符串与文件分开。 String =" 21:12:36 14:45:25 08:17:24" 当我执行strtok()并将所有令牌放入数组时,一切正常,但是当我第二次执行strtok()时,它会混乱一切。 例如:

char *p = strtok (code, " ");
while (p != NULL){
    dal[i++] = p;
    p = strtok (NULL, " ");
}

输出:

dal[0] = 21:12:36
dal[1] = 14:45:25
dal[2] = 08:17:24

我复制了 dal 数组,当我第二次执行strtok时,我更改了原始字符串(代码)和我的 dal 副本,即使我传递了dal数组只有strtok()。我尝试将 dal 发送到LinkedList,但是在第二次strtok之后甚至更改了LinkedList。

宣言:

char *dal[20], *dalcopy[20];
//copying below
for(int k = 0; k<i; k++){
    dalcopy[v] = dal[k];
    v = v+1;
}

示例:

for (int j = 0; j<i; j++){
    char *o = strtok(dal[j], ":");
    while (o != NULL){
        for(int h = 0; h<3; h++){
            if(h == 0){vienas[b].Hour = atoi(o);}
            if(h == 1){vienas[b].Min = atoi(o);}
            if(h == 2){vienas[b].Sec = atoi(o);}
            o = strtok (NULL, ":");
        }            
        b = b+1;
    }

LinkedList示例:

char *p = strtok (code, " ");
while (p != NULL){
    dal[i++] = p;
    put(head, p); //puts each element to list end
    p = strtok (NULL, " ");
}
printf("%s\n", show_by_index(&head, 0)); **Output == 21 after second strtok**

输出:

original string = 21
dal[0] = 21
dal[1] = 14
dal[2] = 08
dalcopy[0] = 21
etc...

为什么会这样?

2 个答案:

答案 0 :(得分:2)

您要记住的两件主要事情是:

  1. strtok是评论中@JohnColeman所说的破坏性函数。这意味着 strtok修改传递给它的字符串(第一个参数)
  2. strtok为您指定指针指向字符串的不同部分,并将它们存储在数组dal中。现在,您创建另一个类似的指针数组dalcopy(假设您修复了what @David told you)并使它们指向字符codedal相同的部分。
  3. daldalcopy指向字符串code的相同标记。因此,您对它们所做的任何更改也会影响code,因为它们指向它。

    strtok和之前:

    +--------+--------+--------+--------+
    | dal[0] | dal[1] | dal[2] | dal[3] | ... = dal
    +--------+--------+--------+--------+
    
    +------------------------------+
    | "21:12:36 14:45:25 08:17:24" | = code
    +------------------------------+
    

    strtok之后和&#34;复制&#34;:

    +--------+--------+--------+--------+
    | dal[0] | dal[1] | dal[2] | dal[3] | ... = dal
    +--------+--------+--------+--------+
       ↓         ↓          ↓
    +---------------------------------+
    | "21:12:36\0014:45:25\008:17:24" | = code
    +---------------------------------+
       ↑         ↑          ↑
       |          \         \----\
    +------------+------------+------------+------------+
    | dalcopy[0] | dalcopy[1] | dalcopy[2] | dalcopy[3] | ... = dalcopy
    +------------+------------+------------+------------+
    

    正如您所看到的,您并未复制它,而仅仅是创建别名。

    解决方案是strdup / malloc + strcpy令牌。

答案 1 :(得分:1)

char *dal[20], dalcopy[20];
//copying below
for(int k = 0; k<i; k++){
    dalcopy[v] = dal[k];
    v = v+1;
 }

这不对。由于dalcopy是一个字符数组,dalcopy[v]是一个字符。但是dal[k]不是一个字符(因为dal是一个指向字符的指针数组),所以这个赋值完全没有意义。