綜合實驗(一)簡單計算器

實驗題目

設(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è)計界面

功能展示

運行調(diào)試圖(一)含有四則的連續(xù)運算表達式

運行調(diào)試圖(二)運行結(jié)果

實驗總結(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;
            }
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惰说,一起剝皮案震驚了整個濱河市曾雕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌助被,老刑警劉巖剖张,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異揩环,居然都是意外死亡搔弄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門丰滑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來顾犹,“玉大人,你說我怎么就攤上這事褒墨§潘ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵郁妈,是天一觀的道長浑玛。 經(jīng)常有香客問我,道長噩咪,這世上最難降的妖魔是什么顾彰? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任极阅,我火速辦了婚禮,結(jié)果婚禮上涨享,老公的妹妹穿的比我還像新娘筋搏。我一直安慰自己,他們只是感情好厕隧,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布奔脐。 她就那樣靜靜地躺著,像睡著了一般吁讨。 火紅的嫁衣襯著肌膚如雪髓迎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天挡爵,我揣著相機與錄音竖般,去河邊找鬼甚垦。 笑死茶鹃,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的艰亮。 我是一名探鬼主播闭翩,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼迄埃!你這毒婦竟也來了疗韵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤侄非,失蹤者是張志新(化名)和其女友劉穎蕉汪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逞怨,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡者疤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了叠赦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驹马。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖除秀,靈堂內(nèi)的尸體忽然破棺而出糯累,到底是詐尸還是另有隱情,我是刑警寧澤册踩,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布泳姐,位于F島的核電站,受9級特大地震影響暂吉,放射性物質(zhì)發(fā)生泄漏仗岸。R本人自食惡果不足惜允耿,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望扒怖。 院中可真熱鬧较锡,春花似錦、人聲如沸盗痒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俯邓。三九已至骡楼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間稽鞭,已是汗流浹背鸟整。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留朦蕴,地道東北人篮条。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像吩抓,于是被迫代替她去往敵國和親涉茧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 數(shù)據(jù)結(jié)構(gòu)與算法 1.算法的有窮性是指( )。答案:A A)算法程序的運行時間是有限的 B)算法程序所處理的數(shù)據(jù)量是...
    織夢學(xué)生閱讀 3,376評論 1 15
  • 一雨饺、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運行的地址不確定 關(guān)于...
    SeanCST閱讀 7,802評論 0 27
  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,380評論 0 5
  • 秋雨聲聲陪葉落钳垮, 寒霜片片染楓紅。 白云遠遠送鴻雁额港, 暮色沉沉落鎮(zhèn)中饺窿。 街道縱橫清掃凈, 高樓廣廈若繁星锹安。 中央廣...
    云逸1108閱讀 233評論 0 2
  • 春風(fēng)一直在吹短荐,早上和太陽肩并肩起來,中午和陽光一起明媚微笑叹哭,夕陽落忍宋,日暮降,她吹得更待勁了风罩,吹落了樹葉糠排,吹來了綠芽...
    邑蝶閱讀 181評論 0 0