如何有效地使用strtok功能

时间:2013-07-05 06:36:17

标签: c strtok

是的,我也是新手。而且我已经有这个问题很长一段时间了。我试图用strtok来分割一个字符串,但问题是它不起作用。我已经看过人工页面和网上的例子,但我仍然没有答案。

在下面的代码中,我尝试使用在此站点中作为答案给出的示例代码。原来的while循环是:

    char str[] = "hello world how are you?\n";
    char *res;

    res = strtok(str, " \n");
    puts(res);
    while (res != NULL)
    {
        res = strtok(NULL, " \n");
        if(res!=NULL)
            puts(res);
    }

但是当将str更改为数据及其各自的分隔符(& =)时,它将变为分段错误。我该如何解决?代码中有什么问题?这是完整的代码。

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

int main()
{
    char *data;

    data = "integer1=1&integer2=2&integer3=3&integer4=4";
    puts(data);

    char str[] = "hello world how are you?\n";
    char *res;

    res = strtok(data, "=&");
    puts(res);
    while (res != NULL)
    {
        res = strtok(NULL, "=&");
        if(res!=NULL)
            puts(res);
    }

    return 0;
}
顺便说一句,strtok_r函数也不起作用。

3 个答案:

答案 0 :(得分:3)

此:

char str[] = "hello world how are you?\n";

创建一个数组并使用字符串文字的内容对其进行初始化。但是,这个:

char *data;

data = "integer1=1&integer2=2&integer3=3&integer4=4";

声明data是指向字符串文字的第一个字符的指针,当然,它是只读的,所以当strtok()尝试修改它时,它会失败(调用未定义的行为) )。


注意:

  1. 这就是为什么你将指向字符串文字的指针声明为const char * 明确地不是 char *,如果这样做的话,我会找到你并使你符合资格。

  2. Arrays are not pointers, they never were, and they never will be either.

答案 1 :(得分:2)

您正在观察的行为可以通过com.lang.c FAQ中的问题1.32解释:

  

这些初始化之间有什么区别?

char a[] = "string literal";
char *p  = "string literal";
     

如果我尝试为p [i]指定新值,我的程序会崩溃。

答案是:

  

字符串文字(C源中双引号字符串的正式术语)可以两种略有不同的方式使用:

     
      
  1. 作为char数组的初始值设定项,如char a []的声明,它指定该数组中字符的初始值(如果需要,还指定其大小)。
  2.   
  3. 在其他地方,它变成一个未命名的静态字符数组,这个未命名的数组可能存储在只读存储器中,因此不一定能被修改。在表达式上下文中,像往常一样将数组一次转换为指针(参见第6节),因此第二个声明将p初始化为指向未命名数组的第一个元素。
  4.   

答案 2 :(得分:0)

strtok打破内存块。文字字符串不能修改。因此,您不能同时使用strtoke。 试试这个:

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

int main(){
    char *data;

    data = "integer1=1&integer2=2&integer3=3&integer4=4";
    char *cur, *res;

    cur = data;
    res = strpbrk(cur, "=&");
    while (res != NULL)
    {
        fwrite(cur, 1, res-cur, stdout);
        fputc('\n', stdout);

        cur = res + 1;
        res = strpbrk(cur, "=&");
    }
    fputs(cur, stdout);

    return 0;
}

这不会修改内存块。