C# 简易计算器(一)、C# 简易计算器(二)
完成了一些功能后我去网上找了找类似的代码,在这个过程中学到了很多,其中了解到设计模式这个词,以及《大话设计模式》这本书,第一章就是使用简单工厂设计模式来写计算器,因此,我花了一段时间,将原先的代码用简单工厂设计模式重新写了一遍。
功能上和之前是一样的,首先是计算类Operation
class Operation
{
private double numberA = 0.0;
private double numberB = 0.0;
public double NumberA
{
get{return numberA;}
set { numberA = value; }
}
public double NumberB
{
get{return numberB;}
set { numberB = value; }
}
//获得结果
public virtual double getResult()
{
double result = 0.0;
return result;
}
//添加小数点
public virtual string addPoint(string str)
{
return str;
}
//正负号
public virtual string posAndNeg(string str)
{
return str;
}
}
接着是四则运算以及开根号的类,继承Operation类;
加:
class OperationAdd : Operation
{
public override double getResult()
{
double result = 0.0;
result = NumberA + NumberB;
return result;
}
}
减:
class OperationSub : Operation
{
public override double getResult()
{
double result = 0;
result = NumberA - NumberB;
return result;
}
}
乘:
class OperationMul : Operation
{
public override double getResult()
{
double result = 0;
result = NumberA * NumberB;
return result;
}
}
除:
class OperationDiv : Operation
{
public override double getResult()
{
double result = 0;
if (NumberB == 0)
throw new Exception("除数不能为0!");
result = NumberA / NumberB;
return result;
}
}
开根号:
class OperationSquareRoot : Operation
{
public override double getResult()
{
double result;
try
{
Regex reg = new Regex(@"(\+|\-)?(\d+)(\.\d+)?");
var res = reg.Match(MainForm.calShow).Groups;
if (res[1].ToString() == "-")
{
throw new Exception("负数不能开根号!");
}
result = Math.Sqrt(Convert.ToDouble(MainForm.calShow));
return result;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "警告");
return 0;
}
}
小数点:
class OperationPoint : Operation
{
public override string addPoint(string str)
{
try
{
bool res = Regex.IsMatch(str, @"^(\-)?\d+$");//匹配纯数字
bool res1 = Regex.IsMatch(str, @"^(\-)?\d+(\.\d+)?(\+|\-|\*|\/)\d+$");//匹配第二个操作数是否为整数
if (res || res1)//满足其中一个则可以添加小数点
{
str += ".";
}
return str;
}
catch (Exception)
{
MessageBox.Show("发生错误!", "警告");
return str;
}
}
}
正负号:
class OperationPosAndNeg : Operation
{
public override string posAndNeg(string str)
{
try
{
Regex reg = new Regex(@"^(\-)?");
var res = reg.Match(str).Groups;
if (res[1].ToString() == "")//正数
{
str = "-" + str;
}
else//负数
{
str = str.Substring(1, str.Length - 1);
}
return str;
}
catch (Exception)
{
MessageBox.Show("发生错误!", "警告");
return str;
}
}
}
接下来就是工厂类,需要啥就new啥
class OperationFactory
{
public static Operation createOperation(string operation)
{
Operation oper = null;
switch (operation)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
case "*":
oper = new OperationMul();
break;
case "/":
oper = new OperationDiv();
break;
case "SquareRoot":
oper = new OperationSquareRoot();
break;
case ".":
oper = new OperationPoint();
break;
case "+/-":
oper = new OperationPosAndNeg();
break;
default:
break;
}
return oper;
}
}
窗体程序:
首先是数字键事件:
private void btnNum_Click(object sender,EventArgs e)
{
bool res = Regex.IsMatch(calShow, @"^0+$");//匹配全都是0的情况
bool res1 = Regex.IsMatch(calShow, @"^(\-)?\d+(\.\d+)?(\+|\-|\*|\/)0+$");//匹配第二个操作数是否全都是0的情况
if (res || res1)//满足其中一个则把前面的0删掉
{
btnDel.PerformClick();
}
if (equalStatus)//等于号按过之后点数字则直接清除原来的结果
{
equalStatus = false;
calShow = "";
resultDouble = 0.0;
txtResual.Text = "";
}
Button btn = (Button)sender;
calShow += btn.Name.ToString().Substring(btn.Name.ToString().Length-1);
txtResual.Text = calShow;
setBtnEnableMethon(true);
btnEqual.Focus();
}
接着是运算符按键事件:
这里用Button btn = sender as Button;将参数传进来,这些按钮都绑定到btnOperation_Click这一个事件,就不会每一个按钮都需要生成一个事件函数,不方便管理。
private void btnOperation_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
Operation oper;
switch (btn.Name)
{
case "btnAdd":
equalStatus = false;
multiDeal();
calShow += "+";
txtResual.Text = calShow;
setBtnEnableMethon(false);
break;
case "btnSub":
equalStatus = false;
multiDeal();
calShow += "-";
txtResual.Text = calShow;
setBtnEnableMethon(false);
break;
case "btnMul":
equalStatus = false;
multiDeal();
calShow += "*";
txtResual.Text = calShow;
setBtnEnableMethon(false);
break;
case "btnDiv":
equalStatus = false;
multiDeal();
calShow += "/";
txtResual.Text = calShow;
setBtnEnableMethon(false);
break;
case "btnEqual":
equalStatus = true;
multiDeal();
break;
case "btnPoint":
if (equalStatus)//等于号按过之后点数字则直接清除原来的结果
{
equalStatus = false;
calShow = "";
resultDouble = 0.0;
txtResual.Text = "";
}
oper = OperationFactory.createOperation(".");
calShow = oper.addPoint(calShow);
txtResual.Text = calShow;
setBtnEnableMethon(true);
break;
case "btnDel":
if (calShow.Length != 0)
{
calShow = calShow.Substring(0, calShow.Length - 1);//删除最后一个字符
}
txtResual.Text = calShow;
setBtnEnableMethon(true);
break;
case "btnClear":
calShow = "";
resultDouble = 0;
txtResual.Text = "";
break;
case "btnSquareRoot":
multiDeal();//先得出前面表达式的值
oper = OperationFactory.createOperation("SquareRoot");
resultDouble = oper.getResult();
calShow = resultDouble.ToString();
txtResual.Text = calShow;
break;
case "btnPosAndNeg":
multiDeal();//先计算结果,再来加正负号
oper = OperationFactory.createOperation("+/-");
calShow = oper.posAndNeg(calShow);
txtResual.Text = calShow;
break;
default:
break;
}
}
最后修改一下运算的函数:
private void multiDeal()
{
try
{
//将前面的表达式的值计算出来
Regex reg = new Regex(@"(\+|\-)?(\d+)(\.\d+)?(\+|\-|\*|\/)(\+|\-)?(\d+)(\.\d+)?");
var res = reg.Match(calShow).Groups;
//res[0] 整个匹配的表达式
//res[1] 第一个操作数的符号
//res[2] 第一个操作数的整数部分
//res[3] 第一个操作数的小数部分
//res[4] 操作符
//res[5] 第二个操作数的符号
//res[6] 第二个操作数的整数部分
//res[7] 第而个操作数的小数部分
Operation oper;
switch (res[4].ToString())
{
case "+":
oper = OperationFactory.createOperation("+");
oper.NumberA = Convert.ToDouble(res[1].ToString() + res[2].ToString() + res[3].ToString());
oper.NumberB = Convert.ToDouble(res[5].ToString() + res[6].ToString() + res[7].ToString());
resultDouble = oper.getResult();
calShow = resultDouble.ToString();
break;
case "-":
oper = OperationFactory.createOperation("-");
oper.NumberA = Convert.ToDouble(res[1].ToString() + res[2].ToString() + res[3].ToString());
oper.NumberB = Convert.ToDouble(res[5].ToString() + res[6].ToString() + res[7].ToString());
resultDouble = oper.getResult();
calShow = resultDouble.ToString();
break;
case "*":
oper = OperationFactory.createOperation("*");
oper.NumberA = Convert.ToDouble(res[1].ToString() + res[2].ToString() + res[3].ToString());
oper.NumberB = Convert.ToDouble(res[5].ToString() + res[6].ToString() + res[7].ToString());
resultDouble = oper.getResult();
calShow = resultDouble.ToString();
break;
case "/":
oper = OperationFactory.createOperation("/");
oper.NumberA = Convert.ToDouble(res[1].ToString() + res[2].ToString() + res[3].ToString());
oper.NumberB = Convert.ToDouble(res[5].ToString() + res[6].ToString() + res[7].ToString());
if (oper.NumberB == 0)
throw new Exception("除数不能为0!");
resultDouble = oper.getResult();
calShow = resultDouble.ToString();
break;
default:
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "警告");
}
txtResual.Text = calShow;
}
其他的没有变化,通过这次作业和后续的改进,我接触到很多,对于面向对象有了新的理解,记得上学期老师说过:你们学过一学期java面向对象程序后,我还是看不出你们有使用面向对象,还是C语言的面向过程。
任重而道远啊~
代码:https://github.com/headwindf/Calculator-