2015-12-16 14 views
0

我試圖用包含在隊列中的運算符和操作數來構建數學表達式(包括括號)。如何從運算符和隊列中的操作數創建數學表達式

這裏是我的代碼:

string createExp (queue<char> q) { 
    string s; 
    string s1, s2; 
    char c; 

    while (!q.empty()) { 

     c = q.front(); 

     if (c == 'x') { 
      s += "x"; 
      q.pop(); 
     } 

     else if (c == 'y') { 
      s += "y"; 
      q.pop(); 
     } 

     else if (c == 'a') { 
      s += "avg("; 
      q.pop(); 

      s1 = createExp(q); 
      q.pop(); 
      s2 = createExp(q); 
      q.pop(); 
      s += s1; 
      s += ','; 
      s += s2; 
      s += ')'; 
     } 

     else if (c == 's') { 
      s += "sin(pi*"; 
      q.pop(); 
      op++; 
     } 
     else if (c == 'c') { 
      s += "cos(pi*"; 
      q.pop(); 
      op++; 
     } 
     else { 
      s += "*"; 
      q.pop(); 
     } 
    } 

    while (op > cp) { 
     s += ")"; 
     cp++; 
    } 

    return (s); 
} 

正如你所看到的,在平均(AVG)的情況下,我想遞歸調用該函數獲取值的下一序列。

例如,如果我的隊列包含下一個值:

smayxy

表達應該是這樣的:

SIN(PI *(AVG(Y, x)* y)

但我的代碼返回這個序列:

罪(PI ** AVG(YYX)yyxyyx

你能幫我嗎?

非常感謝。

+0

您是否嘗試過調試一步一步? – sop

+0

或者至少使用更短/更簡單的輸入? –

+0

你的'op'和'cp'定義在哪裏?他們是全球嗎? – sop

回答

0

這是我最後的遞歸解決方案:

int cp = 0, op = 0; 

string recursiveExp (queue<char>& q) { 
    char e; 

    if (!q.empty()) { 
     e = q.front(); 
     if (e == 'x' || e == 'y') { 
      q.pop(); 
      s += e; 
     } 

     else if (e == 's') { 
      q.pop(); 
      s += "sin(pi*"; 
      op++; 
      recursiveExp(q); 
      s += ")"; 
      cp++; 
     } 

     else if (e == 'c') { 
      q.pop(); 
      s += "cos(pi*"; 
      op++; 
      recursiveExp(q); 
      s += ")"; 
      cp++; 
     } 

     else if (e == 'a') { 
      q.pop(); 
      s += "avg("; 
      op++; 
      recursiveExp(q); 
      s += ","; 
      recursiveExp(q); 
      s += ")"; 
      cp++; 
     } 

     else if (e == 'm'){ 
      q.pop(); 
      s += "("; 
      op++; 
      recursiveExp(q); 
      s += "*"; 
      recursiveExp(q); 
      s += ")"; 
      cp++; 
     } 
    } 
    return s; 
} 

感謝大家:)

1

**來自m這兩個字符串,並且您在代碼中明確寫入sin(pi*

此外,遞歸到平均值(創建s1似乎索引整個表達式,所以你得到yyx)。你必須確保它只能從堆棧中讀出1個完整的表達式,而不是剩下的東西。這很棘手,因爲您需要分辨avg(x,y)avg(x+y,y*x)之間的差異。

+0

它來自'm'立即將'*'放入輸出字符串,而不是解析兩個操作數並將'*'放在它們之間。 –

+0

@BenVoigt是的,我沒有寫同樣的東西? – gt6989b

3

處理avg(-,-)的這部分是可怕的破壞:

s1 = createExp(q); 
q.pop(); 
s2 = createExp(q); 
q.pop(); 

你路過值的隊列,這將創建一個副本。然後你不能發現遞歸有多少次彈出隊列。但你奇蹟般地認爲你應該刪除一個元素。如果其中一個參數有一個函數調用或運算符,會怎樣?

更糟糕的是,遞歸會處理整個隊列的其餘部分,而不僅僅是一個表達式。

+0

那麼,在你看來,哪個解決這個問題最好?也許在所有的函數中使用遞歸? –

+0

是的,遞歸,沒有循環,我會通過引用傳遞隊列,以便遞歸調用控制有多少操作數被刪除。 –

+0

這個功能怎麼樣? –

0

我做你的代碼的小修改,它完美的作品:

int cp = 0, op = 0; 

std::string createExp(std::queue<char>& q) 
{ 
    std::string s; 
    std::string s1, s2; 
    char c; 

    while (!q.empty()) 
    { 
     c = q.front(); 

     if (c == 'x') 
     { 
      s += "x"; 
      q.pop(); 
     } 
     else if (c == 'y') 
     { 
      s += "y"; 
      q.pop(); 
     } 
     else if (c == 'a') 
     { 
      s += "avg("; 
      q.pop(); 

      s1 = q.front(); // here 
      q.pop(); 
      s2 = q.front(); // and here 
      q.pop(); 
      s += s1; 
      s += ','; 
      s += s2; 
      s += ')*'; 
     } 
     else if (c == 's') 
     { 
      s += "sin(pi*"; 
      q.pop(); 
      op++; 
     } 
     else if (c == 'c') 
     { 
      s += "cos(pi*"; 
      q.pop(); 
      op++; 
     } 
     else 
     { 
//    s += "*"; 
      q.pop(); 
     } 
    } 

    while (op > cp) 
    { 
     s += ")"; 
     cp++; 
    } 

    return (s); 
} 

但是如果你的運營商始終是*這隻會工作。如果你還需要其他運營商,那麼你需要一個更復雜的東西。