📄 运算器.c
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct DuLNode{//双向循环链表的结点
int data;
struct DuLNode *prior,*next;
}DuLNode,*PDuLNode;
typedef struct{//链表的头结点
PDuLNode head,ge;//head指向链表的第一个结点,ge指向数据的个位数所在结点
int n1,n2,trag;//n1是数据的整数位,n2是其小数位,trag表示数据的正负,1时为正,-1时为负
}DuLinkList,*PDuLinkList;
PDuLinkList Inicreat(char *fname)
//输入函数,当fname不为空是从文件fname输入,为空是从键盘输入
{
int t=1,*n;//t为控制变量,控制从文件读入还是从键盘读入,初始值为1,即默认从文件读入,n为输入数据整数位或小数位累加器
char c;//暂存每次读入字符
FILE *fp;
PDuLinkList num;//输入的数据储存在num链表中
PDuLNode q,p;
if(strcmp(fname,"\0")!=0)
while((fp=fopen(fname,"r"))==NULL){printf("\t输入文件错误,请重新输入:");scanf("%s",fname);}
else t=0;//当fname为空时,t=0,此后从键盘读入数据,否则从文件读入
num=(PDuLinkList)malloc(sizeof(DuLinkList));//以下为num及其头结点申请空间,并且初始化,构造储存结构形成双向循环链表
q=(PDuLNode)malloc(sizeof(DuLNode));
num->ge=NULL;num->head=q;num->n1=0;num->n2=0;num->trag=0;n=&num->n1;
q->data=0;q->next=q;q->prior=q;
if(t==1) c=fgetc(fp); else c=getchar();//当控制变量t=1时从文件读入,否则从键盘读入,以下雷同
if(c=='-') {num->trag=-1;if(t==1) c=fgetc(fp); else c=getchar();}//当第一个字符为'-'是,表示此数为负,trag赋值为-1,并继续读下一个符
else num->trag=1; //否则trag=1
while(c!='\n'){//当c不为'\n'时循环读入字符并储存
if(c>47&&c<58){//当c为数字时,转化并储存
q->data=c-48;
(*n)++;//整数或小数位加1,初始n指向整数位数,
p=(PDuLNode)malloc(sizeof(DuLNode));
p->next=q->next;q->next->prior=p;p->prior=q;q->next=p;
q=q->next;}
if(c=='.'){ //当读入小数点时
num->ge=q->prior;//个位指针指向前一个存入的数据
n=&num->n2;} //n变为指向小数位个数
if(t==1) if(feof(fp)) break;//当文件结尾时,读入数据完成,跳出循环
if(t==1) c=fgetc(fp); else c=getchar();//读入下一个字符
}
if(!num->ge) num->ge=q->prior;//当读入的数据为整数时,个位指针指向最后一个读入的数字
q=q->prior;q->next=q->next->next;q->next->prior=q;free(p);//删除最后申请的那个空结点,并释放内存空间
return num;//返回头结点地址
}
void print(PDuLinkList p,char *fname)
//输出函数,当fname不为空是输出到文件fname,为空是从输出到屏幕
{
int t=1;//t的用处同Inicreat函数
PDuLNode q;
FILE *fp;
if(strcmp(fname,"\0")!=0)
while((fp=fopen(fname,"w"))==NULL){printf("\t输出文件错误,请重新输入:");scanf("%s",fname);}
else t=0;//同Inicreat函数
if (p->trag==-1) if(t==1) fprintf(fp,"-"); else printf("-");//当trag为-1时先输也出“-”
q=p->head;
if(t==1) fprintf(fp,"%d",q->data);else printf("%d",q->data);
q=q->next;
while (q!=p->head)
{
if(q->prior==p->ge) if(t==1) fprintf(fp,"."); else printf(".");//当输出的前一个是个位时输出小数点
if(t==1) fprintf(fp,"%d",q->data);else printf("%d",q->data);
q=q->next;
}
if(t==1) {fprintf(fp,"\n");fclose(fp);}else printf("\n");
}
int compare(PDuLinkList a,PDuLinkList b,int t)
//此函数用于判断在做加法或减法运算时不同情况下结果的正负号
{
int trag=0;//trag=1时,a>b;trag=0时,a=b;trag=-1时,a<b。初始值为0,即默认情况下a=b
PDuLNode p1,p2;
int ts[3][3][3][3]={//此四维数组中存了不同情况下结果的正负号,四维中的第一维:trag+1;第二维:a->trag+1,即a的正负;第三维:b->trag+1,b的正负;第四维:t+1,加或减运算
1,0,-1,0,0,0,-1,0, 1,0,0,0,0,0,0,0,0,0,1,0,-1,0,0,0,-1,0,1,//1表示正,-1表示负,0是不存在的睛况
1,0,-1,0,0,0,-1,0, 1,0,0,0,0,0,0,0,0,0,1,0, 1,0,0,0, 1,0,1,
-1,0,-1,0,0,0,-1,0,-1,0,0,0,0,0,0,0,0,0,1,0, 1,0,0,0, 1,0,1};
p1=a->head;p2=b->head;//以下判断a与b的大小
if (a->n1>b->n1) trag=1;
else if (a->n1<b->n1) trag=-1;
else
{
if(p1->data>p2->data) trag=1;
else if(p1->data<p2->data) trag=-1;
else
{ p1=p1->next;p2=p2->next;
while(p1!=a->head&&p2!=b->head)
if(p1->data>p2->data){trag=1;break;}
else if(p1->data<p2->data) {trag=-1;break;}
else {p1=p1->next;p2=p2->next;}
}
if(trag==0&&p1!=a->head) trag=1;
if(trag==0&&p2!=b->head) trag=-1;
}
return ts[trag+1][a->trag+1][b->trag+1][t+1];//返回正负号情况
}
void Adjust(PDuLinkList L)
//此函数用于修正结果数据,以去掉数据头部或尾部的零
{
PDuLNode p,q;
while (L->head->data==0&&L->head!=L->ge) L->head=L->head->next;//头结点后移支首个不为0的数或个位
p=L->head->prior;
while(p->data==0&&p!=L->ge)//删除多余的零
{q=p->prior;p->prior->next=p->next;p->next->prior=p->prior;free(p);p=q;}
}
PDuLinkList AddSub(PDuLinkList a,PDuLinkList b,int t)
//此函数用于时进加减法运算,当t=1时返回a+b的值,当t=-1时返回a-b的值
//运算时,从个位数开始分别向两头进行,即整数部分从右往左,小数部分从左往右
{
int sum,t2;//sum存每一位的运算结果;t2同t,它们分别在不同情况下控制两数是做加运算还是减运算
PDuLinkList res;//res即result,结果链表
PDuLNode p,ph,p1,p2,q,q1,q2;//p,ph,p1,p2都为原始数据链表指针;q,q1,q2都为结果链表指针
res=(PDuLinkList)malloc(sizeof(DuLinkList));//以下几行是为结果链表申请空间并初始化
q1=(PDuLNode)malloc(sizeof(DuLNode));
res->head=NULL;res->ge=q1;res->n2=0;res->trag=0;
res->trag=compare(a,b,t);//调用compare函数,判断结果的正负
q1->data=0;q1->next=q1;q1->prior=q1;
t=t*a->trag*b->trag;//t控制每位数之间的加或减
//以下为整数部分的运算,各指针从个位开始前移
p1=a->ge;p2=b->ge;//以下几行(while语句之前)先做一位运算,以防原始数据中整数位只有一位
sum=p1->data+p2->data*t;//每次运算时,b中的数据都必须先乘以t,然后再与a中的数据相加,让t达到控制加减的效果
q1->data+=sum;
q2=(PDuLNode)malloc(sizeof(DuLNode));q2->data=0;//申请一结点空间并初始化为0
q2->prior=q1->prior;q1->prior->next=q2;q2->next=q1;q1->prior=q2;//把新申请的结点插入结果双向链表中
q2->data=q1->data/10;q1->data=q1->data%10;//当sum>10时进位
if(q1->data<0){q1->data+=10;q2->data--;}//当sum<0时退位
q1=q2;//结果链表指针前移一位
while(p1!=a->head&&p2!=b->head)//对a和b整数部分相同的位数进行运算,各语句功能同上
{
p1=p1->prior;p2=p2->prior;//a与b的数据指针前移
sum=p1->data+p2->data*t;
q1->data+=sum;
q2=(PDuLNode)malloc(sizeof(DuLNode));q2->data=0;
q2->prior=q1->prior;q1->prior->next=q2;q2->next=q1;q1->prior=q2;
q2->data=q1->data/10;q1->data=q1->data%10;
if(q1->data<0){q1->data+=10;q2->data--;}
q1=q2;
}
p=(PDuLNode)malloc(sizeof(DuLNode));//此两行没有实际用处,只是防止出错
ph=(PDuLNode)malloc(sizeof(DuLNode));
p=ph;//当下两个if语句没有运行是,下一个while语句也不用运行
if(p1!=a->head) {p=p1;ph=a->head;t2=1;}//当a中还有数据时,复制到res中,t2功能同上面的t,控制复制时是加还是减
if(p2!=b->head) {p=p2;ph=b->head;t2=t;}//当b中还有数据时,复制到res中
while(p!=ph)//具体的复制语句,各句功能与前面的雷同
{
p=p->prior;
q1->data+=p->data*t2;
q2=(PDuLNode)malloc(sizeof(DuLNode));
q2->prior=q1->prior;q1->prior->next=q2;q2->next=q1;q1->prior=q2;
q2->data=q1->data/10;q1->data=q1->data%10;
if(q1->data<0){q1->data+=10;q2->data--;}
q1=q2;
}
res->head=q1;//把q1赋给结果链表的头指针
//以下开始做小数部分的运算,各指针从个位向后移
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -