下面的代码昨天编译得很好,有一段时间开始出现abort trap: 6错误,然后又运行了一段时间,然后再次出现相同的错误。我查过的所有答案都是关于固定长度的字符串我不是很有经验的编程,所以任何帮助,为什么这是发生的赞赏。(代码用于计算Zeckendorf representation
如果我只是使用printf逐个打印数字,而不是使用字符串,代码就可以正常工作。

#include <string.h>

// helper function to compute the largest fibonacci number <= n
// this works fine
void maxfib(int n, int *index, int *fib) {
    int fib1 = 0;
    int fib2 = 1;
    int new = fib1 + fib2;
    *index = 2;
    while (new <= n) {
        fib1 = fib2;
        fib2 = new;
        new = fib1 + fib2;
        (*index)++;
        if (new == n) {
            *fib = new;
        }
    }
    *fib = fib2;
    (*index)--;
}

char *zeckendorf(int n) {
    int index;
    int newindex;
    int fib;
    char *ans = "";  // I'm guessing the error is coming from here
    while (n > 0) {
        maxfib(n, &index, &fib);
        n -= fib;
        maxfib(n, &newindex, &fib);
        strcat(ans, "1");
        for (int j = index - 1; j > newindex; j--) {
            strcat(ans, "0");
        }
    }
    return ans;
}

最佳答案

基本上,当您想从C语言中的函数接收字符串时,有两种方法
调用者分配缓冲区(静态或动态)并将其作为指针和大小传递给被调用者。被调用方将数据写入缓冲区。如果合适,它将返回成功状态。如果不适合,则返回错误。在这种情况下,您可以决定缓冲区是未触及的,或者它包含符合大小的所有数据。你可以选择任何更适合你的东西,只要为将来的用户(包括将来的你)正确地记录下来就行了。
被调用方动态分配缓冲区,填充缓冲区并返回指向缓冲区的指针。调用者必须释放内存以避免内存泄漏。
在您的情况下,zeckendorf()函数可以确定字符串需要多少内存。第一个Fibonacci数小于参数的索引决定了结果的长度。加1表示终止零,您就知道需要分配多少内存。
因此,如果选择第一种方法,则需要将另外两个参数传递给zeckendorf()函数:char *bufferint size并写入instead的缓冲区。您需要有一些标记来知道它是否是ans循环的第一次迭代。如果是,在while()之后检查条件maxfib(n, &index, &fib);。如果条件为真,则可以继续执行函数。否则,您可以立即返回错误。
对于第二种方法,将index+1<=size初始化为:

char *ans = NULL;

ans之后添加:
if(ans==NULL) {
    ans=malloc(index+1);
}

像你一样继续。从函数返回maxfib(n, &index, &fib);。当不再需要结果以避免内存泄漏时,请记住在调用方中调用ans
在这两种情况下,请记住将终止free()写入缓冲区。
还有第三种方法。您可以将ans声明为:
static char ans[20];

内部\0。函数的行为应与第一种方法相同,但缓冲区及其大小已硬编码。我建议zeckendorf()并将变量声明为#define BUFSIZE 20并在检查可用大小时使用static char ans[BUFSIZE];。请注意,它只在单线程环境中工作。每次调用BUFSIZE都将覆盖以前的结果。考虑下面的代码。
char *a,*b;
a=zeckendorf(10);
b=zeckendorf(15);
printf("%s\n",a);
printf("%s\n",b);

zeckendorf()函数总是返回相同的指针。因此zeckendorf()a将指向同一个缓冲区,其中存储b的字符串。因此,您要么需要将结果存储在某个地方,要么按照正确的顺序进行处理:
a=zeckendorf(10);
printf("%s\n",a);
b=zeckendorf(15);
printf("%s\n",b);

根据经验,大多数(如果不是全部)Linux标准C库函数使用第一种或第三种方法。

10-04 14:13