综合实验(一)简单计算器

实验题目

设计一个支持连续计算的简单计算器,其过程包括项目分析,界面设计,代码编写和运行调试。通过该项目的开发,使读者进一步了解基于图形用户界面的Windows应用程序的开发过程,并通过项目实训的扩展练习加深印象,为开发较为复杂的应用程序打下基础。

实验方案

设计思路: 有两个栈 一个存放数字 一个存放运算符
1、将表达式字符串转换成字符数组 遍历字符数组
2、判断表达式是否合法,合法的话再进行计算
3、如果是数字 直接存放到数字栈
4、如果是符号:分为两种情况
(1) 如果符号栈为空 直接将符号入栈
(2)如果符号栈不为空
a、当运算符和栈内的运算符进行比较 如果当前的运算符的优先级低于或者等于栈中的运算符,就需要从数栈中pop出两个数,再从符号栈中pop出一个符号,进行运算, 将得到的结果push进数栈,然后将当前的符号push符号栈;
b、如果当前的操作符的优先级大于栈中的运算符 就直接入符号栈
4、当表达式扫描完毕 就顺序从数栈和符号栈pop出相应的数和符号 并运行
5、最后数栈中只有一个数字 即为表达式的结果


算法流程图

设计界面

功能展示

运行调试图(一)含有四则的连续运算表达式

运行调试图(二)运行结果

实验总结

本次实验代码体量较小,所用到的也是原来在数据结构课程中学过的栈,理解起来相对容易。基础部分主要参考书上代码以及网上的内容。拓展部分主要参考网上的内容自行理解加以修正。整体碰见以下问题,现加以分析:
1、第一次设计时并没有参考书上代码,自己写的比较简单,没有使用栈。但发现在扩展功能需要完成优先级时很困难,故又利用栈重新设计。
2、在拓展部分出现sin,cos的计算功能,刚开始只是在原来基础上简单添加,后来发现没有考虑优先级的问题,加到栈里后又发现这两个是单目运算符,还要再考虑单目运算符和双目运算符的判断。
3、拓展功能还提到了专用领域的计算器,但没有做出来,希望以后有机会可以接触一下。
4、第一次实现窗体桌面程序,虽然内容比较简单,但是在设计过程中不仅仅需要思考怎样可以得到正确的运算结果,还需要考量用户怎么使用会更加舒适,这是自己从来没有接触过的。

源码展示

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 = "";   //算数表达式
        Stack<int> lastlen = new Stack<int>();//添加操作数之前的算术表达式的长度
        Stack<int> lastlenT = new Stack<int>();//添加操作数之前的文本框的长度
        bool start = true;
        string lastAns = "0";//标志初始化
        Stack<double> nums = new Stack<double>();//操作数
        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);  //调用求值算法
            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); //没有添加前的算术表达式的长度
            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)  //检查算术表达式是否匹配
        {
            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;
        }  //返回栈中算符优先级
        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;
        }//返回栈外算符优先级
        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关键字--让参数按照引用传递
        {
            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)  //用堆栈实现中缀表达式求值
        {
            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;  //把减号转成负号
                    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));//弧度角度转换
                            else nums.Push(Math.Cos(r * Math.PI / 180));//弧度角度转换
                        }
                        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;
            }
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 数据结构与算法 1.算法的有穷性是指( )。答案:A A)算法程序的运行时间是有限的 B)算法程序所处理的数据量是...
    织梦学生阅读 3,349评论 1 15
  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 7,774评论 0 27
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,365评论 0 5
  • 秋雨声声陪叶落, 寒霜片片染枫红。 白云远远送鸿雁, 暮色沉沉落镇中。 街道纵横清扫净, 高楼广厦若繁星。 中央广...
    云逸1108阅读 231评论 0 2
  • 春风一直在吹,早上和太阳肩并肩起来,中午和阳光一起明媚微笑,夕阳落,日暮降,她吹得更待劲了,吹落了树叶,吹来了绿芽...
    邑蝶阅读 179评论 0 0