我为LeetCode OJ问题编写了以下代码Evaluate Reverse Polish Notation
<pre>
</pre>
代码无疑是正确的。但是,我觉得代码的某些部分并不干净。实际上,我想写这样的代码:
int evalRPN(vector<string>& tokens)
{
int n = tokens.size();
if (n == 0)
return 0;
stack<int> S;
int a, b;
for (int i = 0; i < n; i++)
{
string tmp = tokens[i];
if (tmp == "+")
{
a = S.top(); S.pop();
b = S.top(); S.pop();
S.push(b + a);
}
else if (tmp == "-")
{
a = S.top(); S.pop();
b = S.top(); S.pop();
S.push(b - a);
}
else if (tmp == "*")
{
a = S.top(); S.pop();
b = S.top(); S.pop();
S.push(b * a);
}
else if (tmp == "/")
{
a = S.top(); S.pop();
b = S.top(); S.pop();
S.push(b / a);
}
else
{
S.push(stoi(tmp));
}
}
return S.top();
}
int evalRPN(vector<string>& tokens)
{
int n = tokens.size();
if (n == 0)
return 0;
stack<int> S;
int a, b;
for (int i = 0; i < n; i++)
{
string tmp = tokens[i];
if (tmp is any of "+", "-", "*", "/") // <== [1]
{
a = S.top(); S.pop();
b = S.top(); S.pop();
S.push(compute(a, b, tmp)); // <== [2]
}
else
{
S.push(stoi(tmp));
}
}
return S.top();
}
,我不想写[1]
,我想要更清晰的代码来检查tmp == "+" || tmp == "-" || tmp == "*" || tmp == "/"
是否是四个运营商中的任何一个; tmp
中,函数[2]
将输出操作数compute(int a, int b, string& tmp)
,a
和运算符b
的结果。但我仍然不想使用任何tmp
(if - else
可能会被接受,但我不知道如何在switch
使用。如果存在,则欢迎使用Lambda函数或任何可能的运算符函数。有没有办法做到这一点?
答案 0 :(得分:2)
这适用于C ++ 11或更高版本。 (如果使用带有-std=c++11
标志的g ++编译)。
#include <map>
#include <functional>
// ...
int evalRPN(vector<string>& tokens)
{
// map of string -> lambda
std::map<std::string, std::function<int(int,int)>> ops;
// fill the map
ops["+"] = [](int a,int b) { return b+a; };
ops["-"] = [](int a,int b) { return b-a; };
ops["*"] = [](int a,int b) { return b*a; };
ops["/"] = [](int a,int b) { return b/a; };
int n = tokens.size();
if (n == 0)
return 0;
stack<int> S;
int a, b;
for (int i = 0; i < n; i++)
{
string tmp = tokens[i];
// find the operator in map
auto opit = ops.find(tmp);
if ( opit != ops.end() ) {
// if token is in map (ie. if it is operator)
a = S.top(); S.pop();
b = S.top(); S.pop();
// get the function
auto fn = opit->second;
// and push it's result to stack
S.push( fn(a,b) );
} else {
// if not operator push to stack
S.push(stoi(tmp));
}
}
return S.top();
}
答案 1 :(得分:1)
至少,我可以为您解决问题的第一部分,即if语句。我认为以下方法可行:
std::string operators = "+-*/";
std::string tmp = tokens[i];
if(operators.find(tmp) != std::string::npos)
{
a = S.top(); S.pop();
b = S.top(); S.pop();
S.push(compute(a, b, tmp)); // <== [2]
}
else
{
S.push(stoi(tmp));
}
我在这里做的很简单:我有一个包含所有运算符的字符串,我只是在该字符串中搜索tmp
。如果它在该字符串中的位置不是npos
,则tmp必须是运算符。
对于第二部分,我有两个想法:
它仍然有点笨拙,但你写了一个switch
声明是可以接受的,那么怎么样:
int compute(int a, int b, std::string op)
{
switch (op[0]) {
case '+':
return b+a;
case '-':
return b-a;
case '*':
return b*a;
case '/':
return b/a;
}
}
另一个想法:最初,我认为你可以使用operator+
和co来避免为已经实现过的东西编写你的胜利函数,但事实证明这是不可能的。但是,您可以使用其他功能:
int compute(int a, int b, std::string op)
{
static std::map<std::string,std::function<int(int,int)> > operations;
operations["+"] = std::plus<int>();
operations["-"] = std::minus<int>();
operations["*"] = std::multiplies<int>();
operations["/"] = std::divides<int>();
return operations[op](b,a);
}
查看http://ideone.com/wSl5zQ以获取完整实现,该实现读取一行RPN表单stdin并计算结果。