下面的代码昨天编译得很好,有一段时间开始给出abort trap: 6错误,然后又正常工作了一段时间,然后又开始给出同样的错误。我所查到的所有答案都涉及固定长度的字符串。我在编程方面不是很有经验,所以对于为什么会发生这种情况,我们表示感谢。(代码用于计算Zeckendorf表示。)
如果我只使用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;
}发布于 2017-06-10 23:24:14
基本上,当您想从C中的函数接收字符串时,有两种方法
在您的示例中,zeckendorf()函数可以确定字符串需要多少内存。第一个斐波那契数小于参数的指标决定了结果的长度。添加1用于终止零,您知道需要分配多少内存。
因此,如果选择第一种方法,则需要向zeckendorf()函数传递额外的两个参数:char *buffer和int size,并写入缓冲区instead of ans。您需要有一些标记来知道它是否是while()循环的第一次迭代。如果是,则在maxfib(n, &index, &fib);之后检查条件index+1<=size。如果条件为真,则可以继续执行您的函数。如果没有,您可以立即返回错误。
对于第二种方法,将ans初始化为:
char *ans = NULL;在maxfib(n, &index, &fib);之后添加:
if(ans==NULL) {
ans=malloc(index+1);
}像你那样继续。从函数返回ans。当不再需要结果以避免内存泄漏时,请记住在调用方中调用free()。
在这两种情况下,都记得将终止\0写到缓冲区。
还有第三种方法。您可以将ans声明为:
static char ans[20];在zeckendorf()内部。函数的行为应与第一种方法相同,但缓冲区及其大小已被硬编码。我建议#define BUFSIZE 20,或者将变量声明为static char ans[BUFSIZE];,并在检查可用大小时使用BUFSIZE。请注意,它只在单线程环境中工作。每次对zeckendorf()的调用都会覆盖前面的结果。考虑遵循以下代码。
char *a,*b;
a=zeckendorf(10);
b=zeckendorf(15);
printf("%s\n",a);
printf("%s\n",b);zeckendorf()函数总是返回相同的指针。因此,a和b将指向同一个缓冲区,其中将存储用于15的字符串。因此,您需要将结果存储在某个地方,或者按照正确的顺序进行处理:
a=zeckendorf(10);
printf("%s\n",a);
b=zeckendorf(15);
printf("%s\n",b);作为经验法则,大多数(如果不是全部) Linux标准C库函数都使用第一或第三种方法。
发布于 2017-06-10 22:21:41
你的猜测是非常正确的:
char *ans = ""; // I'm guessing the error is coming from here这使得ans指向一个字符的只读数组,该数组的唯一元素是字符串终止符。试图附加到这将超出界限,并给您未定义的行为。
一种解决方案是对字符串进行动态分配内存,如果事先不知道大小,则需要重新分配来增加大小。如果您这样做,不要忘记为字符串终止符添加空间,并在完成之后添加到释放记忆。
https://stackoverflow.com/questions/44478579
复制相似问题