先直接贴上题目,大家感受一下:
自定义运算符 @,#,$,&,并且优先级@>#>$>&,利用下面的计算法则,计算出一个给定的字符串表示的表达式的值,返回整型结果。
x@y = (x-1)*(y+1);
x#y = (2*x+5)*(3*y+60)
x$y = (x+1)*(2*x+3)*(y-1)*(2*y-3)
x&y = ((x+y+1)*(y-9)+(x+7)/(y-8))
输入:接受多行输入,每行可能有空格。题目保证不会出现除数为0的情况,且所有操作数都是整数。为了简单起见,表达式不含有括号。
输出:对于每一行输入,输出一个运算结果。
输入样例:
1@2
1#2
1@1@1
1#1#1
1$1$1
1&1&1
1#1@1
1@1#1
1$1&1
1&1$1
1 # 1 & 1
12 @ 12
123 @ 123
输出:
0
462
-2
55881
0
186
420
315
-17
-19
-3608
143
15128
分析:
大体来看,程序主要流程为这么几步
1. 将得到的字符串进行去空格处理。
2. 将第1步得到的字符串(此为中缀形式)转换为逆波兰式(后缀式)
3. 将第2步得到的逆波兰式(RPN)进行计算,求出结果并输出。
核心算法伪代码:
1. 将中缀形式转化为后缀形式:
从左往右扫描inputString
if 当前扫描的是操作数
输出该操作数
else //当前扫描的是操作符
while 无限循环
if 栈为空 或 栈顶元素优先级小于该操作符
该操作符入栈
break
else
输出栈顶元素,并pop
//扫描inputString完毕
while 栈内还有元素
输出栈顶元素,并pop
2.将后缀形式计算为结果
从左往右顺序扫描inputRPN
if 当前扫描的是操作数
该操作数入栈
else //当前扫描到的是操作符
从栈中弹出两个操作数,参加该操作符的运算
运算结果入栈
注意细节:
1. 在由于要处理76 @ 321
这样的多位操作数,因此在转换RPN的时候要注意顺带进行atoi的操作。
2. 若直接用cin>>进行初始化输入的操作,题目中的空格被隔断成多个字符串,比如这种输入123 @ 123
,因此要使用getline来进行初始化操作。
成品代码:
使用C++11 mode下的GCC编译通过。
#include <iostream>
#include <map>
#include <stack>
#include <vector>
using namespace std;
class MarsCalc {
public:
int calcResult(string inputStr) {
string stringWithoutSpace = removeSpcace(inputStr);
vector<int> RPN = convertToRPN(stringWithoutSpace);
return calcRPN(RPN);
}
private:
map<char, int> queryPriority = map<char, int> { { '@', INT32_MIN + 1 }, { '#', INT32_MIN + 2 }, { '$', INT32_MIN + 3 }, { '&', INT32_MIN + 4 } };
string removeSpcace(string inputStr) {
string stringWithoutSpace;
for (char ch : inputStr)
if (ch != ' ')
stringWithoutSpace.append(1, ch);
return stringWithoutSpace;
}
vector<int> convertToRPN(string inputStr) {
vector<int> RPN2;
stack<char> operatorStack;
int atoiNumber = 0;
for (char ch : inputStr) {
if (ch >= '0' && ch <= '9') { //操作数
atoiNumber = atoiNumber * 10 + ch - '0';
} else { //操作符
RPN2.push_back(atoiNumber);
atoiNumber = 0; //atoi清零
while (true) {
if (operatorStack.empty() == true || queryPriority[operatorStack.top()] > queryPriority[ch]) {
operatorStack.push(ch);
break;
} else {
RPN2.push_back(queryPriority[operatorStack.top()]);
operatorStack.pop();
}
}
}
}
RPN2.push_back(atoiNumber);
while (operatorStack.empty() == false) { //弹出栈内操作符
RPN2.push_back(queryPriority[operatorStack.top()]);
operatorStack.pop();
}
return RPN2;
}
int calcRPN(vector<int> inputRPN) {
stack<int> numberStack;
for (auto& it : inputRPN) {
if (it > INT32_MIN + 4) { //操作数
numberStack.push(it);
} else {
int num1 = numberStack.top();
numberStack.pop();
int num2 = numberStack.top();
numberStack.pop();
numberStack.push(doMarsCalc(num2, num1, it));
}
}
return numberStack.top();
}
int doMarsCalc(int num1, int num2, int operate) {
switch (operate) {
case INT32_MIN + 1: //'@':
return (num1 - 1) * (num2 + 1);
case INT32_MIN + 2: //'#':
return (2 * num1 + 5) * (3 * num2 + 60);
case INT32_MIN + 3: //'$':
return (num1 + 1) * (2 * num1 + 3) * (num2 - 1) * (2 * num2 - 3);
case INT32_MIN + 4: //'&':
return ((num1 + num2 + 1) * (num2 - 9) + (num1 + 7) / (num2 - 8));
}
}
};
int main() {
MarsCalc marsCalc;
string inputStr;
while (getline(cin, inputStr)) {
cout << marsCalc.calcResult(inputStr) << endl;
}
return 0;
}