一个实验题目,在TC++3.0下可以勉强调试完成,在Linux下则不行

JeffQChen 2007-10-04 02:07:27
题目是利用自己定义的数据结构来表示超大整数。我的想法是取模之后按位放进数组中。整个构想应该是没有问题,因为利用TC的步进调试最终得出的2^199是正确的。

问题出在如果不用步进的话,出来的结果会混有错误值,并且在一定时间就会出错。

在Linux下则是完全通过不了,第二次主程序循环的时候直接报错Segmentation Fault. 但是我查了源代码也没有看到明显的越界行为,十分困扰……请指教。


#include<stdio.h>
#include<math.h>

#define MAX_LARGE_DIGITS 1000
#define LARGE_INT_MODULE 10
typedef int* LargeInt ;

void Linit( LargeInt );
void LintToLarge( LargeInt , const int ) ;
int LtoInt( const LargeInt ) ;
void Lassign( LargeInt , const LargeInt ) ;
void Ladd( LargeInt , const LargeInt , const LargeInt ) ;
void Lscale( LargeInt , const LargeInt , const int ) ;
void Lprint( const LargeInt ) ;
int Lcompare( const LargeInt , const LargeInt ) ;
void Lcarry(LargeInt) ;

main()
{
LargeInt powerOf2 , temp ;
int i ;

/* Print table of powers of 2 */
Linit( powerOf2 );
Linit( temp );

LintToLarge( powerOf2 , 1 );

printf("Powers of 2 n 2^n\n");

for( i = 1 ; i <= 200 ; i++ )
{
printf(" %i ", i ) ;
Lprint( powerOf2 ) ;
printf("\n");
Ladd( temp, powerOf2, powerOf2 ) ;
Lassign( powerOf2 , temp );
}

return 0;
}

void Linit( LargeInt intVar )
{
int newArray[MAX_LARGE_DIGITS+2];

for(int i=0; i<=MAX_LARGE_DIGITS+1; i++)
newArray[i]=-1;

intVar=newArray;
}

void LintToLarge( LargeInt target , const int value )
{
int tempValue=value;

if(tempValue<0)
{
target[0]=-1;
tempValue*=-1;
}
else
target[0]=1;

target[1]=1;
target[2]=tempValue;
Lcarry(target);
}

int LtoInt( const LargeInt source )
{
if(source[1]>5)
{
printf("\nLarge Int too big to fit in int.");
return 0;
}

if(source[1]==5)
{
if(source[6]<=3)
{
if(source[5]<=2)
{
if(source[4]<=7)
{
if(source[3]<=6)
{
if(((source[2]<=7)&&(source[0]==1))||((source[2]<=8)&&(source[0]==-1))) ;
else
{
printf("\nLarge Int too big to fit in int.");
return 0;
}

}
}
}
}
}

int tempInt=0;

for(int i=source[1]+1; i>=2; i--)
tempInt*=LARGE_INT_MODULE+source[i];

return tempInt;
}

void Lassign( LargeInt target , const LargeInt source )
{
for(int i=0; i<=source[1]+1; i++)
target[i]=source[i];
}

void Ladd( LargeInt target , const LargeInt leftOp , const LargeInt rightOp )
{
target[0]=1;

int i;

for(i=2; i<=leftOp[1]+1; i++)
target[i]=leftOp[i]*leftOp[0];

for(i=2; i<=rightOp[1]+1; i++)
target[i]+=rightOp[i]*rightOp[0];

if(leftOp[1]>rightOp[1])
target[1]=leftOp[1];
else
target[1]=rightOp[1];

Lcarry(target);
}

void Lscale( LargeInt target , const LargeInt source , const int scaleBy )
{
target[0]=source[0];
target[1]=source[1];

for(int i=2; i<=source[1]+1; i++)
target[i]=source[i]*scaleBy;

Lcarry(target);
}

void Lprint( const LargeInt source )
{
if(source[0]==-1)
printf("-");

for(int i=source[1]+1; i>=2; i--)
printf ("%d", source[i]);
}

