2015-09-29 148 views
0

我正在学习C编程语言,我试图创建一个函数,它使一个子字符串,然后返回它。 我发现这个代码hereC:子字符串函数返回

void substring(char s[], char sub[], int p, int l) { 
    int c = 0; 

    while (c < l) { 
     sub[c] = s[p+c-1]; 
     c++; 
    } 
    sub[c] = '\0'; 
} 

我想在参数摆脱char sub[]的,而是返回函数的内部创建一个字符串。 这是最接近我认为我得到的,但我总是得到一个分段错误(核心转储)运行时错误。

char substring(char s[], int p, int l) { 
    int c = 0; 
    char sub[1000]; 

    while (c < l) { 
     sub[c] = s[p+c-1]; 
     c++; 
    } 
    sub[c] = '\0'; 

    return *sub; 
} 

感谢所有帮助

+2

您不能返回本地一*声明的字符串 - 它一旦函数结束时消失。这就是为什么原始代码使用第二个指针。如果你想返回持久化内存,使用'malloc'。 – usr2564301

+0

对于性能和内存负载的原因,我会尽可能使用原始字符串。在你的情况下,我只是返回这个子字符串的指针,它简化了所有'char * SubString = s + p;'其中p是开始位置。如果你以后真的需要拷贝,我不会重新发明轮子,并使用像memcpy(MySubStringCopy,SubString,l)这样的预定义方法;'Variable MySubStringCopy'可以在本地堆栈分配或堆分配。 – bkausbk

回答

3

如果你想回到你不应该返回单个字符的字符串,而是一个char *代替。如sub是本地字符数组,则不能简单地返回sub。如果你坚持从你的函数返回一个指针,你将需要分配动态内存。这将是调用者的责任,释放内存。因此,你应该做这样的事情:

// NOTE: caller takes ownership of the returned value 
char* substring(char s[], int p, int l) { 
    int c = 0; 
    char* sub = malloc(l + 1); 

    while (c < l) { 
     sub[c] = s[p+c-1]; 
     c++; 
    } 
    sub[c] = '\0'; 

    return sub; 
} 

注:感谢@ MOehm的评论我已经注意到了,没有必要分配固定大小的1000,当大小已知aforehand的字符串。不过这可能会导致逻辑上的改变,因此您可能需要更改其余的代码。

+0

是的,但为什么在长度已知时分配固定大小? –

+0

@Meehm我没有注意到我只是重写了原来的代码。我会反映你的评论。仍然改变分配大小可能反映在其他代码上(如果它期望大小为1000)。 –

+0

谢谢。我认为对尺寸的分配比较好。如果代码确实是“获取大小为1000的字符缓冲区并用子字符串填充第一个字节”,则应该首选通过缓冲区的原始变体。我想1000是一个意味着“足够大”的任意值。 –

2

问题:

  • 你的返回类型是char,这意味着你返回单个字符。这应该是char*,因为您想要返回一个指向字符串开头的指针。
  • 您正在使用本地声明的数组来保存结果。局部变量驻留在堆栈上,一旦函数返回就不可用。您需要使用malloc分配堆内存,将子字符串存储在该内存块中,然后返回指针。请注意,这意味着调用者需要拥有该块(即在不需要它之后,free)。

请注意,此实现不必要地强制调用方使用堆内存。如果调用者想把字符串放在别的地方(例如在一个内存映射文件中),他需要复制它。原始实现使用inout参数可能会避免这种折衷。

1

正如在其他答案中已经提到的,你不能返回指向局部变量的指针。最好的办法其实不是与内存分配关心自己所有,而是留给来电:

void substring (size_t index, 
       size_t length, 
       const char source[], 
       char dest[length+1]) 
{ 
    memcpy(dest, source + index, length); 
    dest[length] = '\0'; 
}