2010-02-09 69 views
14

任何人都可以解釋爲什麼我在以下示例中出現分段錯誤?使用strtok_r時的分段錯誤

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

int main(void) { 
    char *hello = "Hello World, Let me live."; 
    char *tokens[50]; 
    strtok_r(hello, " ,", tokens); 
    int i = 0; 
    while(i < 5) { 
    printf("%s\n", tokens[i++]); 
    } 
} 

回答

22

試試這個:

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

int main(void) { 
     char hello[] = "Hello World, Let me live."; // make this a char array not a pointer to literal. 
     char *rest; // to point to the rest of the string after token extraction. 
     char *token; // to point to the actual token returned. 
     char *ptr = hello; // make q point to start of hello. 

     // loop till strtok_r returns NULL. 
     while(token = strtok_r(ptr, " ,", &rest)) { 

       printf("%s\n", token); // print the token returned. 
       ptr = rest; // rest contains the left over part..assign it to ptr...and start tokenizing again.  
     } 
} 
/* 
Output: 
Hello 
World 
Let 
me 
live. 
*/ 
+0

謝謝噸。:) – 2010-02-09 06:59:23

+0

這個例子給我一個printf行的段錯誤。 gdb打印令牌顯示0xffffffffffffdad0 <地址0xffffffffffffdad0越界>當我編譯proj1.c:33:2時警告:隱式聲明函數'strtok_r'[-Wimplicit-function-declaration] proj1。c:33:14:warning:賦值使得整型指針沒有強制轉換[缺省情況下啓用] – schwiz 2012-10-01 00:48:21

+1

對不起,我是一個新手,爲什麼不應該是'char * ptr = Hello;'大寫H?此外,Alok的回答說,第一次參數需要「標記」,然後後續調用需要爲NULL,但是看起來你的例子只是把它稱爲while循環中的一種方式?感謝代碼btw – 2012-12-17 22:48:16

0

我認爲這可能是char *tokens[50];因爲你已經聲明它是一個指針時,它已經是一個指針。一個數組已經是一個聲明的指針。你的意思是說char tokens[50];。這應該夠了吧。

+1

你對C的理解似乎比我弱...... – 2010-02-09 06:40:53

3

strtok_r嘗試空字符寫入你好(這是非法的,因爲它是一個常量字符串)

+0

我試過了'char hello [50]'。分段錯誤消失了,但現在問題在於'printf'只是打印可悲的空白行。 :( – 2010-02-09 06:39:31

2

您已經明白strtok_r的使用不正確。請檢查該example和文檔

並嘗試&看到這一點:

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

int main(void) 
{ 
    char hello[] = "Hello World, let me live."; 

    char *tmp; 
    char *token = NULL; 
    for(token = strtok_r(hello, ", ", &tmp); 
     token != NULL; 
     token = strtok_r(NULL, ", ", &tmp)) 
    { 
     printf("%s\n", token); 
    } 

    return 0; 
} 
5

一堆東西錯了:

  1. hello指向字符串文字,必須將其視爲不可變。 (它可以存在只讀存儲器中。)由於strtok_r突變了其參數字符串,因此不能使用hello

  2. 您只需撥打strtok_r一次,並且不要初始化tokens陣列指向任何內容。

試試這個:

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

int main(void) { 
    char hello[] = "Hello World, Let me live."; 
    char *p = hello; 
    char *tokens[50]; 
    int i = 0; 

    while (i < 50) { 
    tokens[i] = strtok_r(p, " ,", &p); 
    if (tokens[i] == NULL) { 
     break; 
    } 
    i++; 
    } 

    i = 0; 
    while (i < 5) { 
    printf("%s\n", tokens[i++]); 
    } 

    return 0; 
} 
+0

感謝您的回答。我希望SO允許將多個答案標記爲正確的。 :) – 2010-02-09 07:01:08

14
  • 你需要調用strtok_r在一個循環。第一次給它字符串進行標記,然後你給它NULL作爲第一個參數。
  • strtok_rchar **作爲第三個參數。 tokens是一個50 char *值的數組。當您將tokens傳遞給strtok_r()時,傳遞的值是指向該數組的第一個元素的char **值。這沒關係,但是你正在浪費49個根本不用的值。您應該有char *last;並使用&last作爲strtok_r()的第三個參數。
  • strtok_r()修改它的第一個參數,所以你不能傳遞一些無法修改的東西。 C中的字符串文字是隻讀的,所以你需要一些可以修改的東西:例如char hello[] = "Hello World, Let me live.";
+1

感謝您的答案。我希望SO允許將多個答案標記爲正確的。 :) – 2010-02-09 07:00:31

+0

+1,最佳答案。 – 2010-02-09 07:01:09

+0

@Scrub:很高興能有幫助。確保你明白了我的第二點(關於'char * tokens [50];'當傳遞給函數時'等同於'char **')。 – 2010-02-09 07:04:55