我正在寻找一种从字符串中评估简单数学表达式的简单方法,如下所示:
3 * 2 + 4 * 1 +(4 + 9)* 6
我只想要+
和*
操作以及(
和)
符号。 *
的优先级高于+
。
答案 0 :(得分:30)
可以尝试:http://partow.net/programming/exprtk/index.html
答案 1 :(得分:28)
我认为你正在寻找一个简单的recursive descent parser。
这是一个非常简单的例子:
const char * expressionToParse = "3*2+4*1+(4+9)*6";
char peek()
{
return *expressionToParse;
}
char get()
{
return *expressionToParse++;
}
int expression();
int number()
{
int result = get() - '0';
while (peek() >= '0' && peek() <= '9')
{
result = 10*result + get() - '0';
}
return result;
}
int factor()
{
if (peek() >= '0' && peek() <= '9')
return number();
else if (peek() == '(')
{
get(); // '('
int result = expression();
get(); // ')'
return result;
}
else if (peek() == '-')
{
get();
return -factor();
}
return 0; // error
}
int term()
{
int result = factor();
while (peek() == '*' || peek() == '/')
if (get() == '*')
result *= factor();
else
result /= factor();
return result;
}
int expression()
{
int result = term();
while (peek() == '+' || peek() == '-')
if (get() == '+')
result += term();
else
result -= term();
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
int result = expression();
return 0;
}
答案 2 :(得分:11)
要添加其他替代方案,请考虑针对此问题尝试TinyExpr。它是一个源代码文件中的开源和自包含。它实际上是用C语言编写的,但根据我的经验,它会像C ++一样干净地编译。
从上面解决您的示例表达式非常简单:
#include "tinyexpr.h"
#include <stdio.h>
int main()
{
double answer = te_interp("3*2+4*1+(4+9)*6", 0);
printf("Answer is %f\n", answer);
return 0;
}
答案 3 :(得分:3)
在图书馆搜索类似任务时,我找到了libmatheval。似乎是一件正确的事。不幸的是,GPL,这对我来说是不可接受的。
答案 4 :(得分:2)
我在C#中编写了一个非常简单的表达式求值程序(使其符合C ++标准所需的最小更改)。它基于表达式树构建方法,只是实际上没有构建树,但所有节点都是就地评估的。
您可以在以下地址找到它:Simple Arithmetic Expression Evaluator
答案 5 :(得分:2)
所以我正在寻找这个问题的答案。我正在尝试创建自己的编程语言。对于数学表达式,我需要这个函数。
哦,我会把它交给你。按照你想要的方式使用它。
/* Code here before is useless now */
这是一种漫长而且可能是执行此类任务的无效方式。但它完成了工作,所以去吧。很快我就计划增加可变支持。但你也可以这样做,这很容易(我想:P)。
编辑:我现在整理了这个功能,现在它像魔术XD一样工作..
using namespace std;
double eval(string expr)
{
string xxx; // Get Rid of Spaces
for (int i = 0; i < expr.length(); i++)
{
if (expr[i] != ' ')
{
xxx += expr[i];
}
}
string tok = ""; // Do parantheses first
for (int i = 0; i < xxx.length(); i++)
{
if (xxx[i] == '(')
{
int iter = 1;
string token;
i++;
while (true)
{
if (xxx[i] == '(')
{
iter++;
} else if (xxx[i] == ')')
{
iter--;
if (iter == 0)
{
i++;
break;
}
}
token += xxx[i];
i++;
}
//cout << "(" << token << ")" << " == " << to_string(eval(token)) << endl;
tok += to_string(eval(token));
}
tok += xxx[i];
}
for (int i = 0; i < tok.length(); i++)
{
if (tok[i] == '+')
{
//cout << tok.substr(0, i) + " + " + tok.substr(i+1, tok.length()-i-1) << " == " << eval(tok.substr(0, i)) + eval(tok.substr(i+1, tok.length()-i-1)) << endl;
return eval(tok.substr(0, i)) + eval(tok.substr(i+1, tok.length()-i-1));
} else if (tok[i] == '-')
{
//cout << tok.substr(0, i) + " - " + tok.substr(i+1, tok.length()-i-1) << " == " << eval(tok.substr(0, i)) - eval(tok.substr(i+1, tok.length()-i-1)) << endl;
return eval(tok.substr(0, i)) - eval(tok.substr(i+1, tok.length()-i-1));
}
}
for (int i = 0; i < tok.length(); i++)
{
if (tok[i] == '*')
{
//cout << tok.substr(0, i) + " * " + tok.substr(i+1, tok.length()-i-1) << " == " << eval(tok.substr(0, i)) * eval(tok.substr(i+1, tok.length()-i-1)) << endl;
return eval(tok.substr(0, i)) * eval(tok.substr(i+1, tok.length()-i-1));
} else if (tok[i] == '/')
{
//cout << tok.substr(0, i) + " / " + tok.substr(i+1, tok.length()-i-1) << " == " << eval(tok.substr(0, i)) / eval(tok.substr(i+1, tok.length()-i-1)) << endl;
return eval(tok.substr(0, i)) / eval(tok.substr(i+1, tok.length()-i-1));
}
}
//cout << stod(tok.c_str()) << endl;
return stod(tok.c_str()); // Return the value...
}
答案 6 :(得分:0)
将您的中缀表达式转换为后缀1。然后评估。
后缀可能看起来像3 2 * 4 1 * + 4 9 + 6 * +
使用堆栈进行评估非常容易。