【问题标题】:Why might string concatenation prefix each concatenation with garbage?为什么字符串连接会在每个连接前加上垃圾?
【发布时间】:2010-10-03 15:05:39
【问题描述】:

我对 C 很陌生,所以如果这是非常标准的知识,我深表歉意..

我有一个这样的函数,我将一堆 C 风格的字符串附加在一起并输出:

char *example(int n, int days, int years){
    char *ret;
    if (n < 5) {
        ret = (char*)malloc(sizeof(char)*256);
        sprintf(ret, "There are %d days in %d years", days, years);
        ret = (char*)malloc(strlen(ret));
        return ret;
    }
    else {
        char *s1;
        char *s2;
        char *s3;
        s1 = example(n/2, days, years);
        s2 = example(n + 5, days, years);
        s3 = example(n--, days, years);

        int length = strlen(s1) + strlen(s2) + strlen(s3);
        ret = (char*)malloc(length);
        strcat(ret, s1);
        strcat(ret, s2);
        strcat(ret, s3);

        return ret;
       }
}

这是在每个新的串联前加上一些垃圾字符。我假设我的问题在于我的内存管理,但我不确定.. 这简单吗?我做错了什么?另外,这怎么能做得更干净?

【问题讨论】:

  • 哎呀!!!递归!!!你要去哪里释放所有的内存?
  • 好问题!你如何释放你这样返回的记忆?我可能应该想到的事情..

标签: c string memory memory-management


【解决方案1】:
char *example(int n, int days, int years){
   char *ret;
   if (n < 5) {
       ret = (char*)malloc(sizeof(char)*256);
       sprintf(ret, "There are %d days in %d years", days, years);
//     ret = (char*)malloc(strlen(ret));  (DELETE THIS LINE)
       return ret;
   }
   else {
       char *s1;
       char *s2;
       char *s3;
       s1 = example(n/2, days, years);
       s2 = example(n + 5, days, years);  // WILL THIS CAUSE INFINITE RECURSION?
       s3 = example(n--, days, years);

       int length = strlen(s1) + strlen(s2) + strlen(s3) + 1; // ALLOW ROOM FOR TERMINATING '\0'
       ret = (char*)malloc(length);
       strcpy(ret, s1);  // CHANGE TO strcpy()
       strcat(ret, s2);
       strcat(ret, s3);

       return ret;
   }
}

【讨论】:

  • 对无限递归感到抱歉,这是基于我自己的示例方法:) 不过你是对的。好收获!
【解决方案2】:

您分配一块内存,使用 sprintf 写入其中,然后丢弃第一个缓冲区并用未定义内容的新缓冲区替换它。

    ret = (char*)malloc(sizeof(char)*256);
    sprintf(ret, "There are %d days in %d years", days, years);
    ret = (char*)malloc(strlen(ret));
    return ret;

删除第三行可能会有所帮助。

【讨论】:

    【解决方案3】:

    这个

    ret = (char*)malloc(sizeof(char)*256);
    sprintf(ret, "There are %d days in %d years", days, years);
    ret = (char*)malloc(strlen(ret));
    

    正在分配一些内存,将字符串写入该内存,然后分配并返回未初始化的新内存。

    这个:

    ret = (char*)malloc(length);
    strcat(ret, s1);
    

    s1 附加到未初始化的ret。你需要做的

    ret[0] = '\0'
    

    分配内存后将其初始化为零长度字符串。

    【讨论】:

      【解决方案4】:

      strlen() 返回不包括终止零 ('\0') 的字符数。 分配内存时,您应该将 1 添加到 strlen() 以保存该零字符。

      您应该手动将 '\0' 放在字符串的开头,或者使用 strcpy() 而不是第一个 strcat()。

      【讨论】:

        【解决方案5】:

        你为什么写那个调用来重新分配字符串?

        ret = (char*)malloc(strlen(ret));
        

        你认为你在上面一行中放入该字符串的字符如何将其转移到新分配的内存中?

        拨打malloc 的第二个电话,看看是否有帮助。此外,当您在“else”子句中分配字符串时,您需要为终止空字符腾出空间,因此将“长度”加 1。在malloc 调用之后,将*ret 设置为0。

        【讨论】:

          【解决方案6】:

          我很久没用c了,但是...
          如果n &lt; 5 你有以下代码:

          ret = (char*)malloc(sizeof(char)*256);
          sprintf(ret, "There are %d days in %d years", days, years);
          ret = (char*)malloc(strlen(ret));
          

          为什么需要最后一行?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-11-10
            • 2012-12-06
            • 2020-12-18
            • 2010-09-21
            相关资源
            最近更新 更多