2012-10-12 98 views
3

我需要一個帶中綴字符串(如「3 + 4 * 9」)並將其轉換爲後綴(如「4 9 * 3 +」)的函數。C++中的分流碼算法

我得到它的工作,直到你把括號內的括號。我一整天都在努力研究,無法弄清楚自己在做什麼錯了 - 有人可以用清新的頭腦看到它,也許?我覺得我真的很接近!

謝謝!下面的代碼:

string ExpressionManager::infixToPostfix(string infixExpression) 
    { 
cout << "itop Testing : " << infixExpression << endl; 
string posnums = ""; 
string posops = "+-*/%(){}[]"; 
string onlyops = "+-/%*"; 
string space = " "; 
string openbra = "([{"; 
string closebra = ")]}"; 
stack <string> nums; 
stack <string> ops; 
string output = ""; 

//check to make sure expression is valid 

if (!(isBalanced(infixExpression))) 
{ 
    cout << "Infix Expression isn't balanced!" << endl; 
    return "invalid"; 
} 


for (int i=0; i<infixExpression.size(); i++) 
{ 
    if ((posnums.find(infixExpression[i])!=string::npos) || (posops.find(infixExpression[i])!=string::npos) || (space.find(infixExpression[i])!=string::npos)) 
    {} 

    else 
    { 
     cout << "Invalid character " << infixExpression[i] << " found." << endl; 
     return "invalid"; 
    } 
} 


int numcount = 0; 
int opcount = 0; 
//Numbers vs. Operators 
for (int i = 0; i < infixExpression.size(); i++) 
{ 
    if (posnums.find(infixExpression[i]) != -1) 
    { 

     while(infixExpression[i] != ' ') 
     { 
      if (i == (infixExpression.size()-1)) 
       break; 
      i++; 
     } 
     numcount++; 
    } 

    if (onlyops.find(infixExpression[i]) != -1) 
    { 
     opcount++; 
    } 
} 


if (opcount == (numcount - 1)) 
{ 
} 
else 
{ 
    cout << "Bad operators to numbers ratio!" << endl; 
    return "invalid"; 
} 

//Get rid of proceeding whitespaces. 
int safety = 0; 
int net = infixExpression.size(); 

while (infixExpression[0] == ' ') 
{ 
    infixExpression.erase(0,1); 
    safety++; 

    if (safety>=net) 
     break; 
} 

//cout << "At this point, it is " << postfixExpression << endl; 

//the fun part! Set up stacks 

for (int i =0; i< infixExpression.size(); i++) 
{ 
    cout << "It gets hung up on character " << infixExpression[i] << endl; 
    if(openbra.find(infixExpression[i]) != -1) 
    { 

     string word = ""; 
     word += infixExpression[i]; 
     ops.push(word); 

     cout << "Pushing onto stack: " << word << endl; 
    } 
    else if(closebra.find(infixExpression[i]) != -1) 
    { 
      cout << "contents of remaining ops stack: "<< endl; 
      stack <string> temp; 
      temp = ops; 
       for (int j = 0; j < temp.size(); j++) 
       { 
        cout << "\t" << temp.top() << endl; 
        temp.pop(); 
       } 

     while (openbra.find(ops.top()) == -1) 
     { 


      output += " " + ops.top(); 
      cout << "Pushing from stack: " << ops.top() << endl; 
      ops.pop(); 
     } 

     cout << "Pushing from stack: " << ops.top() << endl; 
     ops.pop(); 

    } 

    else if (posnums.find(infixExpression[i]) != -1) 
    { 

     string word = ""; 
     while (infixExpression[i] != ' ') 
     { 
      word += infixExpression[i]; 
      i++; 
      if (i== infixExpression.size()) 
       break; 
     } 
     output += " " + word; 

    } 

    else if (onlyops.find(infixExpression[i]) != -1) 
    { 

     if (ops.size() == 0) 
     { 
      string word = ""; 
     word += infixExpression[i]; 
     ops.push(word); 
     } 
     else 
     { 
     int o1p = 0; 
     int o2p = 0; 

     if ((infixExpression[i] == '+') || (infixExpression[i] == '-')) 
      o1p = 0; 
     else 
      o1p = 1; 

     if ((ops.top() == "+") || (ops.top() == "-")) 
      o2p = 0; 
     else 
      o2p = 1; 

     while ((ops.size() > 0) && (o1p <= o2p)) 
     { 
      output += " " + ops.top(); 
      cout << "(odd) Pushing from stack: " << ops.top() << endl; 

     if ((ops.top() == "+") || (ops.top() == "-")) 
      o2p = 0; 
     else 
      o2p = 1; 

     if (ops.size() > 0) 
     { 
      ops.pop(); 
     } 
     else 
     { 
      break; 
     } 
     } 

     string word = ""; 
     word += infixExpression[i]; 
     ops.push(word); 
     } 
    } 

} 

while (output[0] == ' ') 
{ 
    output.erase(0,1); 
} 

return output; 
    } 
+0

如果只是它開始遞歸下降,不分流.. :) – 2012-10-12 01:35:03

+0

哇。 shift-reduce-parser flashback。我以爲我在很多個月前的大學裏留下這樣的問題。 – WhozCraig

+1

正確的輸出應該是「3 4 9 * +」。當您稍後解析它時,您將遍歷所有元素,直到找到第一個運算符。然後用該操作的結果替換該運算符和前面的兩個操作數,然後查找下一個運算符。 – Atle

回答

0

我個人認爲你必須學習有關調度場算法

困難,因爲你說的輸出是像「4 9 * 3 +」,但我看了一下算法和堆棧操作,它應該是(像「9 4 * 3 +」)

重要的問題是,在對數字和運算符進行分類之後,從運算符堆棧中彈出所有,並將其推入數字堆棧尊重操作員彈出的設定條件

0

我的建議是,你直接去描述

  1. Shunting Yard Algorithm
  2. Reverse Polish Notation

我已經在Java和C實現的調度場算法相關的維基網頁++,發現Wiki頁面優秀並且是一個很好的幫助。它們的詳細程度足以使您能夠按照您喜歡的任何編程語言逐步實現算法。

另一個建議:熟悉堆棧和隊列的實際使用,因爲它們在這些算法的所有位置都被使用。

對於上述Shunting Yard算法的一些C++和Java實現,請參閱此blog posting

如果您希望包含其他數學運算符(sin,cos,log等)和更復雜的表達式和子表達式,它還包含其他部分(進行中)。

0

Here是(最後一個版本)解決方案。在某些步驟中,它使用Dijkstra的分流碼算法(在traverse()成員函數output_的末尾包含input_表達式的逆波蘭表示形式,如果我們以正確方式遍歷它)結束。