返回字符串的函数不起作用 - 分段错误

时间:2013-11-04 13:49:22

标签: c string segmentation-fault strtok

我有一个非常容易的功能,给我一些问题。我想要做的就是从字符串中更改后返回一个子字符串。但是当我运行代码时,我有分段错误。我的代码发生了什么:

#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。如何进行转换?

6 个答案:

答案 0 :(得分:3)

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

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

解决问题的一种方法:

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

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

只需更改函数的签名即可返回char *

char *new_name(char str[])

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

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

答案 1 :(得分:2)

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

解决方案非常简单:

char str[] = "...";
printf("New name: %s\n", new_name(str));

答案 2 :(得分:2)

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

你可以尝试

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

代替。

答案 3 :(得分:2)

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

main的前两行更改为:

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

答案 4 :(得分:1)

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

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

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

  

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

     
    

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

  

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

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

为了完整起见,修改字符串文字undefined behavior {C}标准草案6.4.5 字符串文字 6 < / em>说(强调我的):

  

如果这些数组的元素具有不同的数据,则未指定   适当的价值观如果程序试图修改这样的数组,则行为是   未定义

答案 5 :(得分:1)

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

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