长整数加减的运算一、需求分析问题描述:设计一个实现任意长的整数进行加法运算的演示程序基本要求:利用双向循环链表实现长整数的存储,每个结点含一个整型变量。
任何整型变量的范围是-(2 15 -1)~(2 15 -1)。
输入输出形式:按照中国对于长整数的表示习惯,每四位是一组,组间用逗号隔开更高要求:(1)长整数的减法(2)多个长整数的连续加减法,并带括号等。
具体方式可以参见表达式的求值部分,利用栈测试数据:(1)0;0;应输出“0”(2)-2345,6789;-7654,3211;应输出“-1,0000,0000”(3)-9999,9999;1,0000,0000,0000;应输出“9999,0000,0001”(4)1,0001,0001;-1,0001,0001;应输出“0”(5)1,0001,0001;-1,0001,0000;应输出“1”(6)-9999,9999,9999;-9999,9999,9999;应输出“-1,9999,9999,9998”(7)1,0000,9999,9999;1;应输出“1,0001,0000,0000”一、概要设计1.数据结构此实验采用的数据结构是双向循环链表。
这样可以很容易的找到他的前驱以及它的后继。
节点采用结构体类型,代码如下:typedef struct Node // 双向链表的结构体定义 int data;struct Node *prior;struct Node *next;}DLNode;2.使用函数1)void ListInitiate(DLNode **head)操作结果:初始化一个头结点为head的双向循环链表;2)int ListLength(DLNode *head)操作结果:计算以head为头结点的链表的长度3)int ListInsert(DLNode *head,int i,int x)操作结果:将节点数据为x的节点插到第i个位置上去。
4)int abs(int x)操作结果:绝对值函数,返回x的绝对值。
5)int InputNumber(DLNode *head)操作结果:将从键盘中接收数据并把得到的数据存入以head为头结点的链表中。
四位一存,中间以逗号区分,结束符为分号。
6)void OutputNumber(DLNode *head,int sign)操作结果:将以head为头结点的链表中的所有数据输出到显示屏上,7)void add(DLNode *head1,DLNode *head2,DLNode *head3)操作结果:实现正数加正数的加法操作。
8)int change(DLNode *head1,DLNode *head2)操作结果:判断存在俩个链表中的数的大小,如何head1中的数大于head2中的数那么返回值为0,反之返回值为1,相等时返回值为2;9)void method(DLNode *head1,DLNode *head2,int x)操作结果:计算正数乘以正数的乘法运算。
10)void minus(DLNode *head1,DLNode *head2,DLNode *head3)操作结果:计算正数减正数的减法运算。
11)void yunsuan(DLNode *head1,DLNode *head2,DLNode *head3,char ch)操作结果:正数,负数,加法,减法。
计算式共分为八种运算,在这之前我已经实现了二种运算,那么这个函数就是把这八种运算按照一定的规则转化成已经实现的二种运算来实现完整的加减法运算。
12)void chengfa(DLNode *head1,DLNode *head2)操作结果:在乘法中我只是实现了正数乘以正数的运算,那么这个函数就是通过调用method函数按照一定的规则来实现完整的乘法运算。
13)void main()操作结果:主函数。
调用以上的各个函数来引导用户进行长整数的加法运算,加法运算,乘法运算。
二、详细设计1.数据结构详细设计typedef struct Node // 双向链表的结构体定义int data;struct Node *prior;struct Node *next;}DLNode;双向循环链表的节点由三个部分组成,第一是数据部分data存储此节点的数据,第二是此节点的前驱指针部分*prior指向此节点的前驱,第三是此节点的后继指针部分*next指向此节点的后继。
数据部分我们约定它为整形变量,前驱后继指针均为结构体Node类型。
2.链表初始化函数:void ListInitiate(DLNode **head) //双向链表的初始化if((*head=(DLNode *)malloc(sizeof(DLNode)))==NULL) exit(0);(*head)->prior=*head;(*head)->next=*head;初始化之前需要定义一个类型为Node型的头结点变量,经过函数后完成链表的初始化即:头节点的前驱指针指向自己,同时他的后继指针也指向自己。
3.计算已知的链表长度:int ListLength(DLNode *head) //双向链表的表长DLNode *p=head;int size=0;while(p->next!=head)p=p->next;size++;return size;此函数计算的是已知链表的长度。
主要思想:从头结点开始寻找下一个节点,找到计数器加一。
直到再次寻找到头结点时停止,计算完毕。
4.插入函数:int ListInsert(DLNode *head,int i,int x) //双向链表的数据插入,i表示是插入的第几个元素DLNode *p,*s;int j;p=head->next;j=0;while(p!=head&&j<i)p=p->next;j++;if(j!=i)printf("\n插入位置不合法!");return 0;if((s=(DLNode *)malloc(sizeof(DLNode)))==NULL) exit(0);s->data=x;s->prior=p->prior;//插入p->prior->next=s;s->next=p;p->prior=s;return 1;此函数是已知一双向链表实现在第i个位置插入data为x的节点。
函数需要注意的是在什么位置插入才是合法的,在就是在该节点指针时的顺序不要搞错。
5.绝对值函数:int abs(int x)if(x<0) return -x;else return x;此函数是实现求一个整数的绝对值。
设计这么一个函数主要是考虑到在存储负数的时候头结点应该变为正整数,然后通过其他手段变相实现那种运算。
6.读入数据并插入对应的链表函数:int InputNumber(DLNode *head) //读入输入的数据int input,i=0;//第i个节点char c;scanf("%d%c",&input,&c);while(1)if(input<0&&i==0)//输入数为负且是第一个节点head->data=0;//将长整数的符号保存在头结点中//input=abs(input);//取输入数字的绝对值ListInsert(head,i,input);//插入数据else if(input>=0&&i==0)//输入数为正且是第一个节点head->data=1;//将长整数的符号保存在头结点中ListInsert(head,i,input);//插入数据elseif(head->next->data>=0)ListInsert(head,i,input);//非第一个节点else//input=-1*input;ListInsert(head,i,input);i++;if(c==';') break;//遇到数据输入完成标志,跳出循环scanf("%d%c",&input,&c);return 1;此函数实现的是从键盘上得到数据根据三种情况进行不同的处理,判断是否是头结点,判断是否是整数,判断输入的字符是否是“;”分号。
并且如果是正整数它的头结点data 等于1否则为0。
7.输出函数void OutputNumber(DLNode *head,int sign) //从表尾输出数据元素DLNode *r=head->next;while(r->data==0&&r!=head->prior)r=r->next;if(sign==1)printf("结果是:");elseprintf("结果是: -");printf("%d",r->data);r=r->next;while(r!=head)if(r->data<10)printf(",000");printf("%d",r->data);else if(r->data<100)printf(",00");printf("%d",r->data);else if(r->data<1000)printf(",0");printf("%d",r->data);elseprintf(",%d",r->data);r=r->next;printf("\n");此函数实现的是将最后的结果输出到显示屏上,经过判断数据的正负和数据的范围来进行不同的处理,以保证在显示屏上显示的是正确的格式。
8.不完整加法函数(只可实现正数加上正数)void add(DLNode *head1,DLNode *head2,DLNode *head3){int z=0;int e;DLNode *p1,*p2;p1=head1->prior;p2=head2->prior;while(p1!=head1&&p2!=head2)e=p1->data+p2->data+z;if(e>=10000)z=1;e=e%10000;else z=0;ListInsert(head3,0,e);p1=p1->prior;p2=p2->prior;if(p1==head1&&p2!=head2)while(p2!=head2)e=p2->data+z;if(e>=10000)z=1;e=e%10000;else z=0;ListInsert(head3,0,e);p2=p2->prior;if(z==1) ListInsert(head3,0,z);else if(p1!=head1&&p2==head2){while(p1!=head1)e=p1->data+z;if(e>=10000)z=1;e=e%10000;else z=0;ListInsert(head3,0,e);p1=p1->prior;if(z==1) ListInsert(head3,0,z);else{if(z==1) ListInsert(head3,0,z);此函数实现的是两个正数之间的相加运算,主要的算法和我们手算加法是一样的,首先设置一个进位计数的变量,根据存储的特点从低位开始相加带上进位即可得出相应的位和,最后更新进位变量。