一个计算式,比如 30 + 7 *4 - (5 + 69) /3
利用计算机计算,就需要将其化成逆波兰式。 化成逆波兰式的结果为 30 7 4 * + 5 69 + 3 / -
这样子就可以直接计算了:遇到操作符,就从栈中弹出两个数字,计算完在push到里面
过程: 30 28(遇到*) + 5 69 + 3 / -
58(遇到+) 5 69 + 3 / -
58 74(遇到+) 3 / -
58 24(遇到/) -
34 为最终结果
我的代码实现过程是:
开辟两个栈,一个栈用来存放数值,另一个栈用来存放操作符。
numS
opS
过程如下:
(1)
numS: 30 7
opS: +
(2)
下面即将读到 *, 发现*的优先级 比opS栈顶的优先级高,所以入栈,结果为:
numS: 30 7
opS: + *
(3)
numS: 30 7 4
opS: + *
(4)下面读到的是 ‘-’, 比top(opS)优先级低, 所以从 opS中弹出栈顶 *,从numS中弹出两个数 4 ,7 ,计算后再把结果push到 numS
numS: 30 28
opS: +
此时 ‘-’ 优先级依然不高于top(opS),所以 继续弹出两个数与一个操作符,再把运算结果push到栈中。一直如此,知道操作符栈为空,或者top(opS)优先级高于‘-’;
最后把‘-’压入栈。
numS: 58
opS: -
(5)
numS: 58 5 69
opS: - ( + //(的优先级设为最低)
(6)
下面就要读到‘)’。 一直弹出两个数与一个运算符,知道遇到‘(’
numS: 58 74
opS: -
(7)
numS: 58 74 3
opS: - /
(8)整个序列都读完之后,若 操作符栈不为空,则逐个弹出。
numS:58 24
opS: -
最后一步得到结果34!!!
参考代码: (栈的定义 见我的文章 栈ADT 中)
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<ctype.h>
int calculate(const char *p)
{
int num;
int result;
char op,t;
int i=0;
stack *opS =createStack(100);
stack *numS =createStack(100);
while(*p != '\0')
{
t=*p;
if(isspace(t))
{
p++;
continue;
}
else if( isdigit(t) )
{
/*处理一个数字*/
num = 0;
while( isdigit(*p) )
{
num =10*num+(*p-'0');
p++;
}
push(num,numS); //获得一个数字,并把这个数字压栈
}
else if( t=='+' || t=='-' ||t=='*' || t=='/'|| t =='(' || t==')')
{
if(isEmpty(opS) || t=='(')
{
push(t,opS);
p++;
}
else if (t ==')')
{
int num1,num2,op;
op=pop(opS);
while(op != '(')
{
num1 = pop(numS);
num2 = pop(numS);
switch(op)
{
case '+':
result=num2+num1;
break;
case '-':
result=num2-num1;
break;
case '*':
result=num2*num1;
break;
case '/':
result =num2/num1;
break;
}
push(result,numS);
op=pop(opS);
}
p++;
}
else
{
op = top(opS);
while(getPrio(t) <=getPrio(op) )
{
int num1,num2;
num1 = pop(numS);
num2 = pop(numS);
op=pop(opS);
switch(op)
{
case '+':
result=num2+num1;
break;
case '-':
result=num2-num1;
break;
case '*':
result=num2*num1;
break;
case '/':
result =num2/num1;
break;
}
push(result,numS);
if(isEmpty(opS))
break;
op = top(opS);
}
push(t,opS);
p++;
}
}
}
while(!isEmpty(opS))
{
int num1 = pop(numS);
int num2 = pop(numS);
int op = pop(opS);
switch(op)
{
case '+':
result=num2+num1;
break;
case '-':
result=num2-num1;
break;
case '*':
result=num2*num1;
break;
case '/':
result =num2/num1;
break;
}
push(result,numS);
}
return top(numS);
}
int main()
{
int num= calculate("30+7 *4 -(5 +69 )/ (3-1) ");
printf("%d\n",num);
printf("%d\n",30+7 *4 -(5 +69) /(3-1) );
return 0;
}