前中后缀表达式计算 无误c语言.docx
《前中后缀表达式计算 无误c语言.docx》由会员分享,可在线阅读,更多相关《前中后缀表达式计算 无误c语言.docx(20页珍藏版)》请在冰豆网上搜索。
前中后缀表达式计算无误c语言
#include/*导入需要用到的各种包*/
#include
#include
typedefstruct/*定义结构体用来存储操作符*/
{
charop;/*存储字符*/
intlevel;/*存储优先级*/
}OpNode;
typedefstruct
{
OpNodeop[100];
inttop;
intsize;/*表示栈内元素的个数*/
}stack;/*定义符号栈*/
voidinit(stack*st)/*初始化栈*/
{
st->size=0;
st->top=0;
}
OpNodepop(stack*a)
{
if(a->size==0)/*如果栈为空结束操作*/
{
exit(-1);
}
a->size--;
returna->op[--(a->top)];/*取出栈顶元素*/
}
voidpush(stack*a,OpNodeop)/*入栈函数*/
{
a->size++;
a->op[(a->top)++]=op;
}
OpNodetop(stack*a)/*观察栈顶函数*/
{
if(a->size==0)/*如果栈为空结束操作*/
{
printf("stackisempty\n");
exit(-1);
}
returna->op[(a->top)-1];/*只得到栈顶的值而不出栈*/
}
typedefstruct/*定义数值栈*/
{
doublenum[100];
inttop;/*栈顶指针*/
intsize;
}numstack;
voidinit2(numstack*st)/*初始化数值栈*/
{
st->size=0;
st->top=0;
}
doublepop2(numstack*a)/*数值栈出栈*/
{
if(a->size==0)/*出栈前的判空*/
{
exit(-1);
}
a->size--;
returna->num[--(a->top)];/*得到栈顶的值*/
}
voidpush2(numstack*a,doublenum)/*入栈*/
{
a->size++;
a->num[(a->top)++]=num;
}
intmain(void)/*主函数*/
{
voidchange(charstr[],charexp[]);/*声明要用到的各个函数*/
doubleCalResult(charexp[]);/*声明后缀表达式的计算函数*/
doubleDirectcalresult(charstr[]);
intcheck(charstr[],charchestr[100]);
charstr[100],exp[100],chestr[100];/*str存储原算术表达式,exp存储对应的printf("算术表达式为:
\n");后缀表达式,chestr存储容错字符'^'*/
gets(str);
if(check(str,chestr))/*调用容错函数*/
{printf("表达式错在:
\n");
printf("%s\n",str);
printf(chestr);/*根据输入情况指出错误的地方*/
exit(-1);
}
change(str,exp);/*调用函数将中缀转化为后缀*/
printf("后缀表达式为:
%s\n",exp);
printf("运算结果为:
%f\n",CalResult(exp));/*调用函数计算后缀表达式*/
printf("直接运算的结果为:
%f\n",Directcalresult(str));/*调用直接计算函数*/
}
voidchange(charstr[],charch[])/*将前缀表达式转化为后缀表达式*/
{
inti=0;/*str的索引*/
intk=0;
charc;/*字符串中取出的放在C中*/
stackst;/*定义符号栈*/
OpNodeop;
OpNodeops;
init(&st);/*初始化符号栈*/
c=str[i++];
while(c!
='\0')/*对字符串进行扫描*/
{
if((c>='0'&&c<='9')||c=='.')/*如果字符为数字或小数点*/
{
while((c>='0'&&c<='9')||c=='.')
{
ch[k++]=c;/*将字符直接放入数组中*/
c=str[i++];
}
ch[k++]='|';/*在其后面放入一个分隔符*/
}
if(c=='(')/*如果字符是左括号*/
{
op.op='(';
op.level=-1;/*定义其优先级为-1*/
push(&st,op);/*将左括号直接入栈*/
}
if(c==')')/*如果字符为右括号*/
{
op=top(&st);/*首先观察栈顶*/
while(st.size!
=0&&op.op!
='(')/*如果不是左括号并且栈不为空*/
{
op=pop(&st);/*出栈并存入数组中*/
ch[k++]=op.op;
if(st.size>0)/*再次检查栈是否为空,*/
op=top(&st);
elsebreak;/*为空就结束*/
}
pop(&st);/*去掉左括号*/
}
if(c=='+'||c=='-')/*如果是+-号*/
{
op.op=c;
op.level=1;/*优先级为1*/
if(st.size==0)
{
push(&st,op);/*如果此时栈为空直接入栈*/
}
else
{
ops=top(&st);/*观察栈顶*/
while(ops.level>=op.level)/*如果栈顶优先级高*/
{
ops=pop(&st);
ch[k++]=ops.op;/*将栈顶元素取出存入数组中*/
if(st.size>0)
ops=top(&st);/*进行判空操作,栈为空结束*/
else
break;
}
push(&st,op);/*此时栈顶优先级低,入栈*/
}
}
if(c=='*'||c=='/'||c=='%')
{
op.op=c;
op.level=2;/*优先级为1*/
if(st.size==0)
{
push(&st,op);/*如果此时栈为空直接入栈*/
}
else
{
ops=top(&st);/*观察栈顶*/
while(ops.level>=op.level)/*如果栈顶优先级高*/
{
ops=pop(&st);/*将栈顶元素取出存入数组中*/
ch[k++]=ops.op;
if(st.size>0)
ops=top(&st);/*进行判空操作,栈为空结束*/
else
break;
}
push(&st,op);/*此时栈顶优先级低,入栈*/
}
}
c=str[i++];/*索引自加检索下一个字符*/
}
while(st.size!
=0)/*最后判断栈如果不为空*/
{
ops=pop(&st);/*取出栈内元素存入数组中*/
ch[k++]=ops.op;
}
ch[k]='\0';/*将\0作为结尾存入数组*/
}
doubleCalResult(charexp[])/*后缀表达式的计算*/
{
charc;
numstacknumst;/*建立数值栈*/
doubled1,d2,dr;
intk=0;/*后缀表达式的索引*/
inti=0;/*将字符转化为浮点数的索引*/
char*s;
chartrans[100];/*存字符表示的一段数字*/
init2(&numst);/*实现数值栈*/
c=exp[k++];
while(c!
='\0')/*开始扫描后缀表达式*/
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%')/*如果是操作符*/
{
switch(c)
{
case'+':
/*如果是加法操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=d1+d2;/*相加后入栈*/
push2(&numst,dr);
break;
case'-':
/*如果是减法操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=d1-d2;/*相减后入栈*/
push2(&numst,dr);
break;
case'*':
/*如果是乘法操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=d1*d2;/*相乘后入栈*/
push2(&numst,dr);
break;
case'/':
/*如果是除法操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=d1/d2;/*相除后入栈*/
push2(&numst,dr);
break;
case'%':
/*如果是取余操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=(double)((int)d1%(int)d2);/*类型转化并取余后入栈*/
push2(&numst,dr);
break;
}
}
if(c>='0'&&c<='9'||c=='.')/*如果是字符表示的数字*/
{
while(c>='0'&&c<='9'||c=='.')
{
trans[i++]=c;/*将字符存入数组进行下一个的扫描*/
c=exp[k++];
}
trans[i++]='\0';/*将表示数字的字符串结束*/
i=0;
s=trans;/*将指针指向该数组*/
d1=atof(s);/*利用函数将字符串转化为浮点数*/
push2(&numst,d1);
}
c=exp[k++];
}
returnpop2(&numst);/*最后结果将在数值栈中,取出作为返回值*/
}
doubleDirectcalresult(charstr[])/*表达式的直接计算出结果*/
{
stackms;/*建立符号栈*/
numstackmns;/*建立数值栈*/
doublecalculate(doubleod1,doubleod2,OpNodeop);
intindex=0;/*str的索引*/
intlen=strlen(str);
charc;
chartrans[100];/*存放数值的一段字符*/
inti=0;/*trans的索引*/
char*s;
doubled;
OpNodetempn;/*存放当前扫描的操作符*/
OpNodetempln;
doubleoda,odb,odr;
doubleresult;/*作为返回值返回结果*/
init(&ms);/*实现两个栈*/
init2(&mns);
while(index{
c=str[index++];
if(c>='0'&&c<='9'||c=='.')/*如果是数字字符或小数点*/
{
while(c>='0'&&c<='9'||c=='.')
{
trans[i++]=c;/*将其存入数组扫描下一个*/
c=str[index++];
}
trans[i++]='\0';/*扫描完一个数结束数组*/
i=0;/*索引归0*/
s=trans;
d=atof(s);
push2(&mns,d);/*转化为浮点数入栈*/
}
if(c=='+'||c=='-')/*如果是+-*/
{
tempn.level=1;/*优先级设为1*/
tempn.op=c;
if(ms.size==0)
{
push(&ms,tempn);/*栈为空直接入栈*/
}
else
{
templn=top(&ms);
while(templn.level>=tempn.level)/*栈顶优先级高*/
{
templn=pop(&ms);/*取出操作数和操作符计算*/odb=pop2(&mns);
oda=pop2(&mns);
odr=calculate(oda,odb,templn);
push2(&mns,odr);/*结算结果入栈*/
if(ms.size>0)
{
templn=top(&ms);/*如果栈空结束*/
}
else
break;
}
push(&ms,tempn);/*操作符入栈*/
}
}
if(c=='*'||c=='/'||c=='%')
{
tempn.level=2;/*定义优先级为2*/
tempn.op=c;
if(ms.size==0)
{
push(&ms,tempn);/*栈空直接入栈*/
}
else
{
templn=top(&ms);
while(templn.level>=tempn.level)/*栈顶优先级高*/
{
templn=pop(&ms);/*取出操作数和操作符计算*/
odb=pop2(&mns);
oda=pop2(&mns);
odr=calculate(oda,odb,templn);
push2(&mns,odr);/*结算结果入栈*/
if(ms.size>0)
{
templn=top(&ms);
}
else
break;/*如果栈空结束*/
templn=top(&ms);
}
push(&ms,tempn);/*操作符入栈*/
}
}
if(c=='(')/*如果是左括号*/
{
tempn.level=-1;
tempn.op=c;/*直接入栈优先级定位-1*/
push(&ms,tempn);
}
if(c==')')/*如果是右括号*/
{
while(tempn.op!
='(')/*遇到左括号结束*/
{
templn=pop(&ms);
odb=pop2(&mns);/*从数栈中取两个数,从符号栈里取操作符*/
oda=pop2(&mns);
odr=calculate(oda,odb,templn);/*计算出结果入栈*/
push2(&mns,odr);
if(ms.size>0)
tempn=top(&ms);
else
break;/*如果栈空结束*/
}
pop(&ms);/*取出左括号*/
}
}
tempn=top(&ms);
while
(1)
{
templn=pop(&ms);
odb=pop2(&mns);/*从数栈中取两个数,从符号栈里取操作符*/
oda=pop2(&mns);
odr=calculate(oda,odb,templn);/*计算出结果入栈*/
push2(&mns,odr);
if(ms.size>0)
tempn=top(&ms);/*如果栈空结束*/
else
break;
}
result=pop2(&mns);/*最后的结果在数值栈中返回*/
returnresult;
}
doublecalculate(doubleod1,doubleod2,OpNodeop)/*已知操作符和操作数的计算*/
{
switch(op.op)
{
case'+':
returnod1+od2;
case'-':
returnod1-od2;/*判断操作符是哪个执行相应计算*/
case'*':
returnod1*od2;
case'/':
returnod1/od2;
case'%':
return(double)((int)od1%(int)od2);
}
return0;/*如果上面的都没有执行返回0*/
}
intcheck(charstr[],charchestr[100])/*容错函数*/
{
charc;
charcdivide;
inti=0;/*str的索引*/
stackche;/*括号匹配用到的栈*/
OpNodetemp;
intk=0;/*chestr的索引*/
intisinteger(charinteger[100]);/*%计算是判断是否是整数*/
chars1[10];/*%操作时存储%左右的数字*/
chars2[10];
intindexs1=0;/*s1s2的索引*/
intindexs2=0;
init(&che);
intflag=0;/*0——没有出错1——有错*/
inttag=0;
c=str[i];/*开始扫描*/
intj;/*数组chestr索引*/
for(j=0;j<99;j++)
{
chestr[j]='';/*数组初始化待以后加入'^'*/
}
chestr[j]='\0';
while(c!
='\0')
{
if(c=='(')/*如果是左括号就入栈*/
{
temp.op=c;
push(&che,temp);
}
if(c==')')/*如果是右括号*/
{
if(che.size>0)
{
pop(&che);/*栈不为空就取出一个左括号*/
}
else
{
flag=1;
printf("缺少左括号\n");/*否则提示有错*/
chestr[i]='^';/*右括号下加'^'*/
}
}
if(c=='/')/*判断除数是否为0*/
{
j=0;
cdivide=str[i+1+j];/*取出除号后的数*/
while(cdivide>='0'&&cdivide<='9'||cdivide=='.')/*如果是数或小数点就一直存*/
{
s1[j++]=cdivide;
if(cdivide!
='0'&&cdivide!
='.')/*如果不是0则正确并结束*/
{
tag=1;
break;
}
cdivide=str[i+j+1];
}
if(!
tag)/*如果tag为0则存在错误除数为0*/
{
chestr[i+1]='^';
flag=1;/*flag为1表示有错*/
}
}
if(c=='%')/*取余操作的容错*/
{
while(str[i-indexs1-1]>='0'&&str[i-indexs1-1]<='9'
||str[i-indexs1-1]=='.')/*以%为中心向前扫描*/
{
s1[indexs1++]=str[i-indexs1-1];/*如果是数或小数点*/
}/*放在s1中*/
while(str[i+indexs2+1]>='0'&&str[i+indexs2+1]<='9'/*以%为中心向后扫描*/
||str[i+indexs2+1]=='.')
{/*如果是数或小数点*/
s2[indexs2++]=str[i+indexs2+1];/*放在s1中*/
}
if(isinteger(s1))/*调用函数判断s1内存到是否是整数*/
{
printf("取余算法第一个数应为整数运算\n");
flag=1;/*记录为有错*/
chestr[i-indexs1]='^';
}
if(isinte