这是一个将斐波那契数字加在一起的程序。有问题的功能是hugeAdd。整数正确加到8,但是一旦达到13或更高,就会返回不正确的值。错误的值是进位(1)的内存地址,但是正确的是1(3)的位置。但是,尝试手动设置它,由于某种原因,它似乎不起作用,因为即使在for循环中也无法调用在for语句中声明的计数器变量'k'。
注意:这是我能制造的最小的MCVE。在Fibonacci.c中的第134行处插入一个断点,它将打印出添加的整数。
Fibonacci.h(这是包含struct def等的头文件)
#ifndef __FIBONACCI_H
#define __FIBONACCI_H
typedef struct HugeInteger
{
// a dynamically allocated array to hold the digits of a huge integer
int *digits;
// the number of digits in the huge integer (approx. equal to arraylength)
int length;
} HugeInteger;
// Functional Prototypes
HugeInteger *hugeAdd(HugeInteger *p, HugeInteger *q);
HugeInteger *hugeDestroyer(HugeInteger *p);
HugeInteger *parseString(char *str);
HugeInteger *parseInt(unsigned int n);
unsigned int *toUnsignedInt(HugeInteger *p);
HugeInteger *fib(int n);
double difficultyRating(void);
double hoursSpent(void);
#endif
Testcase4.c类(包含主函数和测试用例到测试函数)
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "Fibonacci.h"
// print a HugeInteger (followed by a newline character)
void hugePrint(HugeInteger *p)
{
int i;
if (p == NULL || p->digits == NULL)
{
printf("(null pointer)\n");
return;
}
for (i = p->length - 1; i >= 0; i--)
printf("%d", p->digits[i]);
printf("\n");
}
int main(void)
{
int i;
HugeInteger *p;
for (i = 0; i <= 1000; i++)
{
printf("F(%d) = ", i);
hugePrint(p = fib(i));
//p = fib(i);
//hugeDestroyer(p);
}
return 0;
}
Fibonacci.c类(此类具有运行testcase4.c的所有功能)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#include "Fibonacci.h"
HugeInteger *hugeAdd(HugeInteger *p, HugeInteger *q)
{
HugeInteger *hugerInt = malloc(sizeof(HugeInteger));
int overhead=1,i,j,results=0;
int *resultArray = NULL;
if(p == NULL || q == NULL || hugerInt == NULL)
{
return NULL;
}
if(p->length > q->length)
{
resultArray = calloc(((p->length)+ overhead), sizeof(int));
hugerInt->length = p->length;
hugerInt->digits = malloc(sizeof(int) * (p->length + overhead));
if(resultArray == NULL)
{
return NULL;
}
for(int k=0; k < p->length; k++)
{
if(k >= q->length)
{
results=p->digits[k]; //check for not skipping smaller int
resultArray[k] = results + resultArray[k];
}
else{
results = p->digits[k] + q->digits[k];
if(results > 9 )
{
if(p->digits[k+1] == 0)
{
hugerInt->digits[k+1] = 1;
}
resultArray[k+1] = resultArray[k+1] + 1;
results = results - 10;
printf("length of resultArray is %d\n",p->length+1);
}
resultArray[k] = results;
}
}
}
else
{
resultArray = calloc(((p->length)+ overhead)+ 1, sizeof(int));
hugerInt->length = q->length;
hugerInt->digits = malloc(sizeof(int) * (q->length)+ overhead);
if(resultArray == NULL)
{
return NULL;
}
for(i=0; i < q->length; i++)
{
// printf("q length %d", q->length);
if(i >= p->length) // Check if second struct passed is smaller then first one passed
{
results=q->digits[i]; //check for not skipping smaller int
resultArray[i] = results;
}
else{
results = q->digits[i] + p->digits[i];
if(results > 9 )
{
printf("I is in larger then 9 check %d", i);
if(p->digits[i+1] == 0)
{
hugerInt->digits[i+1] = 1;
}
printf("i is %d\n",i);
printf("Assigning 1 to %d in resultarray\n", i);
resultArray[i+1] = 1; // if value is greater then 9 the 1 carries and gets added to the result.(This is the part i think is going wrong)
results = results - 10;
printf("length of resultArray is %d\n",p->length+1);
printf("results:$d\n", results);
}
resultArray[i] = results; // Throws added values into array
}
}
}
printf("\n=================\n");
for(i=0; i < hugerInt->length; i++)
{
hugerInt->digits[i] = resultArray[i];
}
printf("Result array at 0 is %d\n", resultArray[0]); // This is were the
printf("Result array at 1 is %d\n", resultArray[1]); // added numbers are stored.
printf("Result array at 2 is %d\n", resultArray[2]);
printf("=====================\n");
free(resultArray);
return hugerInt;
}
HugeInteger *fib(int n)
{
HugeInteger *fibInt = malloc(sizeof(HugeInteger));
HugeInteger *fatherFib = malloc(sizeof(HugeInteger));
HugeInteger *grandfatherFib = malloc(sizeof(HugeInteger));
int j=1,fatherLength=0,grandfatherLength=0,fibLength=0,result, overhead=1;
unsigned int father, grandFather, fib, tempFather, tempGrandfather, tempFib;
fatherFib->digits = calloc((n + overhead),sizeof(int) );
fibInt->digits = calloc((n+overhead),sizeof(int));
grandfatherFib->digits = calloc((n + overhead),sizeof(int) );
fatherFib->length = 1;
grandfatherFib->length = 1;
fibInt->length = 1;
if(n == 0)
{
fibInt->digits[0] = 0;
return fibInt;
}
for(int i=0; i < n; i++)
{
if(i >= 1)
{
if(fatherFib->digits[0] >= 5 && grandfatherFib->digits[0] >= 5)
{
fibInt->length = 2;
}
else if(fatherFib->digits[1] >= 5 && grandfatherFib->digits[1] >= 5)
{
fibInt->length = 3;
}
}
if(i == 0)
{
fatherFib->digits[0]= 0;
grandfatherFib->digits[0]=1;
}
fibInt = hugeAdd(fatherFib,grandfatherFib);
grandfatherFib = fatherFib;
if(fibInt->length == 2)
{
printf("tens value in father fib %d\n", fatherFib->digits[1]);
}
fatherFib = fibInt;
}
free(grandfatherFib->digits);
free(grandFatherFib);
return fatherFib;
}
int power(int base, int numTimes)
{
int result=1,i=0;
if(numTimes == 1)
{
return base;
}
for(;i < numTimes; i++)
{
result = result * base;
}
return result;
}
答案 0 :(得分:2)
在编译代码时考虑警告/错误:(在问题版本之前)
在Fibonacci.c
else if(strlen(str) == 0 && str[0] == "")
str[0]
是 char ,str[0] == ""
从来都不是真的,只是这样做
else if (str[0] == 0)
在
HugeInteger *hugeDestroyer(HugeInteger *p) { int length; // printf("Hiiting destroyer"); if(p == NULL) { return; } length = p->length; free(p->digits); // But this works??????? free(p->length); free(p); }
您永远不会返回值(指向 HugeInteger 的指针),显然它必须具有签名void hugeDestroyer(HugeInteger *p)
(也在标头中)
在
free(p->length);
您释放了 int 吗?
删除该行以及其他关于 length
的无用行那么最后
void hugeDestroyer(HugeInteger *p)
{
// printf("Hiiting destroyer");
if (p != NULL)
{
free(p->digits); // But this works???????
free(p);
}
}
在
unsigned long long int check = malloc(sizeof(unsigned long long int));
malloc 返回一个地址(指针),实际上您没有使用 check (check = nextPow + real
也没有用)
难以想象您想做什么,请删除有关 check
的所有内容在
if(p->digits[k+1] == NULL) ... if(p->digits[i+1] == NULL)
p->digits[k+1]
是 int ,您将其与指针进行比较,将 NULL 替换为0
在
hugePrint(fibInt);
未知,声明缺失
编译时要求较高的警告/错误检测级别,并根据
纠正代码关于内存泄漏:
在 hugeAdd
HugeInteger *test = malloc(sizeof(HugeInteger)); test->length= 1; test->digits = malloc(sizeof(int)); test->digits[0] = 5;
test 永远不会使用,您只会造成内存泄漏
resultArray = calloc(((p->length)+ overhead), sizeof(int));
您设置了内容,但从未释放它,这是另一个内存泄漏
在 fib
HugeInteger *grandfatherFib = malloc(sizeof(HugeInteger));
您从不释放 grandfatherFib 这是另一个内存泄漏
关于结果:
您的问题是,您不能很好地添加至少2位数字,例如,如果我将 hugeAdd 的结尾稍加更改以替换
printf("Result array at 0 is %d\n", resultArray[0]); // This is were the printf("Result array at 1 is %d\n", resultArray[1]); // added numbers are stored. printf("Result array at 2 is %d\n", resultArray[2]); printf("=====================\n");
更实用
printf("=====================\n");
hugePrint(p);
puts("+");
hugePrint(q);
puts("=");
hugePrint(hugerInt);
printf("=====================\n");
然后我显示fib(8)
:
...
=====================
08
+
5
=
13
=====================
13
tens value in father fib 0
I is in larger then 9 check 0i is 0
Assigning 1 to 0 in resultarray
length of resultArray is 3
results:1
=================
=====================
13
+
08
=
11
=====================
您错过了加进位: 8 + 3 = 11 所以 1 和 1 进位添加到 1 以具有 21 而不是 11
拥有
if(results > 9 )
{
printf("I is in larger then 9 check %d", i);
if(p->digits[i+1] == 0)
{
hugerInt->digits[i+1] = 1;
}
不够,因为必须添加进位,如果值是0(没有别的,只有0变成1),则不能设置为1。当然,您可能需要考虑几个更改,将1的进位加到999会产生1000