【问题标题】:How do i copy a string that has been dynamically allocated to another string that has been dynamically allocated?如何将已动态分配的字符串复制到已动态分配的另一个字符串?
【发布时间】:2019-09-15 06:33:12
【问题描述】:

我在尝试实现自定义 strcpy 函数时遇到了麻烦,该函数应该处理 src 字符串大于目标字符串的情况。在这里,我提供了一些代码,以便你们可以看到整个功能。我的问题是,每次我增加 *dest 时,它都会进入一个空地址,尽管我已经分配了足够的内存来容纳其中的所有 src。这会导致(双指针)dest = *src 中的分段错误。 dest 存储为 char** 因为实际上,必须传递的参数是另一个可能比 src 更小的字符串,我希望尽可能安全地覆盖 *dest。

int customStrCpy(char** dest, char* src){
    int strlen1 = strlen(*dest), strlen2 = strlen(src);
    if(strlen1 < strlen2){
        //Creates a dynamically allocated array that is big enough to    store the contents of line2.
        *dest = calloc(strlen2, sizeof(char));
        char* backup_str = *dest;

        int copy_arrs;
        for(copy_arrs = 0; copy_arrs < strlen2; copy_arrs++){
            **dest = *src;
            *dest++; src++;
        }
        *dest = backup_str;
    }
    else strcpy(*dest, src);
}

最后,(char**)dest 应该指向正确的字符串。

【问题讨论】:

  • strlen 返回的结果比您想要的少。注意终止\0。还有 - dest 在传递给这个函数时总是指向一个有效的字符串吗?
  • strlen(*dest) 只会告诉您 *dest 中的当前字符数。如果它是在调用您的方法之前分配的,那么如果不将该长度传递给您的方法,您就无法知道分配了多少空间。
  • 你确实意识到这个功能,即使你修复了它,基本上也是一个内存泄漏工厂?
  • 如果用新分配的字符串替换目标字符串,还应该释放原始分配。
  • 为什么不在calloc() 之后使用strcpy()?另外,如果要立即覆盖它,为什么要使用calloc() 而不是malloc()

标签: c strcpy


【解决方案1】:

通常strcpy 返回char * 以“直接”用于其他操作。

char *mysStrCpy(char **dest, const char *src)
{
    size_t len = strlen(src);
    char *tmpptr;

    *dest = malloc(len + 1);
    // or *dest = realloc(*dest, len + 1);
    if(*dest)
    {
        tmpptr = *dest;
        while(*tmpptr++ = *src++);
    }
    return *dest;
}

【讨论】:

    【解决方案2】:

    您需要将1 添加到字符串长度,以允许空终止符,如果您要分配新字符串,您应该释放dest 的旧内容。完成此操作后,您可以执行与不需要重新分配时相同的strcpy()

    也不需要int 返回类型(除非您想向malloc() 添加错误检查,并返回状态结果)。这个函数修改了一个参数,应该是void

    void customStrCpy(char** dest, char* src){
        int strlen1 = strlen(*dest), strlen2 = strlen(src);
        if(strlen1 < strlen2){
            free(*dest); // Free the old string
            //Creates a dynamically allocated array that is big enough to store the contents of line2.
            *dest = malloc(strlen2+1);
        }
        strcpy(*dest, src); // or memcpy(*dest, src, strlen2+1);
    }
    

    【讨论】:

    • 现在我们只需要返回一些有用的东西……另外,strcpy() 当你知道长度时?
    • 使用strncpy() 并没有什么收获,因为你知道它会很合适。可以使用memcpy()。我不会担心这个。
    • void int 不合逻辑。使用 strlen 来确定是否还有足够的空间 - 目标字符串可能会在调用之前多次更改。
    • @P__J__ 我不是在质疑这个问题的基本前提。
    • @Barmar 我尝试使用 memcpy、strcpy、strncpy 等...在尝试将较大的字符串复制到较小的字符串(包括目标字符串和源字符串)时,它们都完全搞砸了字符串.
    【解决方案3】:
     *dest++;
    

    递增 dest,而不是 dest 指向的指针。你想要:

    (*dest)++;
    

    ps:有更好的方法来完成你所追求的......

    【讨论】:

    • 如果你增加dest指向的指针,那么调用者将不会得到一个指向返回字符串开头的指针,他们会得到一个指向它结尾的指针。
    • 正确的解决方案是为此使用局部变量,而不是调用者的指针。或者直接致电strcpy()
    • 他似乎希望它指向字符串的末尾;但是是的,在评论中他说了一些不同的话。
    • 其实,不,你错了。这就是 backup_str 的作用。
    • 糟糕,没注意到。如果您编辑答案,我可以取消投票。
    猜你喜欢
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-09
    相关资源
    最近更新 更多