實驗題目
設(shè)計一個支持連續(xù)計算的簡單計算器挽霉,其過程包括項目分析写穴,界面設(shè)計,代碼編寫和運行調(diào)試判没。通過該項目的開發(fā),使讀者進一步了解基于圖形用戶界面的Windows應(yīng)用程序的開發(fā)過程隅茎,并通過項目實訓(xùn)的擴展練習(xí)加深印象澄峰,為開發(fā)較為復(fù)雜的應(yīng)用程序打下基礎(chǔ)。
實驗方案
設(shè)計思路: 有兩個棧 一個存放數(shù)字 一個存放運算符
1辟犀、將表達式字符串轉(zhuǎn)換成字符數(shù)組 遍歷字符數(shù)組
2俏竞、判斷表達式是否合法,合法的話再進行計算
3堂竟、如果是數(shù)字 直接存放到數(shù)字棧
4魂毁、如果是符號:分為兩種情況
(1) 如果符號棧為空 直接將符號入棧
(2)如果符號棧不為空
a、當(dāng)運算符和棧內(nèi)的運算符進行比較 如果當(dāng)前的運算符的優(yōu)先級低于或者等于棧中的運算符出嘹,就需要從數(shù)棧中pop出兩個數(shù)席楚,再從符號棧中pop出一個符號肌割,進行運算瘫辩, 將得到的結(jié)果push進數(shù)棧,然后將當(dāng)前的符號push符號棧刻获;
b郎仆、如果當(dāng)前的操作符的優(yōu)先級大于棧中的運算符 就直接入符號棧
4只祠、當(dāng)表達式掃描完畢 就順序從數(shù)棧和符號棧pop出相應(yīng)的數(shù)和符號 并運行
5、最后數(shù)棧中只有一個數(shù)字 即為表達式的結(jié)果
設(shè)計界面
功能展示
實驗總結(jié)
本次實驗代碼體量較小扰肌,所用到的也是原來在數(shù)據(jù)結(jié)構(gòu)課程中學(xué)過的棧抛寝,理解起來相對容易∈镄瘢基礎(chǔ)部分主要參考書上代碼以及網(wǎng)上的內(nèi)容墩剖。拓展部分主要參考網(wǎng)上的內(nèi)容自行理解加以修正。整體碰見以下問題夷狰,現(xiàn)加以分析:
1岭皂、第一次設(shè)計時并沒有參考書上代碼,自己寫的比較簡單沼头,沒有使用棧爷绘。但發(fā)現(xiàn)在擴展功能需要完成優(yōu)先級時很困難书劝,故又利用棧重新設(shè)計。
2土至、在拓展部分出現(xiàn)sin购对,cos的計算功能,剛開始只是在原來基礎(chǔ)上簡單添加陶因,后來發(fā)現(xiàn)沒有考慮優(yōu)先級的問題骡苞,加到棧里后又發(fā)現(xiàn)這兩個是單目運算符,還要再考慮單目運算符和雙目運算符的判斷楷扬。
3解幽、拓展功能還提到了專用領(lǐng)域的計算器,但沒有做出來烘苹,希望以后有機會可以接觸一下躲株。
4、第一次實現(xiàn)窗體桌面程序镣衡,雖然內(nèi)容比較簡單霜定,但是在設(shè)計過程中不僅僅需要思考怎樣可以得到正確的運算結(jié)果,還需要考量用戶怎么使用會更加舒適廊鸥,這是自己從來沒有接觸過的望浩。
源碼展示
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 myCalculator
{
public partial class Form_Main : Form
{
string ptr = ""; //算數(shù)表達式
Stack<int> lastlen = new Stack<int>();//添加操作數(shù)之前的算術(shù)表達式的長度
Stack<int> lastlenT = new Stack<int>();//添加操作數(shù)之前的文本框的長度
bool start = true;
string lastAns = "0";//標(biāo)志初始化
Stack<double> nums = new Stack<double>();//操作數(shù)
Stack<char> ops = new Stack<char>();//運算符
public Form_Main()
{
InitializeComponent();
textDisplay.Text = "0";
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void TextDisplay_TextChanged(object sender, EventArgs e)
{
}
private void Btn_2_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "2";
ptr += "2";
}
private void Btn_3_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "3";
ptr += "3";
}
private void Btn_4_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "4";
ptr += "4";
}
private void Button6_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "5";
ptr += "5";
}
private void Btn_6_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "6";
ptr += "6";
}
private void Btn_7_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "7";
ptr += "7";
}
private void Btn_8_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "8";
ptr += "8";
}
private void Btn_9_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "9";
ptr += "9";
}
private void Btn_equal_Click(object sender, EventArgs e)
{
textDisplay.Clear();
string ans = Cal(ptr); //調(diào)用求值算法
lastlen.Clear();
lastlenT.Clear();
lastlen.Push(0);
lastlenT.Push(0);
textDisplay.Text += ans;
ptr = ans;
double result;
bool flag = double.TryParse(ans, out result);
if (!flag || ans == "0") start = true;
}
private void Button11_Click(object sender, EventArgs e)//點
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
int len = textDisplay.Text.Length;
if (len == 0 || (textDisplay.Text[len - 1] < '0' || textDisplay.Text[len - 1] > '9') && textDisplay.Text[len - 1] != '.')
{
textDisplay.Text += "0.";
ptr += "0.";
}
else
{
textDisplay.Text += ".";
ptr += ".";
}
}
private void Btn_1_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "1";
ptr += "1";
}
private void Btn_0_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "0";
ptr += "0";
}
private void Btn_add_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length); //沒有添加前的算術(shù)表達式的長度
lastlenT.Push(textDisplay.Text.Length);
if (ptr == "")
{
textDisplay.Text += "+";
ptr += "0+"; //把單目運算符“+”改成雙目運算符
}
else
{
textDisplay.Text += "+";
ptr += "+";
}
}
private void Btn_clear_Click(object sender, EventArgs e)
{
textDisplay.Text = "0";
ptr = "";
lastlenT.Clear();
lastlen.Clear();
start = true;
}
private void Btn_sub_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "-";
int len = ptr.Length;
if (len != 0 && (ptr[len - 1] == ')' || (ptr[len - 1] >= '0' && ptr[len - 1] <= '9')))
ptr += "+-"; //把“-”改成單目運算符
else ptr += "-";
}
private void Btn_multi_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "*";
ptr += "*";
}
private void Btn_div_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "/";
ptr += "/";
}
private void Button1_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += "(";
ptr += "(";
}
private void Btn_right_bracket_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
textDisplay.Text += ")";
ptr += ")";
}
private bool check(string str) //檢查算術(shù)表達式是否匹配
{
int jd = 0, num = 0;
int len = str.Length;
int st = 0, ed = len - 1;
while (str[st] == '(' && st < ed) st++;
while (str[ed] == ')' && ed > 0) ed--;
if ((str[st] < '0' || str[st] > '9') && str[st] != '-' && str[st] != 'S' && str[st] != 's' && str[st] != 'c') return false;
if ((str[ed] < '0' || str[ed] > '9') && str[ed] != '!' && str[ed] != '^') return false;
for (int i = 0; i < len; i++)
{
if (str[i] == '+' || str[i] == '*' || str[i] == '/' || str[i] == '%') jd++;
if ((str[i] >= '0' && str[i] <= '9') || str[i] == '.') jd = 0;
if (jd >= 2) return false;
}
jd = 0;
for (int i = 0; i < len; i++)
{
if (str[i] == '(') jd++;
else if (str[i] >= '0' && str[i] <= '9' && jd > 0) num++;
else if (str[i] == ')')
{
if (jd == 0 || num == 0) return false;
jd--;
}
}
if (jd > 0) return false;
return true;
}
private int isp(char op)
{
// s 表示sin, c 表示cos
if (op == '#') return 0;
if (op == '(') return 1;
if (op == '*' || op == '/' || op == 'c' || op == 's') return 5;
if (op == '+' || op == '-') return 3;
if (op == ')') return 7;
return -1;
} //返回棧中算符優(yōu)先級
private int icp(char op)
{
if (op == '#') return 0;
if (op == '(') return 7;
if (op == '*' || op == '/') return 4;
if (op == 'c' || op == 's') return 6;
if (op == '+' || op == '-') return 2;
if (op == ')') return 1;
return -1;
}//返回棧外算符優(yōu)先級
private double compute(double l, char op, double r)
{
if (op == '+') return l + r;
if (op == '-') return l - r;
if (op == '*') return l * r;
if (op == '/') return l / r;
return 0;
} //計算運算符
private bool trans(ref string str)//檢測第一位是不是負號 ref關(guān)鍵字--讓參數(shù)按照引用傳遞
{
int num = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == '-') num++;
else break;
}
str = str.Substring(num);
if (num % 2 == 0) return false;
return true;
}
private string Cal(string str) //用堆棧實現(xiàn)中綴表達式求值
{
if (str == "") str = "0";
if (str == "∞") return str;
if (!check(str)) return "Syntax Error";
str += '#';
nums.Clear();
ops.Clear();
ops.Push('#');
for (int i = 0; i < str.Length; i++)
{
bool number = false;
string tmp = "";
while ((str[i] >= '0' && str[i] <= '9') || str[i] == '.' || str[i] == '-' )
{
number = true;
tmp += str[i];
i++;
}
bool flag;
if (number)
{
flag = trans(ref tmp);
double res;
bool success = double.TryParse(tmp, out res);
if (flag) res = -res; //把減號轉(zhuǎn)成負號
if (success) nums.Push(res);
else return "Syntax Error";
}
flag = true;
while (flag)
{
if (icp(str[i]) > isp((char)ops.Peek()))
{
ops.Push(str[i]);
break;
}
else if (icp(str[i]) < isp((char)ops.Peek()))
{
double r = nums.Pop();
char op = ops.Pop();
if (op == 's' || op == 'c')
{
if (op == 's') nums.Push(Math.Sin(r * Math.PI / 180));//弧度角度轉(zhuǎn)換
else nums.Push(Math.Cos(r * Math.PI / 180));//弧度角度轉(zhuǎn)換
}
else
{
double l = nums.Pop();
if (op == '/' && r == 0) return "∞";
nums.Push(compute(l, op, r));
}
}
else
{
ops.Pop();
break;
}
}
}
if (nums.Count > 1) return "Syntax Error";
lastAns = nums.Pop().ToString();
return lastAns;
}
private void Btn_sin_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
int len = textDisplay.Text.Length;
if (len > 0 && ((textDisplay.Text[len - 1] >= '0' && textDisplay.Text[len - 1] <= '9') || textDisplay.Text[len - 1] == ')'))
{
textDisplay.Text += "*";
ptr += "*";
}
textDisplay.Text += "sin(";
ptr += "s(";
}
private void Btn_cos_Click(object sender, EventArgs e)
{
if (start)
{
ptr = "";
textDisplay.Clear();
start = false;
}
lastlen.Push(ptr.Length);
lastlenT.Push(textDisplay.Text.Length);
int len = textDisplay.Text.Length;
if (len > 0 && ((textDisplay.Text[len - 1] >= '0' && textDisplay.Text[len - 1] <= '9') || textDisplay.Text[len - 1] == ')'))
{
textDisplay.Text += "*";
ptr += "*";
}
textDisplay.Text += "cos(";
ptr += "c(";
}
private void Btn_backspace_Click(object sender, EventArgs e)
{
string str = textDisplay.Text;
if (str == "Syntax Error" || str == "∞" || str == "Math Error" || str == "Too big")
{
textDisplay.Text = "0";
start = true;
return;
}
textDisplay.Text = textDisplay.Text.Substring(0, lastlenT.Pop());
if (ptr.Length != 0)
{
ptr = ptr.Substring(0, lastlen.Pop());
}
if (textDisplay.Text.Length == 0)
{
textDisplay.Text = "0";
lastlenT.Push(0);
start = true;
}
}
}
}