2017-07-13 156 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已經發現:如果不能打印標記,如果是沒有。