题目大意
输入一系列的字符串,进行模拟计算器的计算,只不过这个计算器比较简单只涉及到加减和括号的运算,在里面还会有空格干扰
之前做过类似的题目要带上乘除运算(不过程序被我不小心删掉了)
实现思路:
使用的数据结构栈:
- 数据栈
- 操作符栈
状态转换
借鉴别人的思想系统的说,在这个过程中会有两种状态的转换
可以使用一个state变量来标识
- 当处于处理数字状态下,将例如12的字符串转换为12数值类型的元素
- 同时判断下该数值转换是否已经恰好完成,即下一个状态为处理操作符状态,或者整个字符串已经结束。若果已经恰好完成或整个字符串处理到最后一位,将该数值压入栈中。再判断下cmp_flag是否为1,如果为1,则 从数据栈弹出两个元素,操作符栈弹出一个元素,进行计算,并将结果压入栈中。
- 当处于处理操作符状态下
- 如果为’( ',设置计算标识cmp_flag=0
- 如果为’)’ 表明现在立即可以进行计算
- 如果为其他操作符,设置计算标识cmp_flag=1,并且将操作符压入操作符栈中
可以在处理状态操作之前判断当前字符是否为空格,如果为空格直接continue即可
实现代码
#include <stack>
#include <iostream>
#include <cctype>
using namespace std;
const int BEGIN = 0;
const int NUMBER = 1;
const int OPERA = 2;
long long compute(stack<long long>& data, stack<char>& opera,int flag) {
long num2 = data.top();data.pop();
long num1 = data.top();data.pop();
char op = opera.top();opera.pop();
if (op == '+') {
return num1 + num2;
}
else if (op == '-') {
if (flag)
return num1 - num2;
else
return num2 - num1;
}
return 0;
}
class Solution {
public:
int state;
int cmp_flag;
stack<long long> data;
stack<char>opera;
Solution() {
state = BEGIN;
cmp_flag = 0;
}
int calculate(string s) {
long long num = 0;
for (int i = 0;i < s.length();i++)
{
if (s[i] == ' ')continue;
if (isdigit(s[i]))
state = NUMBER;
else
state = OPERA;
switch (state) {
case NUMBER: {
num = num * 10 + s[i] - '0';
if ((i + 1 < s.length() && !isdigit(s[i + 1])) || i + 1 == s.length()) {
data.push(num);
if (cmp_flag && data.size() >= 2)
{
data.push(compute(data, opera,1));
}
num = 0;
}
break;
}
case OPERA: {
if (s[i] == '(')
cmp_flag = 0;
else
{
cmp_flag = 1;
if (s[i] != ')')
{
opera.push(s[i]);
if (i == 0)
data.push(0);
}
else {
if(data.size()>=2)
data.push(compute(data, opera, 1));
}
}
break;
}
}
}
stack<long long>tdata;
stack<char> topera;
if (!opera.empty()) {
while (!data.empty()) { tdata.push(data.top());data.pop(); }
while (!opera.empty()) { topera.push(opera.top());opera.pop(); }
while(!topera.empty())
tdata.push(compute(tdata, topera,0));
if (!tdata.empty()) data.push(tdata.top());
}
if (data.empty()) return 0;
return data.top();
}
};
int main() {
Solution s;
int sum=s.calculate("(1+(4+5+2)-3)+(6+8)");
cout << sum<<endl;
return 0;
}
}
另一种实现的代码
踩过的坑:
- -2+1
- 这种情况下最开始没有考虑,后来改进当压入的第一个字符为操作符时,在数据栈压入一个0
- 数值超过int类型最大值
- 当时没注意数值范围,只看到给的接口,函数返回值是int,后来在计算过程中都用的long long,最后返回的是int
- 不要忘记只有数据栈的元素≥2才可进行运算
- 按照我的方法处理的相当于是第一轮,实际上还有可能栈中还有元素,剩下的元素按照之前输入的顺序依次算即可,但我实现的有一些些麻烦,将栈中元素导了出来再计算,在利用我写的额外计算的函数,在相减的时候还要颠倒相减才可以,实在是有些繁琐