Windows Form简易计算器实现(下)

  陆陆续续更新这个计算器用了一个礼拜了,今天无论如何也要把它更完。笔者有点追求完美,再者每天都有课,晚上还有作业,还有每晚都会写一些其他的博文。

  上一次漏了写如何实现计算的。思路如下:

  之前得到一个栈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 = "";                                    //声明切定义一个空字符串,用于在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。

  提示:一般遇到访问内存,比如取栈压栈访问栈顶的代码,最好上异常处理,因为很容易就出现错误。

  欢迎大家提出质疑!

时间: 2024-08-05 09:51:29

Windows Form简易计算器实现(下)的相关文章

C#Windows Form简易计算器实现(上)

第一次写博客,来分享一个简易计算器的代码.作为一名准程序员,就是要多写代码才能孰能生巧.重视基础知识才能飞的更快更高以及更稳. 代码可能会写的很糟糕,不完美不安全之处希望发现的越多越好 c#编写计算器带窗口的,对于新手来说是如何建立窗体以及实现按钮的响应事件吧!那么,首先来探索下窗口是怎么实现的吧! 步骤1:新建项目→C#windows窗体应用程序→新建解决方案 此时你会发现有两个名称,一个是解决方案名称,一个是项目名称.对于小程序来说其实没什么区别.但对于大点的程序最好就要区别开了.解决方案就

C#Windows Form简易计算器实现(中)

昨天花了一天的时间弄计算器.也算是做出来了,还是简易的(怀疑猿生!!).在此先感谢昨天被我骚扰的朋友. 先贴一张界面看看 其实健壮性还是挺差的,用户体验也是极差的.比如说用户输入了不合理运算式子,我就直接抛出一个异常完事了,因为要在原来的算法里加判断实在晕乱.所以趁热打铁,希望在写博客的时候再把思路理理,完善不足. 思路一: 因为计算的是四则混合运算,比如2*6-4/(2+3).我们最开始得到的是一个表达式字符串,计算机是不会帮你计算的.而四则混合运算有优先等级的计算,那么该怎么计算呢?于是问了

C语言下的简易计算器

1 #include <stdio.h> 2 #include <math.h> 3 int main() 4 { 5 double data1, data2; 6 char op; 7 while (3 == scanf("%lf%c%lf", &data1, &op, &data2) ) 8 { 9 double result; 10 printf("%lf%c%lf=", data1,data2); 11 swi

C# 简易计算器

编写如下界面的简易计算器界面代码: using System; using System.Windows.Forms; using exp; namespace calculator { public partial class Form1 : Form { public Form1() { InitializeComponent(); } enum symbol { plus,dec,mult,div}; private void button1_Click(object sender, Ev

JAVA开发简易计算器界面-SWT

大家好,我是成都[LD],博客四年前就申请了,一直没打理,最近正好有时间,遂萌生了写技术博客的念头.我不得不感慨现在新技术更新很快,一不小心,就感觉自身就Out了.记得一年前,当时我也是在51CTO上了解到NoSQL和Hadoop这样的信息,当时就简单觉得很新奇,没想到一年之后发展如此迅速~~当然我这样说,并不是叫大家去追寻新技术,最根本的还是基础打牢靠,休息的时候多去了解下最新的IT动态.学习下前辈高手的一些技能~~打铁还需自身硬嘛! 我写博客的目的:一来是为了促进自身的进步,二来是为了希望与

表单提交的的简易计算器

起先,分析需求: 1.可以输入两个数值,选择操作符号,返回计算结果:2.在当前页面显示结果,同时当前页面保存用户的操作(计算样式存在,不因提交而置空) 完毕,先布好html代码: <body> <form method="post" action=""> <input type="text" name="first" > <select name="sel">

基于mini2440简易计算器

基于mini2440简易计算器使用的是数组实现,并非逆波兰式,因此功能不够强大,仅供驱动学习,以及C语言基础编程学习之用.有时间读者可以用逆波兰式来实现强大功能计算器,原理也很简单,建议读<c程序设计第二版>里面有算法的代码.读者自行研究.此程序基于电子相册的改进,触摸屏,LCD,字符现实,数字输入等等 mini2440  索尼X35   LCD液晶屏 主函数部分: #include "def.h" #include "option.h" #includ

如何用jsp实现一个简易计算器(三)

做这个jsp页面,主要是为了实现在同一个页面提交和接受数据的功能. 这个小程序存在很多不足,希望大家多多批评指正. <%@ page language="java" contentType="text/html;" pageEncoding="gbk"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://w

windows form中将服务器端的文件保存到客户端

开发中常常遇到这样的问题:需要将服务器端的文件下载到客户端.这种情况分为两种,一种是windows环境,一种是web环境.前两天在winform开发中就遇到过这样一个问题,上网搜索后没有发现现成的demo,所以自己花费了一点时间,做了一个简单的文件保存的demo,分享如下: 首先需要写一个下载的方法,将其抽象为一个静态类,以方便调用,如下: public static class FileHelper { /// <summary> /// 下载服务器文件至客户端,Create By Wang