使用strtok在c中分割一个字符串

Using strtok to split a string in c

在下面的代码中,我尝试拆分字符串以从字符串中获取用“,”分隔的名称。

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


int main(void)
{
    char *st = "Addison,Jayden,Sofia,Michael,Andrew,Lily,Benjamin";
    char *name[7];
    char *separate = ",";

    char *token = strtok(st, separate);
    int i = 0;
    while(token != NULL)
    {
        strcpy(name[i], token);
        token = strtok(NULL, ",");
        i++;
    }
    for (int j = 0; j < 7; j++)
    {
        printf("%s\n", name[j]);
    }
}

但是,当我尝试 运行 代码时,我 运行 陷入了分段错误。我尝试调试它,似乎这行特定的代码是错误的来源:

char *token = strtok(st, separate);

谁能告诉我我做错了什么?

您声明了一个指向字符串文字的指针

char *st = "Addison,Jayden,Sofia,Michael,Andrew,Lily,Benjamin";

您不能更改字符串文字。任何更改字符串文字的尝试都会导致未定义的行为。

来自 C 标准(6.4.5 字符串文字)

7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined

另一方面,标准 C 函数 strtok 更改传递给它的字符串。

来自C标准(7.23.5.8的strtok函数)

4 The strtok function then searches from there for a character that is contained in the current separator string. If no such character is found, the current token extends to the end of the string pointed to by s1, and subsequent searches for a token will return a null pointer. If such a character is found, it is overwritten by a null character, which terminates the current token. The strtok function saves a pointer to the following character, from which the next search for a token will start.

所以将声明替换为

char st[] = "Addison,Jayden,Sofia,Michael,Andrew,Lily,Benjamin";

您还声明了一个未初始化的指针数组。

char *name[7];

所以这个声明

strcpy(name[i], token);

也调用未定义的行为。

相反,您可以只写

name[i] = token;

并且由于变量 i 包含 tfokens 的数量,因此通常这个循环

for (int j = 0; j < 7; j++)
{
    printf("%s\n", name[j]);
}

至少应该像这样重写(不使用幻数 7)

for (int j = 0; j < i; j++)
{
    puts( name[j] );
}

但是,当我尝试 运行 代码

时,我 运行 陷入了分段错误

两个问题:

  • 正在尝试更改 non-editable 字符串。
  • 试图访问不属于进程的位置。

其中任何一个都可能导致崩溃。 (seg-fault)

内存分配问题:
宣言:

  char *name[7];

创建一个包含 7 个指针的数组。它们中的每一个都需要分配内存才能以这种方式使用:

strcpy(name[i], token);

内存分配示例:

for(int i=0;i<7;i++)
{
    name[i] = malloc((maxNameLen+1)*sizeof(name[i]));
    if(!name[i]) 
    {
        //handle error
    }
}
//now each pointer has space for up to maxNameLen+1 characters

Non-editable 字符串:

char *st = "Addison,Jayden,Sofia,Michael,Andrew,Lily,Benjamin";

要编辑的字符串不能是这种形式(即string literal)。它必须是可编辑的形式,以便 strtok() 更改 它,就像在解析时一样。有很多string形式可以编辑,这里有两个例子:

//Create an editable form:
char st[] = {"Addison,Jayden,Sofia,Michael,Andrew,Lily,Benjamin"};

//Create an editable copy of original: (requires freeing when done using)
char *duplicate = strdup(st);
if(duplicate)
{
    //success duplicating, now parse duplicate.

another discussion here 解释 editable/non-editable C 中的字符串。