2009-12-19 4 views
6

Je suis à la recherche d'une classe C++ que je peux intégrer dans un projet sur lequel je travaille. la fonctionnalité dont j'ai besoin est l'évaluation des opérations de chaîne à la forme numérique: par exemple "2 + 3 * 7" devrait évaluer à 23.C++ opérations simples (+, -, /, *) classe d'évaluation

Je réalise que ce que je demande est une sorte d'interprète, et qu'il y a les outils pour les construire, par mes antécédents en CS est très pauvre donc j'apprécierais si vous pouvez me diriger vers un cours prêt à l'emploi.

+0

Même dans le livre de Stroustrup, il y en a un –

+0

Vous voulez rechercher l'algorithme de Dijkstra Shunting Yard –

+0

Si vous voulez évaluer la chaîne à la compilation: http://www.boost.org/doc/libs/develop/doc/ html/metaparse/getting_started_with_boost_metap.html –

Répondre

5

Cela devrait faire exactement ce que vous voulez. Vous pouvez le tester en direct à: http://www.wowpanda.net/calc

Il utilise Reverse Polish Notation et soutient:

  • priorité de l'opérateur (5 + 5 * 5 = 30 pas 50)
  • parens ((5 + 5) * 5 = 50)
  • les opérateurs suivants: +, -, *,/

EDIT: vous voudrez probablement retirer les Abs() en bas; pour mes besoins 0 - 5 devrait être 5 et non -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. Comme je te fais. – GrayWizardx

+2

Peut-être que je suis bête, mais pourquoi "5 + 5 * 5 = 15 pas 20"? – GManNickG

+0

Parce que j'échoue aux mathématiques de base (la calculatrice fonctionne bien, je ne semble pas) .. Edité mon poste –

0

C++ en action, en plus d'être un grand livre sur C++, comprend une calculatrice entièrement travail, faire ce que vous avez besoin (et en réalité beaucoup plus). Et le livre est disponible gratuitement en ligne

1

muParser est écrit en C++ et fait exactement ce dont vous avez besoin.

Questions connexes