文章目录
- 题目描述
- 思路
- 使用getline()存储输入的字符串
- 边读取边压栈
- 完整代码
题目描述
使用stack处理括号化的表达式。当你看到一个左括号,将其记录下来。当你在一个左括号之后看到一个右括号,从stack中pop对象,直至遇到左括号,将左括号也一起弹出栈。然后将一个值(括号内的运算结果)push到栈中,表示一个括号化的(子)表达式已经处理完毕,被其运算结果所替代。
思路
使用getline()存储输入的字符串
是为了避免cin在提取字符串时遇到空格会终止读取的问题。例如:
// 当输入1 *2时
cin >> s; // s为1
getline(cin, s); // s为1 *2
边读取边压栈
创建两个栈:
- 一个用来存运算符
- 一个用来存操作数
当遇到 “)” 时,弹出运算符栈中的运算符、和对应的操作数栈中的操作数并进行计算直到遇到 “(” ,完成后将这期间的运算结果压入操作数栈。例如:
处理 “ (,+,) ” 时,将1,2作为操作数从nums栈中弹出,将处理结果3压入nums栈中,当然, “ (,+,) ” 三个运算符全部弹出symbol栈。之后:
遇到右括号时,将乘号、左括号弹出栈,在这过程中将3、4作为操作数弹出nums栈进行运算,之后,将运算结果压入nums栈。
当处理完全部括号后,将symbol栈中的运算符清空——也就是将对应的运算都进行计算,(在此过程中,减法和除法要注意操作数的先后问题):
当symbol栈中为空时,nums栈中仅有一个元素,也就是最终的计算结果。
完整代码
#include <iostream>
#include <stack>
#include <string>using namespace std;void resolve(stack<double>& s1, stack<char>& s2){while((!s2.empty()) && (s2.top() != '(')){char temp = s2.top();s2.pop();double num1 = s1.top(); //second//cout << "num1: " << num1 << endl;s1.pop();double num2 = s1.top(); //first//cout << "num2: " << num2 << endl;s1.pop();if(temp == '*'){s1.push(num1*num2);//cout << "*" << endl;}if(temp == '/'){s1.push(num2/num1); // 注意操作数的顺序//cout << "/" << endl;}if(temp == '+'){s1.push(num1+num2);//cout << "+" << endl;}if(temp == '-'){ // 注意操作数的顺序s1.push(num2-num1);//cout << "-" << endl;}}if(!s2.empty()){ // 当symbol栈不为空的时候if(s2.top() == '('){ // 遇见左括号也会跳出上述循环 s2.pop(); // 因此无法执行while中的pop} // 程序会一直卡在左括号的位置} // 所以在这里补上pop避免上述问题}double calculate(string& s) {if(s.empty()){return 0;}stack<double> nums;stack<char> symbol;double num = 0;string temp = ""; // 存储连续数值字符for(size_t i = 0; i < s.size(); i++){if((s[i] >= '0' && s[i] <= '9') || s[i] == '.'){ // 数字temp += s[i]; // 连续数值字符}if(((s[i]<'0'||s[i]>'9')&&s[i]!=' ') || i==s.size()-1){ // 运算符if(!temp.empty()){num = stod(temp); // num存储连续数值字符的终值nums.push(num);}if(s[i] == ')'){resolve(nums, symbol);}else{switch (s[i]) {case '(':case '+':case '-':case '*':case '/':symbol.push(s[i]); // 上述五种运算符直接压栈}}num = 0;temp.clear(); // 清空temp以便存储下一个连续数值字符}}resolve(nums, symbol);return nums.top();
}bool pankong(string& str){ // 判断左右括号是否数量一致int left = 0;int right = 0;for(auto beg = str.begin(); beg != str.end(); beg++){switch (*beg) {case ')': right++; break;case '(': left++; break;}}if(left != right){cout << "左右括号数量不对等" << endl;return false;}else{return true;}
}int main()
{string str; // 表达式double over; // 最终值//cin >> str;getline(cin,str);if(!pankong(str)){ // 判断左右括号数量是否一致return -1;}over = calculate(str);cout << "over: " << over << endl;return 0;
}