数据结构程序设计 任意长的整数进行加法.docx
《数据结构程序设计 任意长的整数进行加法.docx》由会员分享,可在线阅读,更多相关《数据结构程序设计 任意长的整数进行加法.docx(19页珍藏版)》请在冰豆网上搜索。
数据结构程序设计任意长的整数进行加法
任意长的整数进行加法课程设计报告
1目的:
通过课程设计,加深对《数据结构》课程所学知识的理解,熟练掌握和巩固数据结构的基本知识和语法规范。
通过课程设计,巩固和加深对线性表、栈、队列、字符串、树、图、查找、排序等理论知识的理解;掌握现实复杂问题的分析建模和解决方法(包括问题描述、系统分析、设计建模、代码实现、结果分析等);提高利用计算机分析解决综合性实际问题的基本能力。
包括:
数据类型(整形、实型、字符型、指针、数组、结构等);运算类型(算术运算、逻辑运算、自增自减运算、赋值运算等);程序结构(顺序结构、判断选择结构、循环结构);库函数应用等;
2需求分析
在加法运算中,C语言所能定义的整形变量是有一定长度限制的。
例如int型变量所能储存值的值域为-32768~32767,最长的整型longint值域为-2147483648~2157483646.当在需要位数更长的整数加法时计算器设计运用简单的加法运算符难以达到要求,或是在两个较大整数相加的值超过了整型变量所能储存的数值是程序会发生溢出。
需要一种新的加法模式来解决上述问题,来实现任意长的整数进行加法,得到想要的结果。
本程序完成对任意长的整数进行加法运算:
1:
输入和输出形式:
按中国对于长整数的表示习惯,每四位一组,组间用逗号隔开。
如:
1,0000,0000,0000,0000。
2:
输入值范围为任意长的整数,输入时需输入数字和被允许的字符(‘,’,‘-’)。
3:
基本功能包括大整数输入、加法运算、大整数输出。
4:
测试数据为:
(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”。
3概要设计
本程序使用C语言编写,编辑器为C-FREE4.1编译器为MinGW3.4.5,输入输出界面为windows对话框。
本程序所用到的数据类型有自定义Lnode型为节点类型,Lnode型变量包涵两个变量,一个为整型的intdata变量,另一个为Lnode型的指针。
自定义Linklist型变量包涵两个变量,一个为Lnode型的指针head,一个是整型变量intlength。
Linklist型变量为链表类型,head为链表的头指针,整型length为链表的长度(链表长度不包括头节点)。
本程序组成:
函数int*Iput(char*ch)功能:
将输入的标准字符串,转换为所需要的数字储存在int型数组中并返回数组指针。
函数Linklist*CreateList(Linklist*l)功能:
创建一个空的单链表,并返回该链表的指针。
函数Linklist*InList(Linklist*l,intdata)功能:
在链表的头结点后插入一个节点,所需参数为所要插入的链表的指针,所插入节点的数据值。
返回值为插入完成后的链表指针。
函数Linklist*Inlistfail(Linklist*list,intdata)功能:
当结果需要进位时,对结果进行进位,参数为储存结果的链表,所插入节点的数据值。
返回值为插入完成后结果链表的指针。
函数Linklist*OutList(Linklist*list)功能:
对输入的负数进行处理,使其变成标准加数或被加数。
参数为储存输入数的链表指针。
返回值为处理完成后的链表的指针。
函数Linklist*AddList(Linklist*one,Linklist*two)功能:
两个标准加数和被加数,进行加数。
参数为储存加数和被加数的链表指针。
返回值为储存结果的链表。
函数Linklist*SubList(Linklist*listone,Linklist*listtwo)功能:
两个标准减数和被减数进行相减。
参数为储存标准减数和被减数链表指针。
返回值为存储结果的链表。
函数Linklist*Linklistpush(int*number,Linklist*list)功能:
将输入的存储在数组中的数值依次插入到创建好的链表中,每个链表节点储存一位输入的数值。
参数为储存数值的数组指针和创建好的链表的指针。
返回值为存储输入数值的链表的指针。
函数char*test_takeprint(Linklist*list,intj)功能:
将储存结果的链表里的值变为字符串形式便于对话框输出。
参数为存储结果的链表的指针,和整型输出控制变量。
函数intJudgmentsize(int*numone,int*numtwo,intnumberone,intnumbertwo,intv)功能:
对两个位数相同但符号不同的两个数进行大小比较。
参数为两个储存值的数值的指针,和两连表的长度,和控制变量。
返回值为判断后得出的标识值。
函数intJudgment(int*numone,int*numtwo,intnumberone,intnumbertwo)功能:
对输入的两个数值进行判断,是进行加法或是进行减法。
参数为储存两个数的数组指针和两个数的位数。
返回值为判断后的标志整型值。
函数intJudgementprint(Linklist*listone,Linklist*listtwo,inti)功能:
对输出的值的正负进行判断。
参数为储存两个值的链表的指针,和标识整型数。
返回值为标识整型数。
函数Linklist*Caseone(Linklist*listone,Linklist*listtwo)功能:
判断后的第一种情况对两数的处理。
参数为储存两数的链表打的指针。
返回值为处理后的储存结果的链表的指针。
函数Linklist*Casetwo(Linklist*listone,Linklist*listtwo)功能:
判断后的第二种情况对两数的处理。
参数为储存两数的链表打的指针。
返回值为处理后的储存结果的链表的指针。
函数Linklist*Casethree(Linklist*listone,Linklist*listtwo,inti)功能:
判断后的第三种情况的对两数的处理。
参数为储存两数的链表的指针,和整型标识位。
返回值为处理后的储存结果的链表的指针。
函数char*mainlist(char*numberone,char*numbertwo)功能:
整个程序的流程。
参数为输入得到的两字符串的指针。
返回值为最终要求输出的字符串的指针。
模块BOOLWINAPIMain_Proc(HWNDhWnd,UINTuMsg,WPARAMwParam,LPARAMlParam)对话框的定义。
模块BOOLMain_OnInitDialog(HWNDhwnd,HWNDhwndFocus,LPARAMlParam)
对话框的定义。
函数voidMain_OnCommand(HWNDhwnd,intid,HWNDhwndCtl,UINTcodeNotify)
功能:
当消息响应时操作系统所调用的函数。
主程序流程图:
函数之间的调用关系为:
char*mainlist(char*numberone,char*numbertwo)
调用Linklist*CreateList(Linklist*l)
int*Input(char*ch)
Linklist*Linklistpush(int*number,Linklist*list)
intJudgment(int*numone,int*numtwo,intnumberone,intnumbertwo)
intJudgementprint(Linklist*listone,Linklist*listtwo,inti)
char*test_takeprint(Linklist*list,intj)
Linklist*Caseone(Linklist*listone,Linklist*listtwo)
Linklist*Casetwo(Linklist*listone,Linklist*listtwo)
Linklist*Casethree(Linklist*listone,Linklist*listtwo,inti)
以上为平行关系
Linklist*AddList(Linklist*one,Linklist*two)
函数调用Linklist*Inlistfail(Linklist*list,intdata)函数
intJudgment(int*numone,int*numtwo,intnumberone,intnumbertwo)
调用intJudgmentsize(int*numone,int*numtwo,intnumberone,intnumbertwo,intv)函数
Linklist*Caseone(Linklist*listone,Linklist*listtwo)
调用Linklist*AddList(Linklist*one,Linklist*two)函数
Linklist*Casetwo(Linklist*listone,Linklist*listtwo)
调用Linklist*OutList(Linklist*list)和Linklist*AddList(Linklist*one,Linklist*two)函数
Linklist*Casethree(Linklist*listone,Linklist*listtwo,inti)调用
Linklist*SubList(Linklist*listone,Linklist*listtwo)函数
4详细设计
1:
数据类型设计
typedefstructLnode//节点类型
{
intdata;
structLnode*next;
}Lnode;
typedefstructLinklist//链表类型
{
Lnode*head;
intlength;
}Linklist;
2:
输入输出函数设计
字符串转换函数
int*Input(char*ch)
{
int*number;
inti=2,j=0,k=0;
number=(int*)malloc(sizeof(int)*100);//为数组分配空间
while(i!
=0)//循环到字符串结束
{
if(ch[j]==44)//如果取到的字符为‘,’,跳过该字符继
{//转换
k--;
}
else
{
number[k]=ch[j]-48;//根据ASCL码数值等于该字符的值减去48
}
j++;
k++;
if(ch[j]==0)//转换结束,数组的最后一位赋值为888,做
{//为标示位
number[k]=888;
break;
}
}
returnnumber;
}
输出格式转换函数
char*test_takeprint(Linklist*list,intj){
intlength,i,remainder,shang,position=0,positionnum=0,k;
char*chfinal;
intnum[100];
Lnode*now;
now=list->head->next;
chfinal=(char*)malloc(sizeof(char)*100);//为将要输出的字符穿申请内存空间
length=list->length;
shang=length/4;//求链表长度对4的商
remainder=length%4;//求链表长度除于4的余数
if(shang==0)
remainder=0;//如果商等于0时,将余数设为0
for(i=length-1;i>=0;i--)//将保存在链表中的数值反向复制到数组中
{
num[i]=now->data;
now=now->next;
}
if(j==888)//j为结果符号标识变量,j=888时结果为负数
{
chfinal[position]=45;//在字符串第一位加上‘-’号
position++;
}
if(length<=4)//结果少与4位时不需要,添加‘,’号直接添加到字符串中
{
for(i=0;i{
chfinal[position]=num[i]+48;//ASC码字符与数值相差48
position++;
}
}
Else//结果大于4位是的情况
{
for(i=0;i{
chfinal[position]=num[positionnum]+48;
position++;
positionnum++;//此变量为整型变量数组的取值位
}//字符串数组与整型数组的同一个数不在同
if(remainder!
=0)//一位置,故要用不同的取值位
{
chfinal[position]=44;
position++;
}
for(i=0;i{
for(k=0;k<4;k++)//每4位添加一个
{
chfinal[position]=num[positionnum]+48;
position++;
positionnum++;
}
if(i{
chfinal[position]=44;//逗号的ASCII码值为44
position++;
}
}
}
chfinal[position]=0;//为字符串添加结束标识
returnchfinal;//返回字符串
}
3:
链表操作函数
链表创建函数
Linklist*CreateList(Linklist*l)
{
l->head=(Lnode*)malloc(sizeof(Lnode));//头结点分配空间
l->head->next=NULL;
l->length=0;//链表长度为零
returnl;
}
Linklist*InList(Linklist*l,intdata)//链表插入函数
{
Lnode*n;
n=(Lnode*)malloc(sizeof(Lnode));//为插入的节点分配空间
n->data=data;//节点数据位赋值为要插入的值
n->next=l->head->next;//修改节点和头结点的指针
l->head->next=n;
l->length++;//链表长度加一
returnl;
}
Linklist*Inlistfail(Linklist*list,intdata)//结果进位时链表插入函数
{
Lnode*fail,*n;
inti;
fail=list->head;
for(i=0;ilength;i++)//寻找到链表的最尾部的节点
{
fail=fail->next;
}
n=(Lnode*)malloc(sizeof(Lnode));//分配一个新的节点的空间
n->next=fail->next;//将该节点插入到链表的最尾端
fail->next=n;
n->data=data;
list->length++;//链表长度加一
returnlist;
}
Linklist*OutList(Linklist*list)//链表去负号函数
{
Lnode*temporary,*temporary2;
inti=0;
temporary=list->head;
for(i=0;i<(list->length-1);i++)//寻找到链表中保存负号的节点
{
temporary=temporary->next;
}
temporary2=temporary->next;//修改该节点附近指针使其在链表/
temporary->next=NULL;//中删除
free(temporary2);//释放该节点内存空间
list->length--;
returnlist;
}
4:
主要加减函数
Linklist*AddList(Linklist*one,Linklist*two)//链表数值相加函数
{
inti=0,j=3,p=0;
Lnode*nowone,*nowtwo;
nowone=one->head->next;//节点指针分别指向链表的头结点
nowtwo=two->head->next;
if(one->length==two->length)//判断两链表的长度,以便过后判断是否末位进位
p=1;
for(i=0;ilength;i++)//循环加数的位数次,来分别对个个位进行相加
{
if(j==1)//j=1时表示该位有来至低位的进位
{
nowone->data=nowone->data+nowtwo->data+1;//该位有进位时的结果
j=0;
}
else
{
nowone->data=nowone->data+nowtwo->data;//该位没有进位的结果
}
if(nowone->data>=10)//判断该位是否需要向高位进位
{
nowone->data=nowone->data-10;//进位后该位的值
j=1;
}
nowone=nowone->next;
nowtwo=nowtwo->next;
}
if(j==1&&p!
=1)//两数位数不同,但最高位需进位时的情况
{
for(i=0;ilength-two->length;i++)//定位到加数的最高位
{
nowone->data++;//最高位向上进位一
if(nowone->data>=10)//如果该位加上来自低位的进位大于10时继
{//续向高位进位直至无需在进
nowone->data=nowone->data-10;
j=1;
nowone=nowone->next;
}
else
{
j=0;
break;
}
}
if(j==1)//如果结果的最高位也有进位
one=Inlistfail(one,1);//为储存结果的链表添加一个节点来保存进位
}
if(j==1&&p==1)
{
one=Inlistfail(one,1);
}
returnone;
}
Linklist*SubList(Linklist*listone,Linklist*listtwo)//减法函数
{
Lnode*nowone,*nowtwo;
inti=0,j=0;
nowone=listone->head->next;//定位到最低位的数值
nowtwo=listtwo->head->next;
for(i=0;ilength;i++)//做减数的位数次循环
{
if(j==1)//如果该位需向高位借位j=1
{
nowone->data=nowone->data-1-nowtwo->data;//该位借位后进行减法的结果
j==0;
}
else
nowone->data=nowone->data-nowtwo->data;//无需借位情况
if(nowone->data<0)//若该位被低位借位至小{//于零继续向高位借位
nowone->data=nowone->data+10;//借位后结果的值
j=1;
}
nowone=nowone->next;
nowtwo=nowtwo->next;
}
if(j==1)//若减数的最高位,仍需向高位借位,执行
{
while(j==1)//向被减数的高位循环借位,直到无需在借位
{
if(nowone->data==0)
{
nowone->data=9;
j=1;
nowone=nowone->next;
}
else
{
j=0;
nowone->data--;
}
}
}
returnlistone;//返回减法的到的结果
}
5:
不同情况操作函数
Linklist*Caseone(Linklist*listone,Linklist*listtwo)
{//判断后第一种情况
Linklist*final;
if(listone->length>=listtwo->length)//判断两数的位长,位数长的做为加数
final=AddList(listone,listtwo);//两数加法
else
final=AddList(listtwo,listone);//两数加法
returnfinal;
}
Linklist*Casetwo(Linklist*listone,Linklist*listtwo)
{//第二种情况
Linklist*final;
listone=OutList(listone);//两数值去负号,进行标准加法
listtwo=OutList(listtwo);
if(listone->length>=listtwo->length)
final=AddList(listone,listtwo);//加数与被加数相加
else
final=AddList(listtwo,listone);
returnfinal;
}
Linklist*Casethree(Linklist*listone,Linklist*listtwo,inti)
{//第三种需要进行减法的情况
Linklist*final;
if(i<10)