int Lcompare( const LargeInt leftOp , const LargeInt rightOp )
{
if(leftOp[0]>rightOp[0]) //if signs are different, the results are obvious
return 1;
else
{
if(leftOp[0]<rightOp[0])
return -1;
}

//Then, signs are the same, now look at absolute value

int abscompare=0;

if(leftOp[1]!=rightOp[1])
{
if(leftOp[1]>rightOp[1])
{
abscompare=1;
}
else
abscompare=-1;
}
else
{
for(int i=leftOp[1]+1; i>=2; i--)
{
if(leftOp[i]>rightOp[i])
{
abscompare=1;
break;
}
else
{
if(leftOp[i]<rightOp[i])
{
abscompare=-1;
break;
}
}
}
}

switch(abscompare)
{
case 0:
return 0;
case 1:
if(leftOp[0]>0)
return 1;
else
return -1;
case -1:
if(leftOp[0]>0)
return -1;
else
return 1;
}
}

void Lcarry (LargeInt source)
{
//Carry forward

int i,j;

if((source[2]>=LARGE_INT_MODULE)&&source[1]==1)
{
source[3]=source[2]/LARGE_INT_MODULE;
source[2]%=LARGE_INT_MODULE;
source[1]++;
}


for(i=2; i<=source[1]+1; i++)
{
j=i;

while(j<=source[1]+1)
{
source[j+1]+=source[j]/LARGE_INT_MODULE;
source[j]%=LARGE_INT_MODULE;

j++;

if(source[source[1]+1]>=LARGE_INT_MODULE)
{
source[source[1]+2]=source[source[1]+1]/LARGE_INT_MODULE;
source[source[1]+1]%=LARGE_INT_MODULE;
source[1]++;

if(source[1]>1000)
{
printf("\nCarry forward overflow!");
return;
}
}
}
}

//If top digit minus, flip all digits and sign

if(source[source[1]+1]<0)
{
for(i=2; i<=source[1]+1; i++)
source[i]*=-1;

source[0]*=-1;
}

//Carry backword

for(i=source[1]; i>=2; i--)
{
j=i;

while((source[j]<0)&&(j>=2))
{
source[j+1]-=(int)(log10(0-source[j])/(int)log10(LARGE_INT_MODULE)+1);
source[j]+=LARGE_INT_MODULE*(int)log10(0-source[j])/(int)log10(LARGE_INT_MODULE);
}
}

//Clear unused digits

i=source[1]+1;

while((source[i]==0)&&(i>=2))
source[1]--;
}
...全文
156 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
JeffQChen 2007-10-04
  • 打赏
  • 举报
回复
确实……

改了一下,把初始数组分配成全局……

void Linit( LargeInt intVar )
{
static int newArray[MAX_LARGE_DIGITS+2];

for(int i=0; i <=MAX_LARGE_DIGITS+1; i++)
newArray[i]=-1;

intVar=newArray;
}

混乱的问题没有了,不过自动运行的结果还是不错,我再看看……
chenzhiyubuaa 2007-10-04
  • 打赏
  • 举报
回复
void Linit( LargeInt intVar )
{
int newArray[MAX_LARGE_DIGITS+2];

for(int i=0; i<=MAX_LARGE_DIGITS+1; i++)
newArray[i]=-1;

intVar=newArray;
}
下面就没看了,这里返回了一个局部变量
JeffQChen 2007-10-04
  • 打赏
  • 举报
回复
帮别人看看作业的,所以随手拿了TC过来用,没想到给了小弟就没法在Linux上编译,自己找了一台改了一下也有问题……很久不写程序了,跟不上时代了……
believefym 2007-10-04
  • 打赏
  • 举报
回复
y tc????????????????
JeffQChen 2007-10-04
  • 打赏
  • 举报
回复
实验的详细规定在这里:

http://www.cdf.toronto.edu/~csc192h/fall/assignments/assignment2.pdf

表示大整数,将普通整数转换为大整数,进行加法,正确显示。基本上就是自己处理数字的简单模型。

我写的方式是偏向于伸缩性比较强的,进制可以调整预定义的值来改变(2/8/10/16进制测试都通过的)。进位和退位的动作也有定义,不过例程似乎只考虑了正数和加法,所以也没用上…… orz

33,317

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