表达式求值
C++ 环境codeblocks17 通过
/*
表达式求值,可用运算符 +-/*(){}[]
@CGQ 2018/10/30
*/
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<stack>
char compare(char, char); //比较运算符优先级
float Operation(float, float, float ); //实际运算函数
int getnext(float * n); //该函数返回0为数字,返回1为运算符
float EvaluateExpression(); //表达式求值返回结果
int getnext(float * n) //该函数返回0为数字,返回1为运算符
{
char c;
*n = 0;
while((c = getchar()) == ' '); //跳过空格
if(!isdigit(c)) //判断是否是数字
{ // 不是数字
if(c=='{'||c=='[')
*n = '(';
else if(c=='}'||c==']')
*n = ')';
else
*n = c;
return 1;
}
do
{
*n = *n * 10 + (c - '0'); //使用循环获得连续的数字,乘10进位
c = getchar();
}
while(isdigit(c));
ungetc(c, stdin); //读到一个运算符,将运算符写回输入缓存
return 0;
}
/*
对于连续出现的运算符进行比较优先级
结果有> < =,可以得到+-×/之间的优
先级,加减乘除的优先级都低于'(',
但是都高于')',并且根据从左到右运算
可知当运算符相同时,第一个大于第二
个,0表示不存在
*/
char compare(char a, char b)
{
int i, j;
char pre[7][7] = //定义运算符之间的优先级
{
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='},
};
switch(a)
{
case '+':
i = 0;
break;
case '-':
i = 1;
break;
case '*':
i = 2;
break;
case '/':
i = 3;
break;
case '(':
i = 4;
break;
case ')':
i = 5;
break;
case '#':
i = 6;
break;
}
switch(b)
{
case '+':
j = 0;
break;
case '-':
j = 1;
break;
case '*':
j = 2;
break;
case '/':
j = 3;
break;
case '(':
j = 4;
break;
case ')':
j = 5;
break;
case '#':
j = 6;
break;
default:
printf("表达式要以#结尾!!!\n");
exit(1);
}
return pre[i][j];
}
float Operation(float a, float operate, float b) //实际操作两个数a,b的运算
{
float result;
a = (float)a;
b = (float)b;
switch((int)operate)
{
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
result = a * b;
break;
case '/':
result = a / b;
break;
}
return result;
}
float EvaluateExpression()
{
float c; //存储输入缓存中的字符或数字
float flag; //从输入缓存中取操作符的返回值,0表示取出数字,1表示取出运算符
float x; //取栈顶操作符
char operate; //存储要计算的操作符
float a, b; //存取要计算的操作数
std::stack<float> ns;
std::stack<char> os; //ns为操作数栈,os为运算符栈
os.push('#');
flag = getnext(&c);
x = os.top();
while((float)c != '#' || (float)x != '#') //表达式的起始位置都是'#',如果读取的新的字符和运算符都是'#'说明运算已经结束
{
if(flag == 0) //返回数字
{
ns.push(c);
flag = getnext(&c);
}
else //返回运算符
{
x = os.top(); //取栈顶运算符
switch(compare((float)x, (float)c))
{
case '<': //栈顶操作符运算优先级低
os.push(c);
flag = getnext(&c);
break;
case '>': //栈顶运算符优先级高,先退出两个数据进行运算,然后将运算结果在存入数据栈
operate = os.top();
os.pop();
a = ns.top();
ns.pop();
b = ns.top();
ns.pop();
ns.push(Operation(b, operate, a)); //由于压栈的顺序,则应当是先出的操作数在后
break;
case '=': //操作符'('')'紧挨,则直接去除括号
operate = os.top();
os.pop();
flag = getnext(&c);
break;
case '0': //比较结果得出表达式错误
printf("input error!\n");
exit(1);
}
}
x = os.top();
}
c = ns.top();
return c;
}
int main(void)
{
float c;
printf("please input expression (end in #):");
c = EvaluateExpression();
printf("result = %f\n", c);
getchar();
}
/*
测试数据
20-2*(5-1-3*(4-1)-2)-6#
1+(2+3)*[3+6]/{4+5}+{[8*7]}#
1+{[2+3]}#
*/