Оценка арифметических выражений из строки в C ++

c++

62158 просмотра

6 ответа

6023 Репутация автора

Я ищу простой способ вычисления простого математического выражения из строки, например так:

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

Я просто хочу +и *операции плюс (и )знаки. И *имеет больше приоритетов, чем +.

Автор: Mahdi Ghiasi Источник Размещён: 17.02.2012 01:49

Ответы (6)


30 плюса

21620 Репутация автора

Решение

Я думаю, что вы ищете простой парсер рекурсивного спуска .

Вот очень простой пример:

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;
}
Автор: Henrik Размещён: 17.02.2012 01:56

2 плюса

8131 Репутация автора

Я написал очень простой оценщик выражений в C # (минимальные изменения, необходимые для его совместимости с C ++). Он основан на методе построения дерева выражений, только то, что дерево на самом деле не построено, но все узлы оцениваются на месте.

Вы можете найти его по этому адресу: Simple Aрифметические выражения Evaluator

Автор: Zoran Horvat Размещён: 01.06.2013 06:24

3 плюса

1806 Репутация автора

При поиске в библиотеке аналогичной задачи я обнаружил libmatheval . Кажется, это правильная вещь. К сожалению, GPL, что для меня неприемлемо.

Автор: Yury Размещён: 03.12.2013 01:45

31 плюса

832 Репутация автора

Можно попробовать: http://partow.net/programming/exprtk/index.html

  1. очень простой
  2. нужно только включить «exprtk.hpp» в ваш исходный код.
  3. Вы можете изменить значение переменных выражения динамически.
  4. хорошая отправная точка: http://partow.net/programming/exprtk/code/exprtk_simple_example_01.cpp
Автор: Monir Размещён: 12.12.2014 11:45

11 плюса

170 Репутация автора

Просто чтобы добавить другую альтернативу, попробуйте 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;
}
Автор: IsaacH Размещён: 18.05.2016 04:25

2 плюса

21 Репутация автора

Поэтому я искал ответ на этот вопрос. И я пытался создать свой собственный язык программирования. Для математических выражений мне была нужна эта функция.

Ок, дай, я дам тебе. Используйте это так, как вы хотите.

/* 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...
}
Автор: Mustafa Yıldız Размещён: 27.04.2018 10:05
Вопросы из категории :
32x32