为什么 strtok 会导致我的程序出现段错误?

问题描述

我正在尝试构建一个函数,该函数接收两个数字字符串(如 char strArr[2] = {"1,2,3,4,5","4,5,6,7,8"})并解析它们。在编写我的函数时,我遇到了 seg 错误,我已经确定了导致 seg 错误的确切行,并省略了该行之后的所有内容

有问题的行是一个 strtok 调用,它接收第一个字符串和一个要拆分的分隔符。有谁知道这是怎么回事?

有问题的代码

void FindIntersection(char * strArr[]) { 

int nel1 = 1;
int nel2 = 1;
int i = 0;

/*Determine the number of elements in strArr[0] */
while(strArr[0][i] != '\0'){
    if(strArr[0][i] == ','){
        nel1++;
    }
    i++;
}

i = 0;
/* Determine the number of elements in strArr[1] */

while(strArr[1][i] != '\0'){
    if(strArr[1][i] == ','){
        nel2++;
    }
    i++;
}

int intArr1[nel1];
int intArr2[nel2];

/* parse the elements from each char array and place them in int arrays */

char delim[2] = ",";   
char *token;
token = strtok(strArr[0],delim);

解决方法

char strArr[2] = {"1,2,3,4,5","4,5,6,7,8"};

如果这是您的实际代码,那将不起作用 - 它会创建一个 char 数组,而不是一个 char 指针数组。 任何体面的编译器都应该抱怨这个。


如果你拥有的实际上是 char *strArr ...(一个指针数组),那也行不通。修改字符串文字是未定义的行为,这通常是 strtok 编织它的魔力。


为了解决那个问题(假设这就是您所做的),您可以使用与以下代码段相同的技巧:

char *x = "123";  // a pointer to string literal you should not modify.
char x[] = "123"; // a string array you can modify.

换句话说,您可以创建一个多维字符数组,而不是一个指向不可修改字符串文字的一维字符指针数组。

以下使用此方法为您提供了一组可修改的字符串,但您需要注意第二维对于将用于初始化数组的所有文字足够大(足够所有字符plus \0 字符串终止符还有一个):

char strArr[][14] = {"1,8"}

这也意味着,例如,如果您有一个大字符串和许多小字符串,则可能会浪费空间 - 每个都将分配最大大小。


如果您想避免指定第二个维度的大小以及随之而来的浪费,您可以(正如 rici 在评论中指出的那样)使用复合文字来初始化 char 指针数组 可写的元素:

char *strArr[] = {
    (char[]){"1,5"},(char[]){"4,8"},};