使用strtok_r时的分段错误

问题描述:

任何人都可以解释为什么我在以下示例中出现分段错误?使用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++]); 
    } 
} 

试试这个:

#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 当我编译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

我认为这可能是char *tokens[50];因为你已经声明它是一个指针时,它已经是一个指针。一个数组已经是一个声明的指针。你的意思是说char tokens[50];。这应该够了吧。

+1

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

strtok_r尝试空字符写入你好(这是非法的,因为它是一个常量字符串)

+0

我试过了'char hello [50]'。分段错误消失了,但现在问题在于'printf'只是打印可悲的空白行。 :( – 2010-02-09 06:39:31

您已经明白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; 
} 

一堆东西错了:

  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

  • 你需要调用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