在C语言中复制strtok标记的内容

4
需要将一个字符串分隔开,然后进行另一次分隔。
char *token = strtok(str, ",");
while(token){
    char *current_string = malloc(sizeof(char) * strlen(token));
    strcpy(current_string, token);

    char *tk = strtok(current_string, ":"); // KEY
    printf("key: %s ", tk);
    tk = strtok(0, ":");                    // VALUE
    printf("value: %s\r\n", tk);
    printf("%s\n", token);
    token = strtok(0, ",");
}

printf("Done\n");

尝试复制 token 的内容,但这样做会干扰 token 变量中剩余的内容。它只处理了一个行而不是应该处理的三个行。我怀疑问题出在 strcpy(current_string, token) 上,但不确定我应该如何解决它。


3
strtok 不可重入,这就是为什么被注释为 // KEY 的那一行代码“干扰了剩余部分”的原因。有一个可重入版本的函数可用,也许叫做 strtok_rstrtok_s。这些函数在由调用者提供的变量中存储当前状态,而不是在内部使用 static 变量。 - Weather Vane
2
while的前两行中,您还有未定义的行为。 您需要一个额外的元素来终止空字符。 char *current_string = malloc(strlen(token) + 1); - R Sahu
使用strdup代替malloc来复制一个字符串。 - Dan Korn
2
尽管malloc()在标准C库中,但遗憾的是strdup()并不在其中。 - chux - Reinstate Monica
1个回答

6
strtok函数使用内部静态缓冲区来跟踪其上一次处理的位置。这意味着您不能使用它来来回解析两个不同的字符串。
在您具体的情况下,在此调用中:
token = strtok(0, ",");

内部缓冲区仍指向current_string中的位置,因此尝试返回到token是行不通的。

您需要使用strtok_r。这个版本需要一个额外的参数来跟踪当前状态。这样,您可以通过为每个字符串使用不同的状态指针来交替解析两个或多个字符串:

char *state1, *state2;
char *token = strtok_r(str, ",", &state1);
while(token){
    char *current_string = strdup(token);

    char *tk = strtok_r(current_string, ":", &state2); // KEY
    printf("key: %s ", tk);
    tk = strtok_r(NULL, ":", &state2);                    // VALUE
    printf("value: %s\r\n", tk);
    printf("%s\n", token);
    free(current_string);
    token = strtok_r(NULL, ",", &state1);
}

printf("Done\n");

请注意,后续的strtok_r调用中传入的是NULL而不是0,因为NULL可能不一定是0。此外,malloc/strcpy的调用被替换为调用strdup,这样做相同,并且添加了一次free调用以防止内存泄漏。 strtok_r在UNIX/Linux系统上可用。在Windows上,请使用strtok_s,它的工作方式相同。

请注意,传递给malloc的长度不正确。 - chqrlie
@dbush 哦,这很有道理。我不知道 strtok_rstrdup。这让事情变得更容易了。非常感谢你的帮助! - Kagemand Andersen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接