【问题标题】:Why does strtok cause a segfault in my program?为什么 strtok 会导致我的程序出现段错误?
【发布时间】:2021-04-08 04:51:33
【问题描述】:

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

有问题的行是一个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"} 这不是您在数组中存储多个字符串的方式,请在帖子关闭之前提供最小可重复的代码版本
  • strtok 期望得到一个包含分隔符的字符串。由于缺少 nul 终止符,您没有提供有效的 C 字符串:char delim[2] = ", ";

标签: c parsing segmentation-fault token strtok


【解决方案1】:
char strArr[2] = {"1, 2, 3, 4, 5", "4, 5, 6, 7, 8"};

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


如果你实际上是char *strArr ...(一个指针数组),那也行不通。修改字符串字面量是未定义的行为,这就是 strtok 通常用来编织其魔力的方法。


为了解决那个问题(假设你已经这样做了),你可以使用与以下sn-p相同的技巧:

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, 2, 3, 4, 5", "4, 5, 6, 7, 8"}

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


如果你想避免指定第二维的大小和可能带来的浪费,你可以(正如 rici 在评论中指出的那样)使用复合文字来初始化 char 指针数组元素这样它们可写的:

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

【讨论】:

  • 你说得对,它实际上定义为:char *A[] = {"1, 3, 4, 7, 13", "1, 2, 4, 13, 15"}; 如何将它们变成普通字符串以便开始操作它们?
  • @makeartandlove 也许char A[2][42] = {"1, 3, 4, 7, 13", "1, 2, 4, 13, 15"};
  • 为了避免计算字符:char *strArr[] = {(char[]){"1, 2, 3, 4, 5"}, (char[]){"4, 5, 6, 7, 8"}};
  • @rici,在 C 中,强制转换类型必须是标量,因此不允许使用聚合类型(如数组)。即使这不是问题,字符串文字仍然存在同样的问题 - 转换不会创建 new 对象,它只是将对象重新解释为其他东西。因此,后备内存的不可写性可能仍然会导致问题。
  • @paxdiablo:这不是演员表;这是一个复合文字。语义与static char <anonymous>[] = {"..."} 相同,因此它不是字符串文字。
猜你喜欢
  • 2020-04-15
  • 1970-01-01
  • 1970-01-01
  • 2021-02-21
  • 2013-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多