Avaliando expressões aritméticas da string em C ++

Estou procurando uma maneira simples de avaliar uma expressão matemática simples de uma string, como esta:

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

Eu só quero + e * operações mais ( e ) sinais. E * tem mais prioridade que + .

   

Eu acho que você está procurando por um analisador de descida recursivo simples.

Aqui está um exemplo muito simples:

 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; } 

Pode-se tentar: http://partow.net/programming/exprtk/index.html

  1. muito simples
  2. só precisa include “exprtk.hpp” no seu código-fonte.
  3. você pode alterar o valor das variables ​​da expressão dinamicamente.
  4. bom ponto de partida: http://partow.net/programming/exprtk/code/exprtk_simple_example_01.cpp

Apenas para adicionar outra alternativa, considere tentar o TinyExpr para este problema. É open source e auto-contido em um arquivo de código-fonte. Na verdade, é escrito em C, mas será compilado como C ++ na minha experiência.

Resolver sua expressão de exemplo acima é tão simples quanto:

 #include "tinyexpr.h" #include  int main() { double answer = te_interp("3*2+4*1+(4+9)*6", 0); printf("Answer is %f\n", answer); return 0; } 

Enquanto pesquisava uma biblioteca para uma tarefa semelhante, encontrei a libmatheval . Parece ser uma coisa boa. Infelizmente, a GPL, que é inaceitável para mim.

 import java.util.Deque; import java.util.LinkedList; public class EvaluateArithmeticExpression { public static void main(String[] args) { System.out.println(evaluate("-4*2/2^3+3")==-4*2/Math.pow(2, 3)+3); System.out.println(evaluate("12*1314/(1*4)+300")==12*1314/(1*4)+300); System.out.println(evaluate("123-(14*4)/4+300")==123-(14*4)/4+300); System.out.println(evaluate("12*4+300")==12*4+300); } public static int evaluate(String s){ Deque vStack= new LinkedList<>(); Deque opStack= new LinkedList<>(); int i=0; while(i vStack,int i){ int sign=1; if(s.charAt(i)=='-' || s.charAt(i)=='+') sign=s.charAt(i++)=='-'?-1:1; int val=0; while(i opStack,Deque vStack,int i){ char op=s.charAt(i); if(op=='(') opStack.push(op); else{ if(op==')'){ while(!opStack.isEmpty() && opStack.peekFirst()!='(') doOp(opStack,vStack); opStack.pop(); } else{ while(!opStack.isEmpty() && prior(op)< =prior(opStack.peekFirst())) doOp(opStack,vStack); opStack.push(op); } } return i+1; } private static int prior(char op){ switch(op){ case '+': case '-': return 1; case '*': case '/': return 2; case '^': return 4; } return 0; } private static void doOp(Deque opStack,Deque vStack){ int b=vStack.isEmpty()?0:vStack.pop(); int a=vStack.isEmpty()?0:vStack.pop(); char op=opStack.pop(); int res=evaluate(a,b,op); vStack.push(res); } private static int evaluate(int a, int b, char op){ switch(op){ case '+': return a+b; case '-': return ab; case '/': return a/b; case '*': return a*b; case '^': return (int)Math.pow(a,b); } return 0; } private static boolean isNum(String s, int i){ return '0'< =s.charAt(i) && s.charAt(i)<='9'; } private static boolean isOp(String s, int i){ return "()+-*/^".contains(String.valueOf(s.charAt(i))); } } 

Eu escrevi um avaliador de expressão muito simples em C # (alterações mínimas necessárias para torná-lo compatível com C ++). Ele é baseado no método de construção de tree de expressão, apenas que a tree não é realmente construída, mas todos os nós são avaliados no local.

Você pode encontrá-lo neste endereço: Simple Arithmetic Expression Evaluator

Então eu estava procurando uma resposta para essa pergunta. E eu estava tentando criar minha própria linguagem de programação. Para expressões matemáticas, eu precisava dessa function.

Oke dar eu vou dar a você. Use do jeito que você quiser.

 /* Code here before is useless now */ 

Essa é uma maneira longa e provavelmente ineficiente de realizar tal tarefa. Mas fica trabalho feito, então vá em frente. Logo estou planejando adicionar suporte variável. Mas você pode fazer isso também, é bem fácil (suponho: P).

EDIT: eu apenas arrumei a function agora funciona como mágica 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... } 

Eu acho que você pode encontrar a resposta neste post: Avaliando string “3 * (4 + 2)” yield int 18

Ou você pode tentar essa biblioteca: http://weblogs.asp.net/pwelter34/archive/2007/05/05/calculator-net-calculator-that-evaluates-math-expressions.aspx

Aqui está uma pequena apresentação em trees de avaliação para expressões matemáticas complexas (não realmente: p):

http://courses.cs.vt.edu/~cs1044/spring01/cstruble/notes/6.complexexpr.pdf

Ele vai guiá-lo em grande estilo;)