2015-12-16 52 views
4

我知道這已被問過,但以前的答案已經說過你不能修改字符串,除非我誤解我不是。我可以使用strtok_r直到最後一行輸入,然後我得到一個seg錯誤。爲什麼會發生?下面是我的代碼的簡化版本。從打印我知道它通過得到b處理,但是然後有一個seg故障?Strtok_r分段錯誤

#include <stdio.h> 
#include <string.h> //strlen 
#include <stdlib.h> 

    void handler(char * input){ 
    char * end_str; 
    char * token =strtok_r(input, "\n", &end_str); 
    char * endd_str; 
    char * token2= strtok_r(token, " ", &endd_str); 
    while(token!=0){ 
     printf("%s\n",token); 
     token=strtok_r(NULL,"\n",&end_str); 
     while(token2 !=0){ 
      token2 =strtok_r(NULL," ",&endd_str); 
      printf("%s\n",token2);} 
    } 

} 

int main(int argc , char *argv[]) 
{ 
    char test[100]="set a,10.5\nset b,11.5\nget b\nadd e,a,b\nsub g,a,b"; 
    handler(test); 
    return 0; 
} 
+1

是否也提供了代碼失敗?如果沒有,你沒有提供足夠的數據給任何人告訴你爲什麼失敗。請參閱http://stackoverflow.com/help/mcve –

+1

無法用您提供的示例代碼重新創建seg故障。你確定它是'strtok_r'這是導致seg故障,而不是別的。 – Munir

+0

你爲什麼認爲程序執行會導致一些有意義的事情?你可以查看生成的二進制代碼,看看你的情況會發生什麼。 – user502144

回答

1

適用於我(MS Visual C++)。考慮到它是Windows而不是POSIX,唯一不同的是使用strtok_s而不是strtok_r

在這裏我已經添加了一些修改你的代碼。

#include <string.h> //strlen 
#include <stdlib.h> 

void handler(char * input){ 
    char * end_str; 
    char * token =strtok_s(input, "\n", &end_str); // tokenize input string 
    char * endd_str; 
    char * token2 = NULL; 

    while(token!=0){ 

     printf("%s\n",token); 

     token2 = strtok_s(token, " ", &endd_str); // retokenize first token 
     while(token2 !=0){ 
      printf("%s\n",token2); // replace printf call to avoid null string output and first token miss 
      token2 =strtok_s(NULL," ",&endd_str);} 

     token = end_str; // "important" restore char pointer to point the last untokenized input character 

     token=strtok_s(token,"\n",&end_str); // the same as printf issue is for all loops body 
    } 

} 

int main(int argc , char *argv[]) 
{ 
    char test[100]="set a,10.5\nset b,11.5\nget b\nadd e,a,b\nsub g,a,b"; 
    handler(test); 
    return 0; 
} 
+1

我不認爲目前提出的問題提供了一個MCVE –

+0

介意解釋_s和_r之間的區別? –

+1

@Mr_Pouet:與Windows OS相同的函數'_s',POSIX的'_r',只有命名區別。 – Mykola

2

你正在交錯strtok_r調用工作在相同的字符串。在while內循環的第二次迭代中,在調用token2 =strtok_r(NULL," ",&endd_str);,endd_str之前指向一個空字符串,因爲它匹配的字符串到達​​末尾,所以strtok_r返回NULL。將NULL傳遞給printf會導致段錯誤。

在每個"\n"分隔符的解析之後,重新開始循環遍歷" "分隔符。直到你疲憊到內在的一個之前,不要再做外面的一個。另外,將您的strtok_r調用移動到循環的結尾,以便while條件適當地檢查它們。

你需要做到以下幾點:

void handler(char * input){ 
    char * end_str; 
    char * token =strtok_r(input, "\n", &end_str); 
    while(token!=0){ 
     printf("%s\n",token); 
     char * endd_str; 
     char * token2= strtok_r(token, " ", &endd_str); 
     while(token2 !=0){ 
      printf("%s\n",token2); 
      token2 =strtok_r(NULL," ",&endd_str); // call at end of loop 
     } 
     token=strtok_r(NULL,"\n",&end_str);   // call at end of loop 
    } 
} 

輸出繼電器:

set a,10.5 
set 
a,10.5 
set b,11.5 
set 
b,11.5 
get b 
get 
b 
add e,a,b 
add 
e,a,b 
sub g,a,b 
sub 
g,a,b