题意:输入一个表达式,求其表达式的结果输入的是一个中缀表达式,所以我们需要将其先转化为后缀式,然后使用后缀式求其结果,有点类似于数据结构课上的那个表达式求值。
思路:
一.将中缀表达式转化为后缀表达式,首先判断是数字还是运算符,
①如果是数字的话,我们需要判读是不是最后一个字符或者下一个字符不是数字的话,将字符和‘#’压入后缀栈,否则将该字符压入后缀栈。
②如果是运算符的话,又分成三种情况:
1.该字符为‘(’或则字符栈为空或则该字符的优先级大于其字符栈栈顶字符的优先级,则将该字符压入字符栈;
2.如果该字符是‘)’,则将字符栈内‘(’后的字符加入后缀栈,然后将该字符从字符栈内弹出;
3.该字符的优先级小于等于字符栈栈顶字符的优先级,将字符栈内小于该字符的优先级的字符加入后缀栈,然后弹出。
最后将字符栈内剩余的字符全部加入后缀栈,然后在将后缀栈的字符全部加到ch字符数组中。
二.计算值,
①如果是数字,第一种情况:如果后面一个字符如果是#,表示是一个数,可以直接压入栈内,第二种情况后面第一个字符也是数字,则先计算了之后保存,直到遇到了‘#’符,然后将数字压入数字栈内;
②如果是一个运算符,则需要判断一下栈内是不是为空了,因为可能出现-4+3这样的情况出现,-是一个负数的标识而不是一个二位运算符,而导致没有数弹出与4运算,所以弹出前先判断一下。把弹出的两个数字进行相应的运算,把运算的结果压入栈内,最后栈内只剩下了最后的运算结果了。直接返回即可。
注意保存数字的栈一定要使用数字栈,否则第二个通不过
参考大佬的博客:https://blog.csdn.net/reidsc/article/details/54669433
代码:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cmath>
#include<stack>
#define N 150
using namespace std;
char ch[N];
int fun(char ch, int x, int y) {
if (ch == '+')return x + y;
if (ch == '-')return x - y;
if (ch == '*')return x * y;
if (ch == '/'&&y != 0)return x / y;
}
int priority(char ch) {
if (ch == '(' || ch == ')')return 1;
if (ch == '+' || ch == '-')return 2;
if (ch == '*' || ch == '/')return 3;
}
void transform(int n) {//中缀表达式转化为后缀表达式
stack<char> s1, s2;//s1保存最后的后缀表达式的结果,s2保存的是运算符
for (int i = 0; i < n; i++) {
if (ch[i] >= '0'&&ch[i] <= '9') {//如果该字符为数字的时候
if (i == n - 1 || (i + 1 < n && (ch[i + 1]<'0' || ch[i + 1]>'9'))) {//如果后一个字符是最后一个或者是运算符的时候
s1.push(ch[i]);
s1.push('#');//#用于隔开两个整数
}
else {//后面可能还有字符,而且是一个整数的多个字符
s1.push(ch[i]);
}
}
else {//为运算符,三种情况直接入栈:1. 字符栈为空;2.该字符为(,3.字符的优先级大于字符栈的优先级
if (s2.empty() || ch[i] == '(' || priority(ch[i]) > priority(s2.top())) {
s2.push(ch[i]);
}
else if (ch[i] == ')') {//如果字符为),则把(后面的非()字符加入s1栈,形成后缀式
while (s2.top() != '(') {
s1.push(s2.top());
s2.pop();
}
s2.pop();//把(移出来
}
else {//字符的优先级小于字符栈顶的优先级,依次弹出其字符串
while (!s2.empty() && priority(s2.top()) >= priority(ch[i]) && s2.top() != '(') {
s1.push(s2.top());
s2.pop();
}
s2.push(ch[i]);
}
}
}
while (!s2.empty()) {//把s2中剩余的字符加入s1中去
s1.push(s2.top());
s2.pop();
}
int k = 0;
while (!s1.empty()) {//将s1的后缀表达式用ch保存
ch[k++] = s1.top();
s1.pop();
}
reverse(ch, ch + k);//翻转,因为是栈结构,所以是个反的
}
int cal(int n) {
stack<int> s1;//一定要是数字栈,否则会报错
int k = 0, tem = 0;
for (int i = 0; i < n; i++) {
if (ch[i] == '#')continue;
else if (ch[i] == '+' || ch[i] == '-' || ch[i] == '*' || ch[i] == '/') {
int x = 0, y = 0;
if (!s1.empty()) {
x = s1.top();
s1.pop();
}
if (!s1.empty()) {//防止出现-4+3这样的表达式
y = s1.top();
s1.pop();
}
int t = fun(ch[i], y, x);
s1.push(t);
}
else {//是数字
k++;
tem = tem + (ch[i]-'0')*(int)pow(10,k-1);//暂存其数的部分
if (ch[i + 1] == '#') {//在后缀表达式中数字后面只能是数字和#
s1.push(tem);
k = 0;//k保存的是数字的位数
tem = 0;//tem保存的是一个数字
}
}
}
return s1.top();
}
int main() {
scanf("%s", ch);//输入字符串
transform(strlen(ch));
printf("%d\n", cal(strlen(ch)));
return 0;
}