標籤:思路 com break ges nal png idt 訪問 img
陸陸續續更新這個計算機用了一個禮拜了,今天無論如何也要把它更完。筆者有點追求完美,再者每天都有課,晚上還有作業,還有每晚都會寫一些其他的博文。
上一次漏了寫如何?計算的。思路如下:
之前得到一個棧2stack2,裡面存的是逆波蘭式。但是注意了,式子是反過來的。因為棧只能從棧頂寫入,從棧頂拿出。所以,必須把棧2的數反過來。
下面是轉換的代碼:
// //將棧2數值倒過來 // private void UpSideDown() { string[] strTemp = stack2.ToArray(); //將棧stack2數值臨時儲存在數組裡 stack2.Clear(); //將棧stack2清空 for(int i=strTemp.Length-1;i>=0;i--) { stack2.Push(strTemp[i]); } }
將棧的數值倒過來之後,我們就可以進行計算了,計算的思路如下:按步驟
1:從棧頂取元素,如果是數字直接存入新棧 2:如果是操作符,則不存入,將新棧的前兩個元素依次取出,先取出的數字放在運算子右邊,後取出的放在左邊 3:計算的結果放回新棧。重複以上步驟,知道計算完。
注意!新棧儲存的數字,所以要注意棧的類型。
// //計算四則運算 // public double DoMath() { var stackTemp = new Stack<double>(); try { while (myStack2.Count != 0) { if (!IfNumber(myStack2.Peek())) { double d1 = stackTemp.Pop(); double d2 = stackTemp.Pop(); switch (myStack2.Pop()) { case "+": stackTemp.Push(d2 + d1); break; case "-": stackTemp.Push(d2 - d1); break; case "*": stackTemp.Push(d2 * d1); break; case "/": stackTemp.Push(d2 / d1); break; }//end switch }//end if else { stackTemp.Push(Convert.ToDouble(myStack2.Pop())); } }//end while return stackTemp.Pop(); } catch { return 0; } }
四則混合運算的大體步驟和解決思路就這麼多,現在開始解決如何確保使用者在亂輸入公式以及得到的公式該怎麼解析(前面提到的問題:就是當接受了加括弧的一元運算子比如:1+(-2)。轉換得到的式子是不能正確計算的。)
思路一:怎麼解決使用者亂輸入數字
用棧儲存使用者每次按的按鍵內容,除了第一次輸入外,在每次輸入的時候與棧頂元素進行比較。如果連續兩次輸入操作符,則視第二次有效:
private string str = ""; //聲明切定義一個Null 字元串,用於在label顯示使用者輸入 Stack<string> tempStack = new Stack<string>(); //聲明一個數組,用去儲存使用者輸入 //判斷使用者點擊是否有效 public void IfValid(string s) { if (tempStack != null) { if (Calculate.IfNumber(s)) //如果使用者按得是數字,則輸入有效 { tempStack.Push(s); } else { if (!Calculate.IfNumber(tempStack.Peek())) //如果使用者連續兩次按的是操作符,則視第二次有效 { tempStack.Pop(); tempStack.Push(s); } else tempStack.Push(s); } }//end if else { tempStack.Push(s); } str = ""; string[] tempStr = tempStack.ToArray(); //將得到的數組反轉 for (int i = 0; i < tempStr.Length / 2; i++) { string temp = tempStr[i]; tempStr[i] = tempStr[tempStr.Length - i - 1]; tempStr[tempStr.Length - i - 1] = temp; } foreach (var item in tempStr) str += item; label1.Text = str; } private void button1_Click(object sender, EventArgs e) { IfValid(button1.Text); } private void button2_Click(object sender, EventArgs e) { IfValid(button2.Text); }
筆者有很多地方都用到將數組元素前後倒過來的代碼,但卻沒有將其寫成獨立函數,造成代碼的冗餘。
這裡代碼是寫在Form1裡的,用到了ReversePolish的IsNumber的方法,因為是不同類的,而且沒有ReversePolish就直接調用,所以要把之前定義的修飾private 改成public static修飾才能直接調用。
思路二:當接受了加括弧的一元運算子比如:1+(-2)。通過逆波蘭法則轉換得到的式子是不能正確計算的。
把式子進行解析,寫成:1+(0-2)的形式!
代碼如下:
string[] strAnalysis; //存放解析完原始計算公式之後的公式 string[] str; //string數組str用於存放原始計算公式// //解析原始計算公式 // public void Analysis() { var stackTemp = new Stack<string>(); int count = 0; try { while (count < strAnalysis.Length) { if (strAnalysis[count] == "(" && (strAnalysis[count + 1] == "-" || strAnalysis[count + 1] == "+")) //如果公式運算元(的後一位運算元是+或則-, { stackTemp.Push(strAnalysis[count]); stackTemp.Push("0"); count++; } else if (!IfNumber(strAnalysis[count])) { stackTemp.Push(strAnalysis[count]); count++; } else if (IfNumber(strAnalysis[count])) { string strTemp = ""; while (count < strAnalysis.Length && IfNumber(strAnalysis[count])) //如果是數字,包括小數點.,則拼成一個字串,直到遇到一個操作符或則數組遍曆完畢 { strTemp += strAnalysis[count]; count++; } stackTemp.Push(strTemp); } } } catch { stackTemp = null; } str = stackTemp.ToArray(); //反轉字串數組 for (int i = 0; i < str.Length / 2; i++) { string temp = str[i]; str[i] = str[str.Length - i - 1]; str[str.Length - i - 1] = temp; } }
大體思路思路就這麼多了,總之是問題逐一突破,把解決的問題方案寫成方法,最後湊在一起就成功了。以上的代碼並不是所有的代碼,筆者只是想把自己的思路分享一下。因為我猜如果我把所有代碼都貼出來是要花很長時間看的。畢竟每個人的思維不一樣。本人就不擅長讀別人的代碼T T。
提示:一般遇到訪問記憶體,比如取棧壓棧訪問棧頂的代碼,最好上異常處理,因為很容易就出現錯誤。
歡迎大家提出質疑!
Windows Form簡易計算機實現(下)