1、长整数四则运算加减法青岛理工大学数据结构课程设计报告题目: 长整数四则运算 院(系): 计算机工程学院 学生姓名: 班级: 学号: 起迄日期: 指导教师: 房斐斐 20122013年度 第 2 学期 一、需求分析 1.问题描述: 设计一个实现任意长的整数进行加、减法运算的演示程序。2.基本功能1、本程序实现计算任意长的整数的加、减法运算. 以用户和计算机对话的方式,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令,然后程序就计算并显示出这两个数的运算。 2、本演示程序中,集合的元素限定为数字字符09和字符,与;,输入字符可以任意长,输入形式以“回车符”为结束标志
2、,串中字符顺序不限,且允许出现重复字符。3、利用双向循环链表现实长整数的存储,每个结点含一个整形变量。输入的形式以回车结束,可以直接输入正数或负数。按中国对于长整数的表示习惯,每四位一组,除数字和位于首位置的负号外,其它一切字符都将作为分隔符,连续多个分隔符当一个处理。但不使用分隔符也不影响结果。3.输入输出(1)0;0;加法应输出“0”,减法应输出”0”。(2)-2345,6789;-7654,3211;加法应输出“-1,0000,0000”,减法应输出”5408,6422”。(3)-9999,9999;1,0000,0000,0000;加法应输出“9999,0000,0001”,减法应输出
3、1,0000,9999,9999。(4)1,0001,0001;-1,0001,0001;加法应输出“0”,减法应输出”2,0002,0002”。(5)1,0001,0001;-1,0001,0000;加法应输出“1”,减法应输出”2,0002,0001”。(6)-9999,9999,9999;-9999,9999,9999;加法应输出“1,9999,9999,9998”,减法应输出”0”。(7)1,0000,9999,9999;1;加法应输出“1,0001,0000,0000”,减法应输出”1,0000,9999,9998”。二、 概要设计1. 设计思路:(1)利用双向循环链表现实长整数的存
4、储,每个结点中可以存放的最大整数为32767,才能保证两数相加不会溢出,但若这样存放,即相当于按32768进制存放,在十进制与32768进制数之间的转换十分不方便,故可以在每个结点中仅存十进制的4位,即不超过9999的非负整数,整个链表表示为万进制。(2)可以利用头结点数据域的符号代表长整数的符号。用其绝对值表示元素结点数目。相加过程中不要破坏两个操作数链表。两操作数的头指针存于指针数组中是简化程序结构的一种方法。不能给长整数位数规定上限。2. 数据结构设计:1) 数据类型:typedef int DataType; /定义数据类型 typedef struct DoubleNode /定义链
5、表元素 DataType data; struct DoubleNode *prior; struct DoubleNode *next; DLNode; 2) 存储结构:顺序结构,链式存储。采用链式存储的方式会方便字符的读入和操作,且算法简单易懂。3. 软件结构设计: 1)初始化链表void InitNode(DLNode *head) 2)向链表第n个位置插入元素X int InsertNode(DLNode *head,int n,DataType x)3)判断整数N有几位int digit(int n)4)两数相加void add(DLNode *h1,DLNode *h2) 5)两数
6、相减void jian(DLNode *h1,DLNode *h2)6)打印链表 void PrintNode(DLNode *head)7)删除链表void DestroyNode(DLNode *head)8)主函数int main()三、 详细设计 数据类型。 typedef int DataType; /定义数据类型 typedef struct DoubleNode /定义链表元素 DataType data; struct DoubleNode *prior; struct DoubleNode *next; DLNode; 2.存储结构类型:void InitNode(DLNod
7、e *head) /初始化链表 if(*head=(DLNode*)malloc(sizeof(DLNode)=NULL) exit(1); (*head)-prior=*head; (*head)-next=*head; 3.主函数和其他函数的伪码算法;1.主函数:int main() /主函数 DLNode *head1,*head2; char data1N,data2N; char d110,d210; int i,j,k; int xun; printf(提示:较长的字符串数作为被加数,如果等长,则第一个数加第二个数nn); while(1) printf(输入数据:n); scan
8、f(%s %s,data1,data2); InitNode(&head1); InitNode(&head2); i=0; k=0; while(data1i!=;) /将数1用链表储存 for(j=0;j10;j+) d1j=0; j=0; while(data1i!=;&data1i!=,) d1j+=data1i+; if(data1i=,) i+; if(data10=-) /处理正负数 j=-(int)fabs(atoi(d1); /atoi()把字符串转换成整型数,头文件: #include else j=atoi(d1); InsertNode(head1,k+,j); i=0
9、; k=0; while(data2i!=;) /将数2用链表储存 for(j=0;j=strlen(data2) /较长的数作为被加数 add(head1,head2); else add(head2,head1); break; default:break; DestroyNode(&head1); DestroyNode(&head2); printf(nn); return 0; 2.初始化链表:void InitNode(DLNode *head) /初始化链表 if(*head=(DLNode*)malloc(sizeof(DLNode)=NULL) exit(1); (*head
10、)-prior=*head; (*head)-next=*head; 3.向链表第n个位置插入元素X int InsertNode(DLNode *head,int n,DataType x) /向链表第n个位置插入元素X DLNode *p,*nt; int i=0; p=head-next; while(p!=head&inext; i+; if(i!=n) printf(插入位置错误n); return 0; if(nt=(DLNode *)malloc(sizeof(DLNode)=NULL) exit(1); nt-data=x; nt-prior=p-prior; nt-prior
11、-next=nt; nt-next=p; p-prior=nt; return 1; 4.判断整数N有几位 int digit(int n) /判断整数N有几位 int i; for(i=1;n/=10,i+) if(n/10=0) return i; 5.打印链表 void PrintNode(DLNode *head) /打印链表 printf(结果是:); DLNode *p=head-prior; int i; while(p-data=0) /去掉前面的一串0 p=p-prior; if(p=head) printf(0n); return; printf(%d,p-data); /
12、最前面的一个数进行特殊处理,不用补零 p=p-prior; while(p!=head) /打印后面的数字 printf(,); if(p-data=0) printf(0000); p=p-prior; continue; for(i=0;idata);i+) /补零 printf(0); printf(%d,p-data); p=p-prior; printf(n); 6.删除链表 void DestroyNode(DLNode *head) DLNode *p,*p1; p=(*head)-next; while(p!=*head) p1=p; p=p-next; free(p1); f
13、ree(p); head=NULL; 7.两数相加 void add(DLNode *h1,DLNode *h2) int i=0,j=0; DLNode *head3; InitNode(&head3); DLNode *p1=h1-prior,*p2=h2-prior,*p3; while(p1!=h1&p2!=h2) /每个链表元素相加 i=p1-data+p2-data ; p1=p1-prior; p2=p2-prior; InsertNode(head3,j+,i); while(p1!=h1) InsertNode(head3,j+,p1-data); p1=p1-prior;
14、p3=head3-next; while(p3!=head3-prior) /处理链表元素 if(p3-data=10000) p3-next-data+=p3-data/10000; p3-data%=10000; if(p3-dataprior!=0) p3-next-data-=1; p3-data+=10000; p3-data=(int)fabs(p3-data); p3=p3-next; if(head3-prior-data=10000) /处理最前面的数 InsertNode(head3,j,head3-prior-data/10000); head3-prior-prior-
15、data%=10000; if(head3-prior-dataprior-data/10000); head3-prior-prior-data%=10000; head3-prior-prior-data=(int)fabs(head3-prior-prior-data); PrintNode(head3); 8.两数相减void jian(DLNode *h1,DLNode *h2) int i=0,j=0; DLNode *head4; InitNode(&head4); DLNode *p1=h1-prior,*p2=h2-prior,*p4; while(p1!=h1&p2!=h2
16、) /每个链表元素相减 i=p1-data-p2-data ; p1=p1-prior; p2=p2-prior; InsertNode(head4,j+,i); while(p1!=h1) InsertNode(head4,j+,p1-data); p1=p1-prior; p4=head4-next; while(p4!=head4-prior) /处理链表元素 if(p4-data=10000) p4-next-data+=p4-data/10000; p4-data%=10000; if(p4-dataprior!=0&p4-datanext-data-=1; p4-data+=100
17、00; p4-data=(int)fabs(p4-data); p4=p4-next; if(head4-prior-data=10000) /处理最前面的数 InsertNode(head4,j,head4-prior-data/10000); head4-prior-prior-data%=10000; if(head4-prior-dataprior-data/10000); head4-prior-prior-data%=10000; head4-prior-prior-data=(int)fabs(head4-prior-prior-data); PrintNode(head4);4
18、. 主函数的程序流程图 四、调试分析 1. 实际完成的情况说明程序基本功已完成,包括:输入长整型数字字符,用双向循环链表储存,计算两数之和、之差,输出值,删除链表,基本符合题目要求。2. 程序的性能分析时间复杂度:O(strlen(data1)+strlen(data2)3. 上机过程中出现的问题及其解决方案 1)双向循环链表指针指向错误 双向循环链表使用错误,指针顺序不对,参考教课书改正。 2)打印顺序错误由于计算值储存顺序是从尾到头,开始误认为是从头到尾,修改指针指向改正。3)中间计算值错误 中间计算值不足四位的应用0补足。 4)中间值小于0处理错误 中间值小于0但大于-100000的数应
19、取绝对值,小于-10000的数应先借位,这个数加上10000后,再取绝对值4. 程序中可以改进的地方说明 两操作数的头指针存于指针数组中是简化程序结构的一种方法,但由于广泛使用指针 易造成混乱,所以就放弃了,以后可以改进。5. 程序中可以扩充的功能及设计实现假想。本程序可拓展到乘除运算,还有乘方和阶乘运算。五、测试结果 测试方法:输入数据 测试数据:(1)0;0;加法应输出“0”,减法应输出”0”。(2)-2345,6789;-7654,3211;加法应输出“-1,0000,0000”,减法应输出”5408,6422”。(3)-9999,9999;1,0000,0000,0000;加法应输出“
20、9999,0000,0001”,减法应输出1,0000,9999,9999。(4)1,0001,0001;-1,0001,0001;加法应输出“0”,减法应输出”2,0002,0002”。(5)1,0001,0001;-1,0001,0000;加法应输出“1”,减法应输出”2,0002,0001”。(6)-9999,9999,9999;-9999,9999,9999;加法应输出“1,9999,9999,9998”,减法应输出”0”。(7)1,0000,9999,9999;1;加法应输出“1,0001,0000,0000”,减法应输出”1,0000,9999,9998”。六、用户手册本程序使用起
21、来简单方便,只要按照菜单提示进行即可。1.加法1. 输入0;0;2. 输入-2345,6789;-7654,3211;3. 输入-9999,9999;1,0000,0000,0000;4. 输入1,0001,0001;-1,0001,0001;5. 输入1,0001,0001;-1,0001,0000;6. 输入-9999,9999,9999;-9999,9999,9999;7. 输入1,0000,9999,9999;1;2.减法1. 输入0;0;2. 输入-2345,6789;-7654,3211;3. 输入-9999,9999;1,0000,0000,0000;4. 输入1,0001,00
22、01;-1,0001,0001;5. 输入1,0001,0001;-1,0001,0000;6. 输入-9999,9999,9999;-9999,9999,9999;7. 输入1,0000,9999,9999;1;8. 输入0;0;后输入0退出七、体会与自我评价 通过这次的课程设计,我进一步加深了对数据结构的理解。这次课程设计我抽到的题目是长整数四则运算,长整数四则运算的功能比较单一,即输入两个长整数(数字字符和“,”和“;”),每四个数字字符通过atoi()函数转换成数字后储存在一个节点里,每两个对应的节点相加、相减后,生成一个新的节点来储存,然后对链表进行处理,可采用双向循环链表实现长整数
23、的存储,主要原因是顺序表操作起来比较简单,算法较易理解,然后打印链表,最后删除链表,销毁头结点。这次的课程设计我采用的是C语言编程语言,在编程过程中也遇到了很多问题,但经过努力调试修改,基本实现了长整数加法的基本功能。通过这次课程设计我回顾了以前所学的编程知识,理解了学习完数据结构后的编程与以前编程方法上的不同。在以往的编程方法上,我们习惯于是用数组和顺序的储存结构进行编程,这种方法在进行插入和删除是及为复杂不易实现。但数据结构给我们提供了更多的不同的而且较为简单的编程方法,如链表,而且通过这次课程设计,我认识到了链表的许多优点。 通过这次编程我还学习到了一些新的知识,现如下总结:1) 把字符串转换成整型数函数:atoi()函数,它包含在头文件: #include 中。2) 双向循环链表的使用,使我对链表的储存结构有了全新的认识3) 再进行数据处理时应仔细分析4) 应仔细分析运算法则
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1