2017-07-13 92 views
0

我有一个字符串,看起来像1,3-5,7,9-11,我要重复调用strtok来标记它,以便输出看起来像这样:strtok嵌套while循环行为意外

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的“”只),那么输出看起来像人们所期望的:

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

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

+1

你'memcpy' **无处** ......'temptoken'是一个未初始化的指针。然后,对于字符串,只需使用'strcpy'(一旦您为目标正确分配了内存)。 –

+2

使用'strtok_r','strtok'具有内置的副作用。 –

+0

是的,你是对的,但我认为C++程序员也可以回答这个问题。 –

回答

5

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

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

+1

是的,只是重申OP(和其他人)的'strtok'是一个相当古老的图书馆功能 - 不会因为它的设计行为而感到困惑,你不是第一个。没有人再设计这样的库/ API函数! –

-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, ","); 
} 

而且你能指望什么。

您发现令牌“” 然后用函数记号化它(并打印标记) 那么你的subtokenisation之前打印标记再次 和它完成作为strtok的内部有一个状态。

因此,它的工作原理与您所写的完全相同。

您需要: 使用重入版本OD的strtok,

你应该返回你的令牌化功能的价值,表示如果subtokens已经发现:如果不能打印标记,如果是没有。