2009-12-19 68 views
6

我正在尋找一個C++類,我可以將其納入我正在開發的一個項目中。 我需要的功能是將字符串操作評估爲數字形式:例如「2 + 3 * 7」應評估爲23.C++簡單操作(+, - ,/,*)評估類

我確實意識到我所要求的是一種解釋器,根據我在CS的背景,構建它們的工具非常差,所以如果你能指點我一個現成的課程,我將不勝感激。

+0

即使在Stroustrup的書中也有一個 –

+0

您想要搜索Dijkstra的調車場算法 –

+0

如果您想在編譯時評估字符串:http://www.boost.org/doc/libs/develop/doc/ html/metaparse/getting_started_with_boost_metap.html –

回答

5

這應該做你想要的。您可以在現場測試:http://www.wowpanda.net/calc

它採用Reverse Polish Notation和支持:

  • 運算符優先級(5 + 5 * 5 = 30不是50)
  • 的括號((5 + 5)* 5 = 50)
  • 以下運算符:+, - ,*,/

編輯:你可能會想要刪除的ABS()在底部;爲我的需要0 - 5應該是5而不是-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。我怎麼做<3你。 – GrayWizardx

+2

也許我很傻,但爲什麼「5 + 5 * 5 = 15不是20」? – GManNickG

+0

因爲我在基礎數學上失敗(計算器工作正常,但我顯然沒有)..編輯我的文章 –

0

C++在行動,除了是一個偉大的書上C++,包括完全工作的計算器,做你所需要的(實際上更多)。而這本書是免費提供的在線