2


我被要求制作 2 个函数 copyString 和 concatString 我做了并实现了它们,但是在我得到的输出中我被告知它可以做得更好,但从来没有解释过如何做。
现在它正在杀死我我能做的更好所以这里是代码,我很乐意听到任何建议。

void copyString (char **strDst, const char *strSrc)
{
     char *strTmp = NULL;
     int length = strlen (src);
     if (*strDst== NULL) 
     {
        *strDst= malloc (length);   
     }
     else 
     {  
         if (strlen(*strDst) != length)
         {
             strTmp = *strDst;
         }
         *strDst= malloc (length);  
     }
     strcpy (*strDst, strSrc);  
     if (strTmp != NULL)    
         free (strTmp );    
 }

void concatString (char **strDst, const char *cat)
{
     int cat_length = strlen (cat);
     if (cat_length > 0) 
     {  
         *strDst= realloc (*strDst, strlen (*strDst) + cat_length); 
          strcat (*strDst, cat);
     }
}




void main(int argc, char *argv[])
{
    char *str = NULL;
    copyString(&str, "Hello World");
    puts(str);
    copyString(&str,str+6);
    puts(str);
    concatString(&str, " Pesron");
}

输出应如下所示:
1.Hello World
2. World
3. World Person

谢谢。

4

2 回答 2

4

错误:

strlen返回不包括nul 终止符的长度,因此您分配的所有大小都太小。

在 whereif (strlen(*strDst) != length)为 false 的情况下(即长度相等),您会泄漏旧缓冲区。

realloc并且malloc都可能失败,您应该能够编写代码来应对这种情况。

正确的使用方法realloc是:

char *newbuf = realloc(oldbuf, newsize);
if (newbuf == NULL) {
    // handle the error somehow, and note that oldbuf is still allocated
} else {
    oldbuf = newbuf;
}

“以某种方式处理错误”可能需要决定做什么,这取决于你的两个函数的文档说它们在失败时会做什么。如果它没有说,那么它应该。

(Picky)int不能保证是足够大的类型来容纳字符串的长度。使用size_t(除非你被严格禁止使用无符号类型,在这种情况下有ssize_t)。

你可以改进的地方:

无需使用strTmp您的方式,您可以立即释放字符串,而不是在函数末尾。[编辑:是的,有必要,似乎有一个要求,copyString但不concatString应该允许源和目的地重叠。就个人而言,我仍然会稍微不同地写它。]

if (strTmp != NULL) free (strTmp );测试中是多余的,因为free使用空指针调用是有效的,这样做没有任何效果。

*strDst= malloc (length);在这两种情况下都在copyString.

main泄漏内存,因为它从不释放str

main应该返回int,不是void

以下是我可能会如何写它们:

由于您无法更改调用代码以使其检查错误,因此您必须在其中abort()编写可以调用的内容puts。由于该main函数是在假设调用不会失败的情况下编写的,abort()因此可能是最不坏的解决方案。

如果函数返回一个指示成功或失败的值,调用者可能会更好,但我们受到现有调用代码的限制。老实说,这并不是一个完全不切实际的情况来编程......

void concatString (char **strDst, const char *cat) {
    size_t dstlen = *strDst ? strlen(*strDst) : 0;
    char *buf = realloc(*strDst, dstlen + strlen(cat) + 1);
    if (!buf) {
        abort();
    }
    strcpy(buf + dstlen, cat);
    *strDst = buf;
}

void copyString (char **strDst, const char *strSrc) {
    char *buf = malloc(strlen(strSrc) + 1);
    if (!buf) {
        abort();
    }
    strcpy(buf, strSrc);
    free(*strDst);
    *strDst = buf;
}
于 2012-11-17T14:26:15.623 回答
0

除了史蒂夫杰索普在他的回答中提到的内容之外,您的资料中没有错误,但遗漏了:

  • 输入参数的验证
  • 通过错误值返回错误(例如作为函数的整数返回码,而不是void
于 2012-11-17T14:31:43.760 回答