1

我有一个非常简单的功能,这给我带来了一些问题。我要做的就是在从字符串更改子字符串后返回一个子字符串。但是当我运行代码时,我遇到了分段错误。我的代码发生了什么:

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

const char *new_name(char str[])
{

  char * pch;
  char * last="";
  char * pch2;
  static char name[80];
  printf ("Splitting string \"%s\" into tokens:\n",str);

  pch = strtok (str,"/");
  while (pch != NULL)
  {
     last=pch;
     pch = strtok (NULL, "/");

  }

  pch2 = strtok (last,".");
  strcpy(name, pch2);
  strcat(name, ".ppm");

  return name; 
}

int main()
{
  printf("New name: %s",new_name("/home/test/segmentation/test.pgm"));
  return 0;

}

编辑:我还有一个问题:我想使用这个函数的返回作为另一个函数的输入,但它接受 char 并且返回的值是 const char。如何进行转换?

4

6 回答 6

3

崩溃发生在 strtok 中。问题是您将指向字符串文字的指针作为其第一个参数传递,而字符串文字通常位于只读内存中,因此strtok在尝试更改字符串时会崩溃。

char *strtok(char *str, const char *delim);

一种解决方法:

char fileName[] = "/home/test/segmentation/test.pgm";
printf("New name: %s",new_name(fileName));

编辑:在“编辑”下方回答您的问题。

只需将函数的签名更改为 return char *

char *new_name(char str[])

不过,再多修改一点就好了。与其使用本地静态缓冲区(name),不如将缓冲区作为第二个参数传递,并在调用函数之前在客户端代码中分配它。这种方法的问题是调用者通常不知道要生成的字符串的确切长度甚至最大长度。

另一个可能更好的选择是分配缓冲区的内存以动态malloc返回,并将指向它的指针返回给调用者。在这种情况下,释放缓冲区的责任将由用户代码负责,因此您应该正确记录它。

于 2013-11-04T13:54:19.850 回答
2

您必须记住该strtok函数会修改字符串输入。然后你将一个指针传递给一个常量(即只读)的文字字符串。尝试修改文字字符串会导致未定义的行为。

解决方案非常简单:

char str[] = "...";
printf("New name: %s\n", new_name(str));
于 2013-11-04T13:53:40.470 回答
2

strtok通过改变它传递的字符串来工作。您不能将常量字符串传递给strtok.

你可以试试

char str[] = "/home/test/segmentation/test.pgm";
printf("New name: %s",new_name(str));

反而。

于 2013-11-04T13:54:03.083 回答
2

strtok将修改其第一个参数,因此您不能将指向字符串文字的指针传递给它,这将调用未定义的行为。

将前两行更改为main

char str[] = "/home/test/segmentation/test.pgm";
printf("New name: %s\n",new_name(str));
于 2013-11-04T13:54:53.900 回答
1

strtok的第一个参数不能是常量字符串(这就是字符串文字):

pch = strtok (str,"/");
              ^^^

因为它修改了它的第一个参数,所以链接的文档说:

char *strtok( char *restrict str, const char *restrict delim );

这个函数是破坏性的:它在字符串 str 的元素中写入 '\0' 字符。特别是,字符串文字不能用作 strtok 的第一个参数。

使用非常量数组将解决此问题:

char arr[]  = "/home/test/segmentation/test.pgm" ;
printf("New name: %s",newname(arr));

为了完整起见,修改字符串文字未定义的行为,C99 标准草案在6.4.5 字符串文字6段中说(强调我的):

如果它们的元素具有适当的值,则未指定这些数组是否不同。如果程序试图修改这样的数组,则行为是 undefined

于 2013-11-04T13:53:48.487 回答
1

new_name("/home/test/segmentation/test.pgm")

您正在传递字符串文字(只读),并且strtok正在修改此字符串

于 2013-11-04T13:54:40.243 回答