长整数加减实验报告.docx
《长整数加减实验报告.docx》由会员分享,可在线阅读,更多相关《长整数加减实验报告.docx(22页珍藏版)》请在冰点文库上搜索。
长整数加减实验报告
实验一线性表实现方法
题目:
编制一个长整数加减运算实现的程序
班级:
计科0603姓名:
李汉刚学号:
20064140303完成日期:
2008-4-13
一、需求分析
1、本实验中演示中,长整数的每位上的数字必须为数字[0——9]之间,长整数的位数要求无限长。
测试的时候输入数据,当输入回车键的时候结束输入,如果输入的字符不符合题目要求,则程序能过滤这些不符合要求的字符。
2、演示程序以用户和计算机的对话方式执行,即在计算机显示“提示信息”后之后,由用户在键盘上输入演示程序中规定的运算命令;相应的输入数据(滤去输入中不符合要求的字符)和运算结果显示在其后。
3、程序执行的命令包括:
(1)创建第一个长整数;
(2)执行加法或者减法;(3)创建第二个长整数;(4)结束。
4、测试数据
(1)PleaseEntertheFirstlongInteger:
12345678999999999999999
+or-:
+
PleaseEntertheSecondlongInteger:
98765432ht1111111111k11111111111
12345678999999999999999
+
98765432111111111111*********
=
98765444456780111111111111110
(2)PleaseEntertheFirstlongInteger:
1234567899hu99999fg99999999
+or-:
-
PleaseEntertheSecondlongInteger:
98765432hr1111111ky11111111111111
12345678999999999999999
-
98765432111111111111*********
=
-98765419765432111111111111112
二、概要设计
为实现上述程序功能,可以用链表或者长数组表示长整数,如果用数组表示长整数有个缺点就是长整数不能无限长,而链表能动态开辟空间,它克服了这个缺点,所以次试验用链表来表示长整数。
1、链表的抽象数据类型定义为:
ADTNumber{
数据对象:
D={ai|ai∈(0,1,…,9),i=0,1,2,…,n,n≥0}
数据关系:
R={|ai-1,ai∈D,i=1,2,…,n}
基本操作:
CreateList(&L)
操作结果:
创建一个链表L。
PrintList(L)
初始条件:
链表L已存在。
操作结果:
在屏幕上输出链表的值。
PlusList(L1,L2,a)
初始条件:
链表L1,L2已存在,a为+or–表示加减。
操作结果:
将两链表的值相加然后在屏幕上输出。
DestroyList(&L)
初始条件:
链表L已存在。
操作结果:
销毁链表L。
}ADTNumber
2、本程序包含五个模块:
(1)主程序模块:
intmain(){
定义变量;
接受命令;
处理命令;
退出(return0);
}
(2)创建链表模块——产生一个长整数;
(3)输出链表模块——把链表产生的一个长整数输出;
(4)两链表加减模块——即求两个由链表产生的长整数的加减并输出结果;
(5)销毁链表模块——程序结束后释放链表开辟的空间。
各模块之间的调用关系如下:
主程序模块
L1L2
创建链表模块
创建链表模块
+or-:
L2L1
输出链表模块
输出链表模块
+or-
=
两链表加减模块
L1L2
销毁链表模块
结束
销毁链表模块
三、详细设计
1、定义头文件
#include
#include
usingnamespacestd;
2、元素类型、节点类型和指针类型
structNumber//链表的类型
{
intdata;//链表当前结点的值
structNumber*next;//链表当前结点指向下一结点的指针
structNumber*prior;//链表当前结点指向前一结点的指针
}*number1,*number2;//定义该链表类型的两个指针对象
3、创建链表模块,即产生一个长整数
voidCreateList(Number*&L)//创建长整数
{
Number*s,*r;//定义两个链表类型的临时指针
charx;//定义一个临时字符变量
L=(Number*)malloc(sizeof(Number));//为头结点开辟空间
L->next=L->prior=NULL;//此时头结点的后继指针和前驱指针赋值为空
r=L;//是r指针指向头结点
x=getchar();//用x接受一个从键盘输入的字符
while(x!
='\n')//控制当输入回车键时结束
{
if(x>='0'&&x<='9')//过滤不符合要求的字符
{
s=(Number*)malloc(sizeof(Number));//开辟下一结点的空间
s->data=x-'0';//将字符转化为int型赋给结点
r->next=s;//r的后继指针指向s
s->prior=r;//s的前驱指针指向r
r=s;//是s指向r
}
x=getchar();//用x接受一个从键盘输入的字符
};
r->next=NULL;//当创建结束时,r的后继指针为空
}
4、输出链表模块,把链表产生的一个长整数输出
voidPrintList(Number*L)//输出长整数
{
Number*p=L->next;//定义一个临时指针并指向链表的第一个结点
while(p!
=NULL)//判断结点是否为空,空就结束
{
cout<data;//输出结点的值
p=p->next;//指向下一个结点
}
cout<}
5、两链表加减模块,即求两个由链表产生的长整数的加减并输出结果
voidPlusList(Number*L1,Number*L2,chara)//两个长整数加减运算
{
Number*p,*q,*r,*p1,*q1;//定义几个链表类型的临时指针
inti=0,j=0;//定义几个临时的整型变量
while(L1->next!
=NULL)//将指针p指向第一个长整数的尾节点并算出它的长度i
{
p=L1->next;
L1->next=L1->next->next;
i++;
}
while(L2->next!
=NULL)//将指针q指向第二个长整数的尾节点并算出它的长度j
{
q=L2->next;
L2->next=L2->next->next;
j++;
}
if(a=='+')//将两个长整数相加
{
if(i>j)//当第一个长整数的长度大于第二个
{
while(i!
=0)//控制长整数的长度
{
while(j!
=0)//控制短整数的长度
{
if((p->data+q->data)>9)//当两数相加大于9向前一位进一
{
p->data=p->data+q->data-10;
p->prior->data=p->prior->data+1;
}
elsep->data=p->data+q->data;//不进位
p=p->prior;//指针向前移
q=q->prior;//指针向前移
j--;//用来计数
i--;//用来计数
}//while(j!
=0)
if(p->data>9&&i>1)/*长整数多余的位数值大于9向前一位进一,
当最高位大于9则不进一*/
{
p->data=p->data-10;
p->prior->data=p->prior->data+1;
}//if
r=p;//指针r最终指向链表的第一个结点
p=p->prior;//指针向前移
i--;//用来计数
}//while(i!
=0)
}//if(i>j)
elseif(i==j)//当两个长整数的长度相等
{
while(i!
=0)//控制整数的长度
{
if((p->data+q->data)>9&&i>1)/*两数相加大于9向前一位进一,
当最高位大于9则不进一*/
{
p->data=p->data+q->data-10;
p->prior->data=p->prior->data+1;
}
elsep->data=p->data+q->data;//不进位
r=p;//指针r最终指向链表的第一个结点
p=p->prior;//指针向前移
q=q->prior;//指针向前移
i--;//用来计数
}//while(i!
=0)
}//elseif(i==j)
else//当第一个长整数的长度小于第二个
{
while(j!
=0)//控制长整数的长度
{
while(i!
=0)//控制短整数的长度
{
if(p->data+q->data>9)//当两数相加大于9向前一位进一
{
q->data=q->data+p->data-10;
q->prior->data=q->prior->data+1;
}
elseq->data=p->data+q->data;//不进位
p=p->prior;//指针向前移
q=q->prior;//指针向前移
j--;//用来计数
i--;//用来计数
}//while(i!
=0)
if(q->data>9&&j>1)/*长整数多余的位数值大于9向前一位进一,
当最高位大于9则不进一*/
{
q->data=q->data-10;
q->prior->data=q->prior->data+1;
}
r=q;//指针r最终指向链表的第一个结点
q=q->prior;//指针向前移
j--;//用来计数
}//while(j!
=0)
}//else
}//if(a=='+')
if(a=='-')//将两个长整数相减
{
if(i>j)//当第一个长整数的长度大于第二个时,用第一个长整数减第二个
{
while(i!
=0)//控制长整数的长度
{
while(j!
=0)//控制短整数的长度
{
if(p->datadata)/*当第一个长整数的数小于
第二个长整数的数,则向前一位借一*/
{
p->data=p->data-q->data+10;
p->prior->data=p->prior->data-1;
}
elsep->data=p->data-q->data;//不借一
p=p->prior;//指针向前移
q=q->prior;//指针向前移
j--;//用来计数
i--;//用来计数
}//while(j!
=0)
if(p->data<0&&i>1)//长整数多余的位数值小于0向前一位借一,
{
p->data=p->data+10;
p->prior->data=p->prior->data-1;
}
r=p;//指针r最终指向链表的第一个结点
if(p->data==0&&i==1)//当最高位等于0时,则r指向下一结点
{
r=p->next;
break;
}
p=p->prior;//指针向前移
i--;//用来计数
}//while(i!
=0)
}//if(i>j)
elseif(i==j)//当第一个长整数的长度等于第二个的长度
{
intc=0,h=i,k=j;//定义几个临时整型变量
p1=p;q1=q;//使指针p1指向p,指针q1指向q
while(i!
=1)//将指针移到第一结点
{
p1=p1->prior;//指针向前移
q1=q1->prior;//指针向前移
i--;//用来计数
}
while(j!
=0)/*判断两个长整数的大小,从高位开始判断,c=1,
表示第一个长整数大于或者等于第二个长整数,c=0则小于*/
{
if(p1->data>q1->data)
{
c=1;
break;
}
elseif(p1->datadata)
{
c=0;
break;
}
elseif(p1->data==q1->data&&j==1)c=1;
else
{
p1=p1->next;
q1=q1->next;
}
j--;//用来计数
}//while(j!
=0)
if(c==1)//第一个长整数大于或者等于第二个长整数
{
while(h!
=0)//控制整数的长度
{
if(p->datadata)/*当第一个长整数的数小于第二个
长整数的数,则向前一位借一*/
{
p->data=p->data-q->data+10;
p->prior->data=p->prior->data-1;
}
elsep->data=p->data-q->data;//不借一
r=p;//指针r最终指向链表的第一个结点
p=p->prior;//指针向前移
q=q->prior;//指针向前移
h--;//用来计数
}//while(h!
=0)
while(r->data==0&&k>1)/*如果链表的的高位为0,则r向下一结点
移到,直到最后一位不移动*/
{
k--;
r=r->next;
}
}//if(c==1)
if(c==0)//第一个长整数小于第二个长整数
{
while(h!
=0)//控制整数的长度
{
if(p->data>q->data&&h>1)/*当第二个长整数的数小于第
一个长整数的数,则向前一位借一*/
{
q->data=q->data-p->data+10;
q->prior->data=q->prior->data-1;
}
elseq->data=q->data-p->data;//不借一
r=q;//指针r最终指向链表的第一个结点
p=p->prior;//指针向前移
q=q->prior;//指针向前移
h--;//用来计数
}//while(h!
=0)
while(r->data==0)/*如果链表的的高位为0,则r向下一结点移到*/
{
r=r->next;
}
r->data=-r->data;//如果高位不为0,则取负数
}//if(c==0)
}//elseif(i==j)
else//当第一个长整数的长度小于第二个
{
while(j!
=0)//控制长整数的长度
{
while(i!
=0)//控制短整数的长度
{
if(p->data>q->data)/*当第二个长整数的数小于第
一个长整数的数,则向前一位借一*/
{
q->data=q->data-p->data+10;
q->prior->data=q->prior->data-1;
}
elseq->data=q->data-p->data;//不借一
p=p->prior;//指针向前移
q=q->prior;//指针向前移
j--;//用来计数
i--;//用来计数
}//while(i!
=0)
if(q->data<0&&j>1)/*长整数多余的位数值小于0向前一位借一,
当到时最高位则不借一*/
{
q->data=q->data+10;
q->prior->data=q->prior->data-1;
}
r=q;//指针r最终指向链表的第一个结点
if(r->data==0&&j==1)/*如果最高位值为0,
则r指向下一结点,并取负数*/
{
r=r->next;
r->data=-r->data;
break;
}
if(r->data!
=0&&j==1)//如果最高位值不为0,取负数
r->data=-r->data;
q=q->prior;//指针向前移
j--;//用来计数
}//while(j!
=0)
}//else
}//if(a=='-')
while(r!
=NULL)//输出加减运算后的值
{
cout<data;
r=r->next;
}
cout<}
6、销毁链表模块,程序结束后释放链表开辟的空间
voidDestroyList(Number*&L)//销毁链表
{
Number*p=L,*q=p->next;
while(q!
=NULL)
{
free(p);//释放p的空间
p=q;
q=p->next;
}
cout<<"释放链表"<}
7、主程序模块
intmain()
{
chara,x;//定义临时字符变量
cout<<"PleaseEntertheFirstlongInteger:
";
CreateList(number1);//调用创建长整数函数
for(;;)//过滤非“+”和“-”的字符
{
cout<<"+or-:
";
cin>>a;
x=getchar();
if(a=='+'||a=='-')break;
cout<<"你输入的有误!
请重新输入";
}
cout<<"PleaseEntertheSecondlongInteger:
";
CreateList(number2);//调用创建长整数函数
cout<<"********************************************************************************";
PrintList(number1);//调用输出长整数函数
cout<PrintList(number2);//调用输出长整数函数
cout<<"="<PlusList(number1,number2,a);//调用两长整数相加减的函数
cout<<"********************************************************************************";
DestroyList(number1);//调用销毁链表的函数
DestroyList(number2);//调用销毁链表的函数
return0;
}
四、调试分析
1、在创建长整数时,没有使用getchar()来接受字符,而用C++中的cin>>来输入,这样使得每一次输入之后都要按回车键,而且在输入结束时控制也不方便,使用getchar()函数解决了这一问题。
2、从键盘输数据的时候,符合要求的只有0到9,输入其他的字符就可能出错或者结果不正确,最后用了一个条件来控制滤过不符合要求的字符。
3、在加减运算过程中也遇到了很多问题。
首先,遇到的问题就是if条件中的“==”中少了一个“=”导致编译正确,但是一运行就错误,这个问题不该错的,以后一定重视每一个细节。
还有就是链表的使用过程中,指针太多,一会儿指向这个,一会儿又指向那个,如果思路不清楚的话,很容易弄晕的;有时候一个指针指向空的时候根本就不知道,编译没错误,检查不出来,一运行就不正确,有时候运行正确了,但是结果却不正确,这还好点,有时候指针指向空了,运行就弹出错误要终止程序。
经过一步一步的测试,一步一步的运行,花了不少时间终于弄出来了。
4、在销毁链表的时候,也遇到过一个问题,现在还没弄明白是为什么。
在销毁链表的函数中,如果参数接受两个链表来销毁的话,如:
voidDestroyList(Number*&L1,Number*&L2),运行会出错,或许是我写的代码不正确;但是,当用voidDestroyList(Number*&L)来一个链表一个链表的销毁就没问题。
五、运行结果
(1)两个长整数相加
输入:
输出:
(2)两个长整数相减
输入:
输出:
六、实验环境
(1)WindowsXP系统下
(2)编程环境:
VC6.0++,TC2.0
七、实验体会
本次实验是求两个无限长整数加减运算。
由于没有限制长度所以不能用一般的整型和长整型来声明,必须用链表或者数组来表示两个长整数,这样来求它们的加减运算。
这次实验说简单也简单,说难也难,看上去就是两个长整数从低位相加,如果进位的话则前一位加一,两个长整数相减,如果被减数小于减数的话,则向前一位借一,然后把它们输出就可以了。
但是,实际上要的到完全正确的结果,编写该程序还是有点难度的,如果不仔细考虑的话有些地方,运算的结果是不正确的。
比如说,4976+