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

Why strtok() splits string that i didn't even passed to it?

我需要将字符串与文件分开。 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[= 的副本35=] 即使我只将 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;
    }

链表示例:

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...

为什么会这样?

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 是指向字符的指针数组),所以这个赋值根本没有意义。

您要牢记的两个主要事项是:

  1. strtok 是评论中 @JohnColeman 所说的破坏性功能。这意味着 strtok 修改传递给它的字符串(第一个参数).
  2. strtok 给你 指针 指向字符串的不同部分 并且你将它们存储在数组 dal。现在,您创建另一个类似的指针数组 dalcopy(假设您修复了 )并使它们指向字符串 code 中与 dal 相同的部分。

daldalcopy 指向字符串 code 的相同标记。因此,您对它们所做的任何更改也会影响 code,因为它们指向它。

strtok 之前以及所有内容:

+--------+--------+--------+--------+
| dal[0] | dal[1] | dal[2] | dal[3] | ... = dal
+--------+--------+--------+--------+

+------------------------------+
| "21:12:36 14:45:25 08:17:24" | = code
+------------------------------+

strtok 和 "copying" 之后:

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

如您所见,您并没有复制它,而只是创建了一个别名。

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