[C#]自制简易计算器窗体应用程序(仿windows自带计算器)

前言 

C#学习过程中,遇到一个作业:仿照windows自带计算器编写一个窗体应用程序。经过学习、编写、不断试错和优化,做出了一个满意度较高的成品。

结果展示

程序界面与功能如下:

算法讲解:

要能够实现按钮的输入操作,在这一步,可以将多个按钮的Click函数合并,用一个函数来控制多个不同但功能类似的按钮。

private void Numbtn_Click(object sender, EventArgs e)//数字部分
        {
            Button btn = (Button)sender;
            if (output)//连等结束后的处理
            {
                left_num = right_num = result = 0;
                textBox1.Text = "";
                flag = ' ';
                output = false;
            }
            if (btn.Text.Equals("0"))
            {
                if (start || textBox2.Text == "0")//计算结束后重新输入,输入框清零
                {
                    textBox2.Text = "";
                    textBox2.Text += "0";
                    put0 = false;
                }
                if (put0)//只有允许输出0时才能输出0
                {
                    textBox2.Text += "0";
                }
            }
            else
            {
                if (start || textBox2.Text == "0")
                {
                    textBox2.Text = "";
                    start = false;
                }
                textBox2.Text += btn.Text;//输入数字
                if (flag != ' ')//若有运算符,则能够进行运算
                    end = true;
                put0 = true;//输入数字后可以输入多个0
            }
            
        }

数字输入部分功能:

(1)连等后数字重新输入

(2)计算结束后数字重新输入

(3)添加数字

private void Flagbtn_Click(object sender, EventArgs e)//符号部分
        {
            Button btn = (Button)sender;
            if (flag != '+' && textBox2.Text == "")//符号变换
            {
                if (!(string.IsNullOrEmpty(textBox1.Text)))//判断非空
                {
                    int temp = textBox1.Text.Length;
                    textBox1.Text = textBox1.Text.Substring(0, temp - 1);
                    textBox1.Text += btn.Text;
                    Flagchange(btn.Text);
                    return;
                }
            }
            if (end)//计算
            {
                right_num = Convert.ToDouble(textBox2.Text);
                Numcal();
                textBox1.Text = Convert.ToString(result) + btn.Text;
                Flagchange(btn.Text);
                start = true;
                end = false;
            }
            else//添加符号
            {
                checkPoint();
                left_num = Convert.ToDouble(textBox2.Text);
                textBox1.Text = textBox2.Text + btn.Text;
                Flagchange(btn.Text);
                output = false;
                start = true;
            }
        }

符号输入部分功能:

(1)已经输入符号,需要变换符号。例如:  已经输入”6+“,想要改为”6-“,故而在已经输入过符号后再次输入符号

(2)连续计算。例如6+3+4。由于本程序为仿照windows简易计算器功能,故不具备括号或优先级计算的功能,仅能实现输入第二个+号时,自动计算前面式子并输出答案的功能

(3)添加符号。如果未输入符号,则添加按钮相应符号

private void button18_Click(object sender, EventArgs e)//等号部分
        {
            checkPoint();
            if (flag == ' ')//无运算的等号
            {
                textBox1.Text = textBox2.Text + "=";
                start = true;
                return;
            }
            if (output)//处理连等
            {
                textBox1.Text = left_num.ToString() + textBox1.Text.Substring(textBox1.Text.Length - right_num.ToString().Length - 2, right_num.ToString().Length + 2);
                Numcal();
                start = true;
                end = false;
                put0 = false;
                return;
            }
            //计算
            right_num = Convert.ToDouble(textBox2.Text);
            textBox1.Text += textBox2.Text + "=";
            Numcal();
            start = true;
            end = false;
            output = true;
            put0 = false;
        }

等号输入部分功能:

(1)无运算的等号

(2)连等处理

(3)等号的计算

剩余根号、百分号、倒数、正负号、清零、删除部分较为简单,故不详细介绍。

完整代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using Button = System.Windows.Forms.Button;

namespace Calculator
{
    public partial class Calculation : Form
    {
        public Calculation()
        {
            InitializeComponent();
        }
        double left_num = 0, right_num = 0, result = 0;
        bool start = true, end = false, put0 = false, output = false;
        char flag = ' ';//根据加减乘除的选择控制运算
        public void Flagchange(string btn_flag)//控制符号
        {
            if(btn_flag == "+")
            {
                flag = '+';
            }
            else if(btn_flag == "-")
            {
                flag = '-';
            }
            else if(btn_flag == "×")
            {
                flag = '*';
            }
            else if(btn_flag == "÷")
            {
                flag = '/';
            }
        }

        public void Numcal()//计算
        {
            if (flag == '+')
                result = left_num + right_num;
            else if (flag == '-')
                result = left_num - right_num;
            else if (flag == '*')
                result = left_num * right_num;
            else if (flag == '/')
                result = left_num / right_num;
            left_num = result;
            textBox2.Text = Convert.ToString(result);
        }

        public void checkPoint()//检查小数点后有无数字
        {
            if (textBox2.Text.Contains("."))
            {
                try
                {
                    Convert.ToInt32(textBox2.Text[textBox2.Text.IndexOf(".") + 1]);
                }
                catch
                {
                    textBox2.Text = textBox2.Text.Replace(".", "");
                }
            }
        }

        private void Numbtn_Click(object sender, EventArgs e)//数字部分
        {
            Button btn = (Button)sender;
            if (output)//连等结束后的处理
            {
                left_num = right_num = result = 0;
                textBox1.Text = "";
                flag = ' ';
                output = false;
            }
            if (btn.Text.Equals("0"))
            {
                if (start || textBox2.Text == "0")//计算结束后重新输入,输入框清零
                {
                    textBox2.Text = "";
                    textBox2.Text += "0";
                    put0 = false;
                }
                if (put0)//只有允许输出0时才能输出0
                {
                    textBox2.Text += "0";
                }
            }
            else
            {
                if (start || textBox2.Text == "0")
                {
                    textBox2.Text = "";
                    start = false;
                }
                textBox2.Text += btn.Text;//输入数字
                if (flag != ' ')//若有运算符,则能够进行运算
                    end = true;
                put0 = true;//输入数字后可以输入多个0
            }
            
        }

        private void button11_Click(object sender, EventArgs e)//小数点部分
        {
            if (start)
            {
                textBox2.Text = "0";
            }

            if (!textBox2.Text.Contains("."))//只有不存在小数点时才允许输入,防止小数点过多
            {
                textBox2.Text += ".";
                start = false;
            }

        }

        private void Flagbtn_Click(object sender, EventArgs e)//符号部分
        {
            Button btn = (Button)sender;
            if (flag != '+' && textBox2.Text == "")//符号变换
            {
                if (!(string.IsNullOrEmpty(textBox1.Text)))//判断非空
                {
                    int temp = textBox1.Text.Length;
                    textBox1.Text = textBox1.Text.Substring(0, temp - 1);
                    textBox1.Text += btn.Text;
                    Flagchange(btn.Text);
                    return;
                }
            }
            if (end)//计算
            {
                right_num = Convert.ToDouble(textBox2.Text);
                Numcal();
                textBox1.Text = Convert.ToString(result) + btn.Text;
                Flagchange(btn.Text);
                start = true;
                end = false;
            }
            else//添加符号
            {
                checkPoint();
                left_num = Convert.ToDouble(textBox2.Text);
                textBox1.Text = textBox2.Text + btn.Text;
                Flagchange(btn.Text);
                output = false;
                start = true;
            }
        }

        private void button16_Click(object sender, EventArgs e)//百分号部分
        {
            checkPoint();
            textBox2.Text = Convert.ToString(Convert.ToDouble(textBox2.Text) * left_num / 100);
        }

        private void button17_Click(object sender, EventArgs e)//倒数部分
        {
            checkPoint();
            textBox1.Text = "1/(" + textBox2.Text + ")";
            textBox2.Text = Convert.ToString(1 / (Convert.ToDouble(textBox2.Text)));
            left_num = result;
            start = true;
            put0 = false;
            end = false;
        }

        private void button18_Click(object sender, EventArgs e)//等号部分
        {
            checkPoint();
            if (flag == ' ')//无运算的等号
            {
                textBox1.Text = textBox2.Text + "=";
                start = true;
                return;
            }
            if (output)//处理连等
            {
                textBox1.Text = left_num.ToString() + textBox1.Text.Substring(textBox1.Text.Length - right_num.ToString().Length - 2, right_num.ToString().Length + 2);
                Numcal();
                start = true;
                end = false;
                put0 = false;
                return;
            }
            //计算
            right_num = Convert.ToDouble(textBox2.Text);
            textBox1.Text += textBox2.Text + "=";
            Numcal();
            start = true;
            end = false;
            output = true;
            put0 = false;
        }

        private void button19_Click(object sender, EventArgs e)//根号部分
        {
            checkPoint();
            textBox1.Text = "√(" + textBox2.Text + ")";
            textBox2.Text = Convert.ToString(Math.Sqrt(Convert.ToDouble(textBox2.Text)));
            left_num = result;
            start = true;
            put0 = false;
            end = false;
        }

        private void button20_Click(object sender, EventArgs e)//正负号部分
        {
            checkPoint();
            textBox2.Text = Convert.ToString(Convert.ToDouble(textBox2.Text) * -1);//只需乘以-1即可(感谢zjt)
        }

        private void button21_Click(object sender, EventArgs e)//CE部分
        {
            textBox2.Text = "0";
            put0 = false;
            start = true;
            end = false;
        }

        private void button22_Click(object sender, EventArgs e)//C部分
        {
            left_num = right_num = result = 0;
            textBox1.Text = "";
            textBox2.Text = "0";
            flag = ' ';
            start = true;
            put0 = false;
            end = false;
        }

        private void button23_Click(object sender, EventArgs e)//Delete部分
        {
            if (!start)//计算完成不允许删除
            {
                if (textBox2.Text != "0")
                {
                    int temp = textBox2.Text.Length;
                    textBox2.Text = textBox2.Text.Substring(0, temp - 1);
                    if (textBox2.Text == "")
                    {
                        textBox2.Text = "0";
                        put0 = false;
                        start = true;
                    }
                }
            }
            else
            {
                textBox1.Text = "";
            }

        }
    }
}

再给大家分享一下笔者在编写程序过程中遇到的一些bug,各位也可据此测试一下自己的程序并进行相关优化。

  • 未输入其他数字时可以输入很多个0
  • 小数点数量不受限制(限制小数点数量为一个后删除小数点则不能添加回来)
  • 符号同时出现多个
  • 连等(连续计算)出错
  • 计算完成后不能重新输入
  • 清零有误(不能还原所有设置)
一、实验题目:计算器实验 二、实验目的: 1)熟悉.NET的编程方法,掌握项目的创建与使用及安装; 2)熟悉C#编程语言,字符串使用、自定义类、自定义类库等; 3)熟悉Windows应用程序类编程、事件驱动编程; 三、实验内容: 1)参照Windows提供的计算器工具,设计一个与之类似的程序;另外可参考运行效果下载(计算器Demo程序); 2)基本要求:实现“普通运算”功能,支持连续运算,如连续输入“2+3×5”后点击“等号”按钮进行运算其结果为25. 3)附加要求: A,支持“科学运算”功能,即输入表达式时遵循运算符号的优先原则,连续输入“2+3×5”后点击“等号”按钮进行运算其结果为17; B,支持数字键盘(小键盘)输入功能(焦点不在文本框内时也支持键盘输入); 四、实验方法 经过用户的输入得到数学表达式后,可选择以下方法计算结果: 方法1)不定义"计算类",根据用户输入在程序中直接计算出结果。 方法2)在项目中设计一个计算类(CalculateClass),其中包含“普通计算”和“科学计算”功能,即输入数学运算表达式字符串,返回计算结果。直接在项目中调用该类,输出计算结果。 方法3)在解决方案中增加一个类库(ClassLibrary)项目(在bin\debug下生成dll文件),其中包含计算类(CalculateClass),该类中包含两个方法(普通计算和科学计算),可以根据表达式计算结果。然后在计算器项目中“引用”该类库中的类,输出计算结果; 点评:方法1代码重用性差;方法2代码重用性好,在项目内可方便使用;方法3代码重用性较好,能在不同的项目内重用。 五、实验说明 1)认真分析总结每个“按钮”点击之后的动作(对应的代码); 默认的控件是Button按钮,其实可以用其他支持Click事件的控件替代也行,比如图片控件PictureBox; 2)代码的共享:如数字按钮可以共享一个事件代码; // 参考代码 private void button2_Click(object sender, EventArgs e) { Button objbutton = (Button)sender; label1.Text = "你按了第" + (sender as Button).Tag.ToString() + "个按钮"; } 3)考虑操作性或实用性,如支持退格键、异常输入处理等; 4)为突出实验重点,可以不考虑数制转换、复合运算、括号运算等功能; 5)支持数字小键盘输入时,留意理解窗口的KeyPreview属性,即是否窗口接收键盘事件。另外实现时会涉及到“焦点隐藏”问题,以及按钮的键盘事件等。 敲键盘时发生的事件当然是键盘事件,关键是“窗体”还是“控件”接收键盘事件。如果窗体的KeyPreview设为true,则敲键盘时发生的事件被窗体接收;否则就是控件接收键盘事件。 所谓“焦点隐藏” 是指界面上没有焦点,例如系统提供的计算器。方法一:界面上的控件不获取焦点或者没有焦点(如标签);方法二:将焦点藏在界面上不可见的控件上。 支持数字键盘输入的情形:当焦点在按钮1上时,按数字键2,其使用效果应相当于点击了按钮2。 6)键盘事件KeyPress和KeyDown中e参数包括键盘码; private void KeyBoardForm_KeyPress(object sender, KeyPressEventArgs e) { //KeyPress 不能识别组合键 label1.Text = "你按的键是:" + e.KeyChar; } 7)“麻雀虽小,五脏俱全”,程序很容易出Bug,请认真调试; 8)要想达到界面有特点,不亚于在功能上下功夫。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值