【问题标题】:strtok in nested while loops behaves unexpectedly [duplicate]嵌套while循环中的strtok行为异常[重复]
【发布时间】:2017-07-13 15:09:21
【问题描述】:

我有一个看起来像 1,3-5,7,9-11 的字符串,我将通过重复调用 strtok 来标记它,以便输出看起来像:

1
3
5
7
9
11

我的代码如下所示:

#include <stdio.h>
#include <string.h>

void tokenize(char *string){
    char *token;
    token = strtok (string,"-");
    while (token != NULL) {
            // ... do some other unrelated stuff ...
            printf("\tToken %s\n", token);
            token = strtok (NULL, ",");
    }
}

int main (int argc,char **argv)
{
    char *token;
    token = strtok (*(argv+1),",");
    while (token != NULL) {
            if (strchr(token,45)){  //45 is ASCII for "-".
                    tokenize(token);
            }
            printf("Token1 %s \n", token);
            token = strtok (NULL, ",");
    }
    return 0;
}

但是,当我运行代码时,它过早结束,我得到:

./tokenizer 1,3-5,7,9-11
Token1 1
        Token 3
        Token 5
Token1 3

但我期望/想要类似的东西:

./tokenizer 1,3-5,7,9-11
Token1 1
        Token 3
        Token 5
Token1 7
        Token 9
        Token 11

如果我注释掉 tokenize(temptoken); 的行(换句话说,strtok on "," only),那么输出看起来就像人们期望的那样:

./tokenizer 1,3-5,7,9-11
Token1 1
Token1 3-5
Token1 7
Token1 9-11

所以看起来问题确实出在对已经标记化的字符串的后续 strtok 调用上,所以我尝试 memcpy 指向标记指针的内存,但这并没有真正帮助:

#include <stdio.h>
#include <string.h>

void tokenize(char *string){
    char *token;
    token = strtok (string,"-");
    while (token != NULL) {

            printf("\tToken %s\n", token);
            token = strtok (NULL, ",");
    }
}

int main (int argc,char **argv)
{
    char *token;
    char *temptoken ;
    token = strtok (*(argv+1),",");
    while (token != NULL) {
            if (strchr(token,45)){  //45 is ASCII for "-".
/* added memcpy */  memcpy(temptoken,token,strlen(token)+1);
                    tokenize(temptoken);
            }
            printf("Token1 %s \n", token);
            token = strtok (NULL, ",");
    }
    return 0;
} 


$ ./tokenizer 1,3-5,7,9-11 
Token1 1
        Token 3
        Token 5
Token1 3-5

关于我可以做些什么来修复代码、了解我的误解所在并获得所需输出的任何想法?

【问题讨论】:

  • you memcpy nowhere ... temptoken 是一个未初始化的指针。然后,对于字符串,只需使用 strcpy 代替(一旦你为你的目标正确分配了内存)。
  • 使用strtok_r, strtok 有一个内置的副作用。
  • C++ 程序员不要使用这个愚蠢的strtok 函数。
  • @GlenMacLachlan 这只是标签垃圾邮件。尽管您可以用 C++ 编写这样的代码,但您不应该这样做。 C++ 程序员不会感兴趣。
  • 而不是45 和评论,只需使用'-'

标签: c strtok


【解决方案1】:

您不能使用嵌套的strtok(),因为它使用一些静态内存来保存调用之间的上下文,以了解正在被标记的字符串中的当前位置。

请改用strtok_r(),这是 strtok 的可重入版本,没有任何内部状态。

【讨论】:

  • 是的,只是重申 OP(和其他人)strtok 是一个相当古老的库函数——不要因为被它的设计行为混淆而感到难过,你不是第一个一。再也没有人像这样设计库/API 函数了!
【解决方案2】:
while (token != NULL) {
        if (strchr(token,45)){  //45 is ASCII for "-".
         /* added memcpy */  memcpy(temptoken,token,strlen(token)+1);
                tokenize(temptoken);
        }
        printf("Token1 %s \n", token);
        token = strtok (NULL, ",");
}

你有什么期望。

你正在寻找令牌',' 然后用你的函数标记它(并打印标记) 然后在子标记化之前再次打印该标记 它在 strtok 具有内部状态时结束。

所以它和你写的完全一样。

您需要: 使用可重入版本 od strtok,

你应该在你的 tokenize 函数中返回值来指示是否找到了子标记:如果没有打印标记,如果是则不打印。

【讨论】:

    猜你喜欢
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    相关资源
    最近更新 更多