前段时间微软在全球最大的同性交友网站GitHub上开源了微软计算器的C++代码:https://github.com/Microsoft/calculator。我在动手做这个计算器之前和大多数人都有着一样的观点:不就是一个计算器吗?这能有多难啊?(眼高手低 十分不屑.jpg)然而等到自己真正动手做起来的时候就会发现其实做一个计算器并没有想象中的那么简单。下面这张截图是我写的1.4版的计算器运行界面啦(GitHub:https://github.com/Don2025/MyCode/tree/master/calculator),前面几个版本的计算器代码太丑陋就不放上来了,就简述一下这些版本存在的bug以及修改的方法。
对了,附上我们老师做的计算器(GitHub:https://github.com/HBU/DataBase/tree/master/Csharp/Calculator),我的1.0版是在老师的基础上实现的(当时老师也还没支持键盘输入),but now哈哈哈哈我感觉我写的这个1.4版计算器的功能比老师的更强大。
1.0版 只有一行文本框,只能进行加减乘除运算。1.0版发现的第一个bug就是当除数为0时,结果会是∞。
1.1版 用一条if语句解决了除数为0时结果为∞的问题,若除数为0,计算器会提示“除数不能为0!”,且会在下一次计算开始前进行初始化(效果和按下AC键一样)。1.1版修改了左上角的图标、新增加了当前时间,但是我发现有俩个bug:①用户完成一次计算后,重新输入一串数字,文本框不会清空,而是会在上一次的计算结果后加数字;②用户在完成一次计算后,继续输入运算符和一串数字,计算器并不能够在上一次计算结果的基础上进行计算,计算器会直接奔溃;③当用户输入完一串数字和一个运算符后文本框会变为空,此时用户不输入下一串数字而是继续输入运算符,计算器就会直接奔溃。
1.2版 出现了俩行输入文本框,第一行显示计算式子,第二行显示计算结果。解决了1.1版的俩个问题:①在一次计算完成后,重新输入一串数字能够开始一次新的运算;②在上一次计算结束后直接输入运算符和一串数字,第二行结果会变到第一行并且完成计算。1.2版还是没能够解决用户连续输入多个运算符的问题,而且我发现它不能一次性进行多个运算符的运算,比如2×3+1。
1.3版 这个版本有俩个很重要的突破。首先是能支持键盘输入了(前面的版本都只能靠点击按钮),然后我也并没有像前面的版本一样对字符串进行分割开来再计算结果,而是用到了DataTable.Compute()这个函数来直接得出计算结果(代码如下所示)。这样一来就可以直接对用户在文本框中输入的字符串型计算式进行求值。
string str = "2*3+1";
var sum = new DataTable().Compute(str, null);
//这样能计算出来sum = 7;
1.4版 主要是做了一些界面上的优化,计算器的文本框应该是靠右显示的,于是我将textBox的属性TextAlign从Left改为了Right,还有就是AutoSizeMode属性设置为了GrowAndShrink,不允许用户自动调节窗体大小。然后新增加了回删功能,可以点击←或在键盘上按Backspace键进行回删。
private void ButtonBack_Click(object sender, EventArgs e) //用于删除textBox的最后一个字符
{
if (textBox1.Text.Length != 0)
{
textBox1.Text = textBox1.Text.Substring(0, textBox1.Text.Length - 1);
}
}
1.4版还在界面上把乘号从"*"改成了"×",把除号从"/"改成了"÷",这样改了之后需要在计算之前对字符串进行一次替换。
string str = textBox1.Text.Replace('÷', '/').Replace('×', '*'); //替换一下乘号和除号
1.4版目前还存在的一个小bug就是数字键的Enter不能实现等于号的功能。
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 WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1() //默认构造函数
{
InitializeComponent();
}
bool isEqual = false; //判断一次计算是否完成
public void Initialize() //初始化
{
textBox1.Text = "";
textBox2.Text = "";
isEqual = false;
}
private void Button0_Click(object sender, EventArgs e)
{
if(isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "0";
}
private void Button1_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "1";
}
private void Button2_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "2";
}
private void Button3_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "3";
}
private void Button4_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "4";
}
private void Button5_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "5";
}
private void Button6_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "6";
}
private void Button7_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "7";
}
private void Button8_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "8";
}
private void Button9_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += "9";
}
private void ButtonDot_Click(object sender, EventArgs e)
{
if (isEqual)
{
Initialize();
isEqual = false;
}
textBox1.Text += ".";
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
if(isEqual)
{
textBox1.Text = textBox2.Text;
textBox2.Text = "";
isEqual = false;
}
textBox1.Text += "+";
}
private void ButtonSub_Click(object sender, EventArgs e)
{
if(isEqual)
{
textBox1.Text = textBox2.Text;
textBox2.Text = "";
isEqual = false;
}
textBox1.Text += "-";
}
private void ButtonMul_Click(object sender, EventArgs e)
{
if(isEqual)
{
textBox1.Text = textBox2.Text;
textBox2.Text = "";
isEqual = false;
}
textBox1.Text += "×";
}
private void ButtonDiv_Click(object sender, EventArgs e)
{
if(isEqual)
{
textBox1.Text = textBox2.Text;
textBox2.Text = "";
isEqual = false;
}
textBox1.Text += "÷";
}
private void ButtonAC_Click(object sender, EventArgs e) //全部清零
{
textBox1.Text = "";
textBox2.Text = "";
}
private void ButtonBack_Click(object sender, EventArgs e) //用于删除textBox的最后一个字符
{
if (textBox1.Text.Length != 0)
{
textBox1.Text = textBox1.Text.Substring(0, textBox1.Text.Length - 1);
}
}
private void ButtonEquals_Click(object sender, EventArgs e)
{
string str = textBox1.Text.Replace('÷', '/').Replace('×', '*'); //替换一下乘号和除号
var sum = new DataTable().Compute(str, null);
textBox2.Text = "";
textBox2.Text += sum;
if(textBox2.Text == "∞")
{
textBox2.Text = "除数不能为0!";
}
isEqual = true;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyData)
{
case Keys.D0: case Keys.NumPad0: Button0_Click(sender, e); break;
case Keys.D1: case Keys.NumPad1: Button1_Click(sender, e); break;
case Keys.D2: case Keys.NumPad2: Button2_Click(sender, e); break;
case Keys.D3: case Keys.NumPad3: Button3_Click(sender, e); break;
case Keys.D4: case Keys.NumPad4: Button4_Click(sender, e); break;
case Keys.D5: case Keys.NumPad5: Button5_Click(sender, e); break;
case Keys.D6: case Keys.NumPad6: Button6_Click(sender, e); break;
case Keys.D7: case Keys.NumPad7: Button7_Click(sender, e); break;
case Keys.D8: case Keys.NumPad8: Button8_Click(sender, e); break;
case Keys.D9: case Keys.NumPad9: Button9_Click(sender, e); break;
case Keys.Decimal: ButtonDot_Click(sender, e); break;
case Keys.Add: ButtonAdd_Click(sender, e); break;
case Keys.Subtract: ButtonSub_Click(sender, e); break;
case Keys.Multiply: ButtonMul_Click(sender, e); break;
case Keys.Divide: ButtonDiv_Click(sender, e); break;
case Keys.Back: ButtonBack_Click(sender, e); break;
case Keys.Oemplus: ButtonEquals_Click(sender, e); break;
default: break;
}
}
private void Timer1_Tick(object sender, EventArgs e)
{
label2.Text = DateTime.Now.ToString(); //设置label2的文本为当前的系统时间
}
}
}