在C ++中从字符串中计算算术表达式

时间:2012-02-17 13:49:27

标签: c++

我正在寻找一种从字符串中评估简单数学表达式的简单方法,如下所示:

  

3 * 2 + 4 * 1 +(4 + 9)* 6

我只想要+*操作以及()符号。 *的优先级高于+

7 个答案:

答案 0 :(得分:30)

可以尝试:http://partow.net/programming/exprtk/index.html

  1. 非常简单
  2. 只需要包含" exprtk.hpp"到您的源代码。
  3. 您可以动态更改表达式变量的值。
  4. 良好的起点:http://partow.net/programming/exprtk/code/exprtk_simple_example_01.cpp

答案 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 * +

使用堆栈进行评估非常容易。