首先我们日常见到的表达式是下面这个样子的
((1+2)*5+1)/4;
诸如此类的式子叫做中缀表达式这种表达式是基于人的思维方式
运算符号在两个要运算的数字中间,但是这并不利于计算机的计算,
计算机只需要知道要运算那两个数字和运算符号就好,
所以我没们在这里可以利用后缀表达式(也称逆波兰式)后缀表达式子
是如下样子
1#2+#5#*1+#4/ // #用于分隔两个数字
那么写成这样有什么优点呢?
(1).操作符位于操作数之后;
(2).没有括号;
(3).操作符没有优先级;
那么我们怎样将一个中缀表达式转化为后缀表达式呢?
在这里我们就需要用到栈的特性(后入先出)
中缀表达式转后缀表达式
开辟:操作符栈 stack<char>oc、结果字符串ans[];
(1).操作数压到结果字符串;操作符玉如操作符栈;
(2).当待压入操作符栈的操作符优先级大于栈顶操作符时,直接入栈;
若小于等于栈顶操作符的话,栈顶操作符加入到结果字符串后面,直到遇到前括号‘(’或者栈顶操作符优先级小于待入栈操作符,最后待入栈操作符入栈;
(3).如果时前‘(’直接入栈;
(4).如果是后‘)’,将栈中操作符依次弹出并压入结果字符串,并弹出前‘(’不加入结果字符串;
根据以上四个步骤,得到的就是后缀表达式;
实现代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stack>
#include<algorithm>
using namespace std;
char ans[5000],s[1100];//ans结果字符串,s原串;
int cmp(char c) {
if (c == '(')
return 0;
else if (c == '+' || c == '-')
return 1;
else if (c =='*' || c == '/')
return 2;
}
double subans(double x , double y , char c) {
if (c == '+')
return x + y;
if (c == '-')
return x - y;
if (c == '*')
return x * y;
if (c == '/')
return x / y;
}
int main(void) {
int T;
stack<char>oc; //中缀->后缀 操作符栈;
stack<double>on; //后缀->求值 操作数栈;
scanf("%d", &T);
while(T--) {
int k = 0;
while(!oc.empty()) oc.pop();
while(!on.empty()) on.pop();
scanf("%s", s);
int len = strlen(s);
s[len] = '=';
//中缀-->后缀;
for(int i = 0; i <= len; i++) {
if ((s[i]>='0'&&s[i] <= '9')|| s[i] =='.')
ans[k++] = s[i];
else if(s[i] == '+'|| s[i] == '-'|| s[i] == '*'||s[i] == '/') {
ans[k++] = '#';
if (oc.empty())
oc.push(s[i]);
else {
// 2+(3+2*3-2*1)
while(!oc.empty()&&cmp(oc.top()) >= cmp(s[i])) {
ans[k++] = oc.top();
oc.pop();
}
oc.push(s[i]);
}
}
else if(s[i] == '(') {
oc.push(s[i]);
}
else if(s[i]==')') {
while(oc.top()!='(') {
ans[k++] = oc.top();
oc.pop();
}
oc.pop();
}
else if(s[i] == '=') {
while(!oc.empty()) {
ans[k++] = oc.top();
oc.pop();
}
}
}
//ans[k++] = '=';
//得到后缀表达式 ans;
// printf("\n");
//puts(ans);
//后缀表达式求值;
int pos = 0;
for(int i = 0; i < k; i++) {
pos = 0;
if (ans[i] >= '0'&& ans[i] <= '9')//对操作数进行操作;
{
for(int j=i; j<k; j++) {
if ((ans[j] >= '0'&& ans[j] <= '9')|| ans[j] == '.')
pos++;
else
break;
}
double k = 1, sum1 = 0, sum2 = 0;
for(int j = i + pos - 1; j >= i; j--) {
if (ans[j] >= '0' && ans[j] <= '9') {
sum1 += (ans[j] - '0') * k;
k *= 10;
}
else if(ans[j] == '.') {
sum1 /= k;
k = 1;
sum2 += sum1;
sum1 = 0;
}
}
sum2 += sum1;
on.push(sum2); //报操作数压入操作数栈中;
i += pos - 1;
}
else if (ans[i] == '+'||
ans[i] == '-'|| ans[i] == '*'|| ans[i] == '/') {
double x = on.top();
on.pop();
double y = on.top();
on.pop();
on.push(subans(y,x,ans[i])); //求值,结果仍压入操作数栈;
}
}
printf("%.2lf\n",on.top()); //处理操作数栈中只有一个操作数;
}
return 0;
}