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

如何在C中动态扩展字符串,c,string,malloc,C,String,Malloc,我有一个函数,它递归地对一组数字进行计算。我还希望通过传递上一次计算中的字符串并将其与当前操作连接,在每次递归调用中漂亮地打印计算。示例输出可能如下所示: 3 (3) + 2 ((3) + 2) / 4 (((3) + 2) / 4) x 5 ((((3) + 2) / 4) x 5) + 14 ... and so on void calc_rec(int input[], int length, char * previous_string); 因此,基本上,第二个调用得到3并附加+2,

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

3
(3) + 2
((3) + 2) / 4
(((3) + 2) / 4) x 5
((((3) + 2) / 4) x 5) + 14
... and so on
void calc_rec(int input[], int length, char * previous_string);
因此,基本上,第二个调用得到3并附加+2,第三个调用通过(3)+2,等等。我的递归函数原型如下所示:

3
(3) + 2
((3) + 2) / 4
(((3) + 2) / 4) x 5
((((3) + 2) / 4) x 5) + 14
... and so on
void calc_rec(int input[], int length, char * previous_string);
我编写了两个帮助函数来帮助我进行操作,但当我测试它们时,它们会内爆:

/**********************************************************************
 * 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;
    }
}
/**********************************************************************
*动态分配新字符串并将其附加到旧字符串,并返回指向该字符串的指针
**********************************************************************/
字符*带(字符*旧,字符*新)
{
//查找要分配的字符串的大小
int len=sizeof(char)*(strlen(旧)+strlen(新));
//分配一个指向新字符串的指针
char*out=(char*)malloc(len);
//concat字符串和return
sprintf(输出,“%s%s”,旧的,新的);
返回;
}
/**********************************************************************
*返回计算操作的精确数学表示形式
**********************************************************************/
char*mathop(char*old,char操作数,int num)
{
字符*输出,*新输出;
char fstr[50];//随机猜测..想不出更好的方法了。
sprintf(fstr,“%c%d”,操作数,num);
输出=捆扎带(旧,fstr);
newout=(char*)malloc(2*sizeof(char)+sizeof(output));
sprintf(newout,(%s)”,输出;
自由(输出);
返回newout;
}
无效测试_mathop()
{
int i,总计=10;
char*first=“3”;
printf(“测试中”;
而(i

Strap()返回一个指向新附加字符串(works)的指针,mathop()应该接受旧的计算字符串(“(3)+2”)、字符操作数(“+”、“-”)和int,并返回指向新字符串的指针,例如“((3)+2)/3”。知道我把事情搞砸了吗?谢谢。

我能看到的一个紧迫问题是:

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

不为末尾的
NULL
字符分配空间。因此,您需要分配一个额外的字符。

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

您应该在此处使用
strlen
而不是
sizeof

newout = (char*)malloc( 2*sizeof(char)+sizeof(output) );
Sizeof返回
char*
(在一个平均系统中类似于4)的大小,而不是
输出所指向的字符串长度

此外,正如@Agnel正确指出的,
i
是未初始化的,尽管这不会使程序崩溃,但只需执行随机次数的循环即可


另外,我建议将字符串连接到
strstrstr
strcat

首先尝试以下方法:

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()


这应该会快一点,但我还没有做基准测试。请注意最后的
memcpy()
如何包含
新的
字符串中的终止符,因此无需手动设置它。

感谢所有的回复,它们非常有用-特别是strcat建议,并发现我需要为“\0”字符分配空间。最后,我使用realloc“拉伸”字符串并附加前导字符和尾随字符。我还消除了Strap(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;  
 }

再次感谢

sizeof(output)将提供指针的大小。与斯特伦大不相同。你还没有初始化我!!您可能应该删除sizeof(char),这只是一种写1的大方法,它会使事情变得混乱,并且(最坏的情况)会增加混乱。@Agnel为什么不添加这些作为答案呢?我想说,你应该为你的观察得到一些+:-)@Péter Török-我对这些回答不太自信。但是你有一点…空字符被sizeof(char)@kenny覆盖了不,不是。自己测试一下。@kenny:假设旧的是“1”,新的是“2”。两者的strlen值均为1。现在,您希望将它们连接成单个字符串。它应该容纳“1”、“2”和“\0”,以标记字符串的结尾。所以我们需要在字符串长度的总和上增加一个字符。我认为strstrstr是在另一个字符串中找到一个子字符串。他不仅必须为尾随的\0分配空间,而且还必须将\0放在那里。@sharptooth确实是一个很好的观点,值得明确提及。虽然strcat将自动处理它。从技术上讲,给函数命名以“str”开头是个坏主意。@sgm你是对的,但我想这应该是对原始问题的一个评论。@sgm:你完全正确,我将编辑它作为改进。