1

是的,我也是新手。我已经有这个问题很长一段时间了。我正在尝试使用 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 函数也不起作用。

4

3 回答 3

3

这个:

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

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

char *data;

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

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


笔记:

  1. 所以这就是为什么你声明指向字符串文字的指针 asconst char *明确地不是 as char *,如果你这样做,我会找到你并 const 限定你。

  2. 数组不是指针,它们从来都不是,也永远不会是。

于 2013-07-05T06:39:01.533 回答
2

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

这些初始化有什么区别?

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

如果我尝试为 p[i] 分配一个新值,我的程序就会崩溃。

答案是:

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

  1. 作为 char 数组的初始值设定项,就像在 char a[] 的声明中一样,它指定了该数组中字符的初始值(如果需要,还指定其大小)。
  2. 在其他任何地方,它都会变成一个未命名的静态字符数组,并且这个未命名的数组可能存储在只读存储器中,因此不一定可以修改。在表达式上下文中,数组像往常一样立即转换为指针(参见第 6 节),因此第二个声明将 p 初始化为指向未命名数组的第一个元素。
于 2013-07-05T06:45:32.510 回答
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;
}

这不会修改内存块。

于 2013-07-05T06:54:44.623 回答