用C#實現一個普通計算器——棧和佇列的應用
阿新 • • 發佈:2019-01-28
這是大二上學期課設的一道題,我當時剛好學習了C#,C#窗體應用程式的介面程式碼和業務程式碼是分開的,這比其他同學使用的C++MFC要方便很多,分享給你,希望對你有幫助。閱讀本文並加以實現的話,需要有一定的C#程式設計基礎,當然,程式碼裡面計算中綴表示式的方法還是值得一看的。
在編輯區它是這樣子的:
注意右側的解決方案資源管理器中的檔案,後面會一個一個粘上來~~~
在看看執行時的效果吧:
如果瞭解C#窗體應用程式,實現起來應該是不會有問題的,我下面就開始貼程式碼了,敲黑板~~~我們的重點在棧和佇列的應用
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 計算器的設計與實現CSharp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string input="";
/// <summary>
/// 監聽輸入函式
/// </summary>
/// <param name="c">輸入的字元</param>
void Input(char c)
{
input += c;
}
/// <summary>
/// 顯示函式
/// </summary>
void ShowMessage()
{
txtBox.Text = input;
}
#region 監聽輸入
private void btn1_Click(object sender, EventArgs e)
{
Input('1');
ShowMessage();
}
private void btn2_Click(object sender, EventArgs e)
{
Input('2');
ShowMessage();
}
private void btn3_Click(object sender, EventArgs e)
{
Input('3');
ShowMessage();
}
private void btn4_Click(object sender, EventArgs e)
{
Input('4');
ShowMessage();
}
private void btn5_Click(object sender, EventArgs e)
{
Input('5');
ShowMessage();
}
private void btn6_Click(object sender, EventArgs e)
{
Input('6');
ShowMessage();
}
private void btn7_Click(object sender, EventArgs e)
{
Input('7');
ShowMessage();
}
private void btn8_Click(object sender, EventArgs e)
{
Input('8');
ShowMessage();
}
private void btn9_Click(object sender, EventArgs e)
{
Input('9');
ShowMessage();
}
private void btn0_Click(object sender, EventArgs e)
{
Input('0');
ShowMessage();
}
private void btnAdd_Click(object sender, EventArgs e)
{
Input('+');
ShowMessage();
}
private void btnSubtruct_Click(object sender, EventArgs e)
{
Input('-');
ShowMessage();
}
private void btnRide_Click(object sender, EventArgs e)
{
Input('x');
ShowMessage();
}
private void btnRemove_Click(object sender, EventArgs e)
{
Input('÷');
ShowMessage();
}
private void btnDot_Click(object sender, EventArgs e)
{
Input('.');
ShowMessage();
}
private void btnClear_Click(object sender, EventArgs e)
{
input = "";
txtBox.Text = "";
ShowMessage();
txtBox.ReadOnly = false;
btnEqual.Enabled = true;
}
#endregion
/// <summary>
/// 判斷運算優先順序
/// </summary>
/// <param name="sign"></param>
/// <returns></returns>
private int GetSignYouXianJi(char sign) // get sign priority
{
switch (sign)
{
case '+':
case '-':
return 1;
case 'x':
case '÷':
return 2;
}
return -1;
}
/// <summary>
/// 分析字尾表示式
/// </summary>
/// <param name="obj">使用者輸入的資訊</param>
/// <returns></returns>
private char HouZhuiBiaoDaShi(string obj)
{
if (obj == "+")
{
return '+';
}
else if (obj == "-")
{
return '-';
}
else if (obj == "x")
{
return 'x';
}
else if (obj == "÷")
{
return '÷';
}
else
{
return '0';
}
}
/// <summary>
/// 計算表示式的結果
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnEqual_Click(object sender, EventArgs e)
{
btnEqual.Enabled = false;//避免多次輸入"="帶來的異常
Stack<double> tempStack = new Stack<double>(); // 運算棧
Queue<string> houZhuiBiaoDaShiQueue = new Queue<string>(); // 儲存字尾表示式的佇列
Stack<char> signStack = new Stack<char>(); // 運算子棧
string tempStr = ""; // 臨時記錄輸入的數字或小數點
int objType;
double tempDouble;
try
{
#region 中綴表示式轉字尾表示式
for (int i = 0; i < input.Length; i++)
{
if (input[i] <= '9' && input[i] >= '0' || input[i] == '.') //找出運算數
{
tempStr += input[i];
}
else
{
if (tempStr.Length > 0) //如果符號前存在數字,則將數字新增到houZhuiBiaoDaShiQueue隊尾
{
houZhuiBiaoDaShiQueue.Enqueue(tempStr);
tempStr = "";
}
if (signStack.Count == 0) //運算子棧為空,該運算子直接入棧
{
signStack.Push(input[i]);
}
else //運算子棧不為空,需要判斷運算子的優先順序
{
#region 判斷運算優先順序
if (GetSignYouXianJi(input[i]) > GetSignYouXianJi(signStack.Peek()))
{
signStack.Push(input[i]);
}
else
{
while (true)
{
houZhuiBiaoDaShiQueue.Enqueue(Convert.ToString(signStack.Pop()));
if (signStack.Count == 0 || GetSignYouXianJi(input[i]) > GetSignYouXianJi(signStack.Peek()))
break;
}
signStack.Push(input[i]);
}
#endregion
}
}
} // end for
if (tempStr.Length > 0) //將最後一個運算數新增到houZhuiBiaoDaShiQueue隊尾
{
houZhuiBiaoDaShiQueue.Enqueue(tempStr);
tempStr = "";
}
while (signStack.Count > 0)//將所有運算子依次新增到隊尾,形成字尾表示式
{
houZhuiBiaoDaShiQueue.Enqueue(Convert.ToString(signStack.Pop()));
}
#endregion
signStack.Clear();
tempStr = "";
#region 計算字尾表示式
while (houZhuiBiaoDaShiQueue.Count > 0)
{
objType = HouZhuiBiaoDaShi(houZhuiBiaoDaShiQueue.Peek());
switch (objType)
{
case '0': // 如果是運算數,則直接入棧(並在字尾表示式佇列中移除該運算數)
tempStack.Push(Convert.ToDouble(houZhuiBiaoDaShiQueue.Dequeue()));
break;
case '+':
houZhuiBiaoDaShiQueue.Dequeue();//在後綴表示式佇列中移除該運算子
tempStack.Push(tempStack.Pop() + tempStack.Pop());
break;
case '-':
houZhuiBiaoDaShiQueue.Dequeue();
tempDouble = tempStack.Pop();//提取出減數
tempStack.Push(tempStack.Pop() - tempDouble);
break;
case 'x':
houZhuiBiaoDaShiQueue.Dequeue();
tempStack.Push(tempStack.Pop() * tempStack.Pop());
break;
case '÷':
houZhuiBiaoDaShiQueue.Dequeue();
tempDouble = tempStack.Pop();//提取出除數
if (tempDouble != 0)
{
tempStack.Push(tempStack.Pop() / tempDouble);
}
else
{
MessageBox.Show("Error: 0是被除數!");
}
break;
default:
MessageBox.Show("未知錯誤!");
break;
}
}
#endregion
input += "=" + Convert.ToString(tempStack.Pop());
ShowMessage();
txtBox.ReadOnly = true;
}
catch (Exception)
{
MessageBox.Show("請輸入正確的運算式!");
throw;
}
}
}
}
當時我正好看了設計模式這本書,下面的程式碼有點走架構風,不過感覺也不影響理解
Operation.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 計算器的設計與實現CSharp
{
public class Operation:Form1
{
public double NumberA { get; set; }
public double NumberB { get; set; }
public virtual double GetResult()
{
double result = 0;
return result;
}
}
}
OperationAdd.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 計算器的設計與實現CSharp
{
public class OperationAdd : Operation
{
public override double GetResult()
{
return NumberA + NumberB;
}
}
}
OperationRemove.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 計算器的設計與實現CSharp
{
public class OperationRemove:Operation
{
public override double GetResult()
{
if (NumberB!=0.0)
{
return NumberA / NumberB;
}
else
{
return 0;
}
}
}
}
OperationRide.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 計算器的設計與實現CSharp
{
public class OperationRide:Operation
{
public override double GetResult()
{
return NumberA * NumberB;
}
}
}
OperationSubtruct.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 計算器的設計與實現CSharp
{
public class OperationSubtruct : Operation
{
public override double GetResult()
{
return NumberA - NumberB;
}
}
}
自我感覺註釋寫得很清楚了,希望對你有幫助~~~