2009-12-19 10 views
6

Estoy buscando una clase de C++ que pueda incorporar a un proyecto en el que estoy trabajando. la funcionalidad que necesito es la evaluación de las operaciones de cadena a forma numérica: por ejemplo "2 + 3 * 7" debería evaluar a 23.C++ operaciones simples (+, -, /, *) clase de evaluación

Me doy cuenta de que lo que estoy pidiendo es una especie de intérprete, y que hay herramientas para construirlos, por mi experiencia en CS es muy pobre, por lo que agradecería que me indicasen una clase preparada.

+0

Incluso en el libro de Stroustrup hay uno –

+0

Desea buscar el algoritmo de yarda de derivación de Dijkstra –

+0

Si desea evaluar la cadena en tiempo de compilación: http://www.boost.org/doc/libs/develop/doc/ html/metaparse/getting_started_with_boost_metap.html –

Respuesta

5

Esto debería hacer exactamente lo que quiere. Puede probar en directo en: http://www.wowpanda.net/calc

Utiliza Reverse Polish Notation y soportes:

  • La precedencia de operadores (5 + 5 * 5 = 30 no 50)
  • Parens ((5 + 5) * 5 = 50)
  • los siguientes operadores: +, -, *,/

EDITAR: es probable que desee para eliminar los ABS() en la parte inferior; para mis necesidades 0 - 5 debería ser 5 y no -5!

static bool Rpn(const string expression, vector<string> &output) 
{ 
    output.clear(); 
    char *end; 
    vector<string> operator_stack; 
    bool expecting_operator = false; 

    for (const char *ptr = expression.c_str(); *ptr; ++ptr) { 
     if (IsSpace(*ptr)) 
      continue; 

     /* Is it a number? */ 
     if (!expecting_operator) { 
      double number = strtod(ptr, &end); 
      if (end != ptr) { 
       /* Okay, it's a number */ 
       output.push_back(boost::lexical_cast<string>(number)); 
       ptr = end - 1; 
       expecting_operator = true; 
       continue; 
      } 
     } 

     if (*ptr == '(') { 
      operator_stack.push_back("("); 
      expecting_operator = false; 
      continue; 
     } 

     if (*ptr == ')') { 
      while (operator_stack.size() && operator_stack.back() != "(") { 
       output.push_back(operator_stack.back()); 
       operator_stack.pop_back(); 
      } 

      if (!operator_stack.size()) 
       return false; /* Mismatched parenthesis */ 

      expecting_operator = true; 
      operator_stack.pop_back(); /* Pop '(' */ 
      continue; 
     } 

     if (*ptr == '+' || *ptr == '-') { 
      while (operator_stack.size() && IsMathOperator(operator_stack.back())) { 
       output.push_back(operator_stack.back()); 
       operator_stack.pop_back(); 
      } 

      operator_stack.push_back(boost::lexical_cast<string>(*ptr)); 
      expecting_operator = false; 
      continue; 
     } 

     if (*ptr == '*' || *ptr == '/') { 
      while (operator_stack.size() && (operator_stack.back() == "*" || operator_stack.back() == "/")) { 
       output.push_back(operator_stack.back()); 
       operator_stack.pop_back(); 
      } 

      operator_stack.push_back(boost::lexical_cast<string>(*ptr)); 
      expecting_operator = false; 
      continue; 
     } 

     /* Error */ 
     return false; 
    } 

    while (operator_stack.size()) { 
     if (!IsMathOperator(operator_stack.back())) 
      return false; 

     output.push_back(operator_stack.back()); 
     operator_stack.pop_back(); 
    } 

    return true; 
} // Rpn 

/***************************************************************************************/ 

bool Calc(const string expression, double &output) 
{ 
    vector<string> rpn; 

    if (!Rpn(expression, rpn)) 
     return false; 

    vector<double> tmp; 
    for (size_t i = 0; i < rpn.size(); ++i) { 
     if (IsMathOperator(rpn[i])) { 
      if (tmp.size() < 2) 
       return false; 
      double two = tmp.back(); 
      tmp.pop_back(); 
      double one = tmp.back(); 
      tmp.pop_back(); 
      double result; 

      switch (rpn[i][0]) { 
       case '*': 
        result = one * two; 
        break; 

       case '/': 
        result = one/two; 
        break; 

       case '+': 
        result = one + two; 
        break; 

       case '-': 
        result = one - two; 
        break; 

       default: 
        return false; 
      } 

      tmp.push_back(result); 
      continue; 
     } 

     tmp.push_back(atof(rpn[i].c_str())); 
     continue; 
    } 

    if (tmp.size() != 1) 
     return false; 

    output = Abs(tmp.back()); 
    return true; 
} // Calc 

/***************************************************************************************/ 
+0

Ahh rpn. Cómo lo hago <3 thee. – GrayWizardx

+2

Tal vez estoy siendo tonto, pero ¿por qué es "5 + 5 * 5 = 15 not 20"? – GManNickG

+0

Porque fallo en matemáticas básicas (aunque la calculadora funciona bien, al parecer no). Edité mi publicación –

0

C++ en acción, además de ser un gran libro sobre C++, incluye una calculadora totalmente funcional, haciendo lo que necesita (y de hecho mucho más). Y el libro está disponible de forma gratuita en línea

Cuestiones relacionadas