如何在C中动态扩展字符串

时间:2010-03-18 08:45:57

标签: c string malloc

我有一个递归地对一组数字进行一些计算的函数。我还希望通过传递前一次计算中的字符串并将其与当前操作连接来在每次递归调用中打印计算。示例输出可能如下所示:

3
(3) + 2
((3) + 2) / 4
(((3) + 2) / 4) x 5
((((3) + 2) / 4) x 5) + 14
... and so on

所以基本上,第二个调用得到3并且向它追加+ 2,第三个调用被传递(3)+ 2等等。我的递归函数原型看起来像这样:

void calc_rec(int input[], int length, char * previous_string);

我写了一个2个辅助函数来帮助我进行操作,但是当我测试它们时它们会崩溃:

/**********************************************************************
 * dynamically allocate and append new string to old string and return a pointer to it
 **********************************************************************/
 char * strapp(char * old, char * new)
 {
     // find the size of the string to allocate
     int len = sizeof(char) * (strlen(old) + strlen(new));

     // allocate a pointer to the new string
     char * out = (char*)malloc(len);

     // concat both strings and return
     sprintf(out, "%s%s", old, new);

     return out;
 }

/**********************************************************************
 * returns a pretty math representation of the calculation op
 **********************************************************************/
 char * mathop(char * old, char operand, int num)
 {
     char * output, *newout;
     char fstr[50]; // random guess.. couldn't think of a better way.
     sprintf(fstr, " %c %d", operand, num);
     output = strapp(old, fstr);
     newout = (char*)malloc( 2*sizeof(char)+sizeof(output) );
     sprintf(newout, "(%s)", output);
     free(output);
     return newout;  
 }


void test_mathop()
{
    int i, total = 10;
    char * first = "3";
    printf("in test_mathop\n");
    while (i < total)
    {
        first = mathop(first, "+", i);
        printf("%s\n", first);
        ++i;
    }
}

strapp()返回一个指向新附加字符串(工作)的指针,mathop()应该使用旧计算字符串(“(3)+2”),一个字符操作数('+',' - '等等)和一个int,并返回一个指向新字符串的指针,例如“((3)+2)/ 3”。知道我搞砸了什么吗?感谢。

4 个答案:

答案 0 :(得分:4)

您应该为终止0分配一个额外的字节。

你应该在这里使用strlen代替sizeof

newout = (char*)malloc( 2*sizeof(char)+sizeof(output) );

Sizeof返回char*的大小(在平均系统上大小为4),而不是output指向的字符串的长度。

此外,正如@Agnel正确指出的那样,i未初始化,虽然这不会导致程序崩溃,但只需执行循环一次。

此外,我建议 strstr strcat来连接字符串。

答案 1 :(得分:2)

我能看到的一个直接问题是:

int len = sizeof(char) * (strlen(old) + strlen(new));

最后没有为NULL char分配空间。所以你需要分配一个额外的char。

答案 2 :(得分:2)

首先尝试这个:

char * append_strings(const char * old, const char * new)
{
    // find the size of the string to allocate
    size_t len = strlen(old) + strlen(new) + 1;

    // allocate a pointer to the new string
    char *out = malloc(len);

    // concat both strings and return
    sprintf(out, "%s%s", old, new);

    return out;
}

这只是您的代码,有许多修复:

  • 输入字符串未更改,因此应将其声明为const
  • 添加一个新缓冲区所需的大小,以便为终结符留出空间。
  • 字符串长度最好存储在size_t类型的变量中。
  • sizeof (char)删除了不必要的缩放。
  • 请勿投回malloc()
  • 不要定义名称以str开头的函数,即保留空格。评论者指出,谢谢!

对于性能,您可以利用这两个输入上的strlen()调用这一事实,并避免使用sprintf()

char * append_strings(const char * old, const char * new)
{
    // find the size of the string to allocate
    const size_t old_len = strlen(old), new_len = strlen(new);
    const size_t out_len = old_len + new_len + 1;

    // allocate a pointer to the new string
    char *out = malloc(out_len);

    // concat both strings and return
    memcpy(out, old, old_len);
    memcpy(out + old_len, new, new_len + 1);

    return out;
}

这应该更快一些,但我没有对它进行基准测试。请注意最终memcpy()如何包含new字符串中的终结符,因此无需手动设置它。

答案 3 :(得分:0)

感谢所有回复,他们非常有帮助 - 尤其是strcat建议,并发现我需要为'\ 0'字符分配空间。我最终使用realloc来“拉伸”字符串并附加前导和尾随字符。我还删除了strapp(append_strings)函数,并将其全部用于mathop。方法如下:

/**********************************************************************
 * returns a pretty math representation of the calculation op
 **********************************************************************/
 char * mathop(char * previous, char operand, float num)
 {
     char *output, *temp, calculation[50];
     size_t newlen;

     // copy the previous data into the temp string     
     temp = (char*)malloc( strlen(previous) + 1 );
     output = (char*)malloc(2);

     strcpy(temp, previous);
     strcpy(output, "(\0");

     // create the string portion to append to the output
     sprintf(calculation, " %c %.1f)\0", operand, num);

     // reallocate the output to append the additional string
     newlen = strlen(temp) + strlen(calculation) + 1;
     temp = realloc(temp, newlen);

     // append the new data to output
     strcat(temp, calculation);
     output = realloc(output, strlen(temp) + 2);
     strcat(output, temp);
     printf("%s\n", output);

     free(temp);
     return output;  
 }

再次感谢!