问题描述:假设计算器只能进行加减乘除运算,运算数和结果都是整数。
输入样例:1+12/2*3-12=
输出样例:7
思路:1.先将用户输入全部作为字符串存入一个链表中,再将此链表中的数字字符转换为数字,同运算符一起,存入另一个链表中。
2.遍历链表,先乘除后加减。
实现:1.存储用户输入的字符
typedef struct ch{//将用户的输入全部做为字符串存储到此链表中
int ch;
struct ch *next;
}Char;
2.输入字符,存入链表:
char ch;
Char *heads=NULL;
Char *currents,*previouss;
while(true)
{
currents=(Char*)malloc(sizeof(Char));
scanf("%c",&ch);
if(ch!='=')
{
if(heads==NULL)
heads=currents;
else
previouss->next=currents;
previouss=currents;
currents->ch=ch;
currents->next=NULL;
}
else
{
if(heads==NULL)
heads=currents;
else
previouss->next=currents;
previouss=currents;
currents->ch=ch;
currents->next=NULL;
break;
}
}
3.将字符转为数学表达式存储:
typedef struct cal{
int count;//交替存储数字和运算符
char oper;
int emm;//用来标记本节点存储的是数字还是运算字符,1为数字,-1为运算字符
struct cal *next;
struct cal *front;//加减乘除法都需要用到运算符下一位和前一位的数据
}Cal;
4.将字符链表的值经过整理后存入数学表达式链表:
while(true)
{
current=(Cal*)malloc(sizeof(Cal));
argu=s_gets(current,&heads,emm);
if(argu)
{
if(head==NULL)
{
head=current;
head->front =NULL;
}
else
{
previous->next=current;
current->front =previous;
}
previous=current;
current->next=NULL;
current->emm =emm;
emm=-emm;
}
else
break;
}
5.进行运算:
current=head;
while(current!=NULL)
{
if((current->oper=='/')||(current->oper=='*'))
{
if(current->oper=='/')
{
if(current->next ->count==0)
{
printf("ERROR");
return 0;
}
divi(¤t);//将current设置为被除数的地址,删除运算符和除数
}
else
{
mul(¤t);
}
}
current=current->next;
}
current=head;
while(current!=NULL)
{
if(current->oper =='+'||current->oper =='-')
{
if(current->count='+')
sum(¤t);
else
sub(¤t);
}
current=current->next;
}
6.细节函数:
bool s_gets(Cal *current,Char **heads,int emm)
{
Char *immi=*heads; //因为在后面我们会先改变heads的值,而后又需要用到heads的初值
if((*heads)->ch=='=')
return false;
if(emm==1)//存储数字
{
int tally=0,sum=0;//sum存储转化的数字
while((*heads)->ch>='0'&&(*heads)->ch<='9')
{
tally++;
(*heads)=(*heads)->next;
}//跳出循环后获得数字位数,heads指针的值也改变成最后一位数字字符后面的 运算符的地址
for(int i=tally;i>=1;i--)
{
sum=sum+pow(10,i-1)*(immi->ch-'0');
immi=immi->next;
}
current->count =sum;
current->emm=emm;
}
else
{
(*heads)=(*heads)->next;//指向下一位(下一位是数字字符)
current->oper =immi->ch;//在这里我最初写的是(*heads)忽略了其值已经改变
current->emm =emm;
}
return true;
}
void divi(Cal **current)
{
Cal *temp1,*temp2;
(*current)->front->count=(*current)->front->count/(*current)->next->count;
(*current)->front->next=(*current)->next->next;
if((*current)->next->next!=NULL) //我最初忽略了还需要把下下个节点(如果存在)的前一位节点更新
(*current)->next->next->front=(*current)->front;
temp1=(*current);
temp2=(*current)->next;
(*current)=(*current)->front;
free(temp1);
free(temp2);
}
void mul(Cal **current)
{
Cal *temp1,*temp2;
(*current)->front->count=((*current)->front->count)*((*current)->next->count);
(*current)->front->next=(*current)->next->next;
if((*current)->next->next!=NULL)
(*current)->next->next->front=(*current)->front;
temp1=(*current);
temp2=(*current)->next;
(*current)=(*current)->front;
free(temp1);
free(temp2);
}
void sum(Cal **current)
{
Cal *temp1,*temp2;
(*current)->front->count=(*current)->front->count+(*current)->next->count;
(*current)->front->next=(*current)->next->next;
if((*current)->next->next!=NULL)
(*current)->next->next->front=(*current)->front;
temp1=(*current);
temp2=(*current)->next;
(*current)=(*current)->front;
free(temp1);
free(temp2);
}
void sub(Cal **current)
{
Cal *temp1,*temp2;
(*current)->front->count=(*current)->front->count-(*current)->next->count;
(*current)->front->next=(*current)->next->next;
if((*current)->next->next!=NULL)
(*current)->next->next->front=(*current)->front;
temp1=(*current);
temp2=(*current)->next;
(*current)=(*current)->front;
free(temp1);
free(temp2);
}
7.输出结果(为了更直观,不直接用head->count,而是重新遍历一遍):
current=head;
while(current!=NULL)
{
if(current->emm==1)
printf("%d",current->count );
else
printf("%c",current->oper);
current=current->next ;
}
完整代码:
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<math.h>
typedef struct ch{//将用户的输入全部做为字符串存储到此链表中
int ch;
struct ch *next;
}Char;
typedef struct cal{
int count;//交替存储数字和运算符
char oper;
int emm;//用来标记本节点存储的是数字还是运算字符,1为数字,-1为运字符
struct cal *next;
struct cal *front;//乘除法都需要用到运算符下一位和前一位的数据
}Cal;
bool s_gets(Cal *current,Char **heads,int emm);//将Char链表的值作为输入传递给Cal链表
void divi(Cal **current);//计算除法
void mul(Cal **current);
void sum(Cal **current);
void sub(Cal **current);
int main(void)
{
int i,j;
Cal *head=NULL;
Cal *current,*previous;
bool argu;
int emm=1;
char ch;
Char *heads=NULL;
Char *currents,*previouss;
while(true)
{
currents=(Char*)malloc(sizeof(Char));
scanf("%c",&ch);
if(ch!='=')
{
if(heads==NULL)
heads=currents;
else
previouss->next=currents;
previouss=currents;
currents->ch=ch;
currents->next=NULL;
}
else
{
if(heads==NULL)
heads=currents;
else
previouss->next=currents;
previouss=currents;
currents->ch=ch;
currents->next=NULL;
break;
}
}
while(true)
{
current=(Cal*)malloc(sizeof(Cal));
argu=s_gets(current,&heads,emm);
if(argu)
{
if(head==NULL)
{
head=current;
head->front =NULL;
}
else
{
previous->next=current;
current->front =previous;
}
previous=current;
current->next=NULL;
current->emm =emm;
emm=-emm;
}
else
break;
}
//存储转换工作已完成,没有错误,不准在改
/*乘除法*/
current=head;
while(current!=NULL)
{
if((current->oper=='/')||(current->oper=='*'))
{
if(current->oper=='/')
{
if(current->next ->count==0)
{
printf("ERROR");
return 0;
}
divi(¤t);//将current设置为被除数的地址,删除运算符和除数
}
else
{
mul(¤t);
}
}
current=current->next;
}
//加减法
current=head;
while(current!=NULL)
{
if(current->oper =='+'||current->oper =='-')
{
if(current->count='+')
sum(¤t);
else
sub(¤t);
}
current=current->next;
}
current=head;
while(current!=NULL)
{
if(current->emm==1)
printf("%d",current->count );
else
printf("%c",current->oper);
current=current->next ;
}
}
bool s_gets(Cal *current,Char **heads,int emm)
{
Char *immi=*heads; //因为在后面我们会先改变heads的值,而后又需要用到heads的初值
if((*heads)->ch=='=')
return false;
if(emm==1)//存储数字
{
int tally=0,sum=0;//sum存储转化的数字
while((*heads)->ch>='0'&&(*heads)->ch<='9')
{
tally++;
(*heads)=(*heads)->next;
}//跳出循环后获得数字位数,heads指针的值也改变成最后一位数字字符后面的 运算符的地址
for(int i=tally;i>=1;i--)
{
sum=sum+pow(10,i-1)*(immi->ch-'0');
immi=immi->next;
}
current->count =sum;
current->emm=emm;
}
else
{
(*heads)=(*heads)->next;//指向下一位(下一位是数字字符)
current->oper =immi->ch;//在这里我最初写的是(*heads)忽略了其值已经改变
current->emm =emm;
}
return true;
}
void divi(Cal **current)
{
Cal *temp1,*temp2;
(*current)->front->count=(*current)->front->count/(*current)->next->count;
(*current)->front->next=(*current)->next->next;
if((*current)->next->next!=NULL)
(*current)->next->next->front=(*current)->front;
temp1=(*current);
temp2=(*current)->next;
(*current)=(*current)->front;
free(temp1);
free(temp2);
}
void mul(Cal **current)
{
Cal *temp1,*temp2;
(*current)->front->count=((*current)->front->count)*((*current)->next->count);
(*current)->front->next=(*current)->next->next;
if((*current)->next->next!=NULL)
(*current)->next->next->front=(*current)->front;
temp1=(*current);
temp2=(*current)->next;
(*current)=(*current)->front;
free(temp1);
free(temp2);
}
void sum(Cal **current)
{
Cal *temp1,*temp2;
(*current)->front->count=(*current)->front->count+(*current)->next->count;
(*current)->front->next=(*current)->next->next;
if((*current)->next->next!=NULL)
(*current)->next->next->front=(*current)->front;
temp1=(*current);
temp2=(*current)->next;
(*current)=(*current)->front;
free(temp1);
free(temp2);
}
void sub(Cal **current)
{
Cal *temp1,*temp2;
(*current)->front->count=(*current)->front->count-(*current)->next->count;
(*current)->front->next=(*current)->next->next;
if((*current)->next->next!=NULL)
(*current)->next->next->front=(*current)->front;
temp1=(*current);
temp2=(*current)->next;
(*current)=(*current)->front;
free(temp1);
free(temp2);
}