目前正在学习C#并且无法弄清楚我的逻辑出错的地方我正在制作的计算器。计算器在文本框中有三行,顶行是用户通过按钮输入的数字,第二行是屏幕上显示的等式,例如12 + 23-4,最后一个是当用户按下等号时出现的答案。
计算器的逻辑因以下原因而失败:
重现的步骤
在尝试再次减去它的第三步时,由于某种原因增加了它。
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 WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double totalOne = 0;
double totalTwo = 0;
string startingState;
string calculation;
bool plusButtonpressed = false;
bool minusButtonpressed = false;
bool multiplyuButtonpressed = false;
bool divideButtonpressed = false;
private void btnOne_Click(object sender, EventArgs e)
{
startingState += btnOne.Text;
calculation += btnOne.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnTwo_Click(object sender, EventArgs e)
{
startingState += btnTwo.Text;
calculation += btnTwo.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnThree_Click(object sender, EventArgs e)
{
startingState += btnThree.Text;
calculation += btnThree.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnFour_Click(object sender, EventArgs e)
{
startingState += btnFour.Text;
calculation += btnFour.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnFive_Click(object sender, EventArgs e)
{
startingState += btnFive.Text;
calculation += btnFive.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnSix_Click(object sender, EventArgs e)
{
startingState += btnSix.Text;
calculation += btnSix.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnSeven_Click(object sender, EventArgs e)
{
startingState += btnSeven.Text;
calculation += btnSeven.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnEight_Click(object sender, EventArgs e)
{
startingState += btnEight.Text;
calculation += btnEight.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnNine_Click(object sender, EventArgs e)
{
startingState += btnNine.Text;
calculation += btnNine.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnZero_Click(object sender, EventArgs e)
{
startingState += btnZero.Text;
calculation += btnZero.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void button12_Click(object sender, EventArgs e)
{
startingState += btnDecimal.Text;
calculation += btnDecimal.Text;
textDisplay.Clear();
textDisplay.Text = startingState + "\r\n" + calculation;
}
private void btnClear_Click(object sender, EventArgs e)
{
textDisplay.Clear();
}
private void btnPlus_Click(object sender, EventArgs e)
{
totalOne = totalOne + double.Parse(startingState);
startingState = "";
calculation += "+";
textDisplay.Clear();
textDisplay.Text = "" + "\r\n" + calculation;
plusButtonpressed = true;
minusButtonpressed = false;
multiplyuButtonpressed = false;
divideButtonpressed = false;
}
private void btnEqual_Click(object sender, EventArgs e)
{
if (plusButtonpressed == true)
{
totalTwo = totalOne + double.Parse(startingState);
textDisplay.Text = totalTwo.ToString();
textDisplay.Text = "" + "\r\n" + calculation + "\r\n" + "_______________" + "\r\n" + totalTwo;
}
else if (minusButtonpressed == true)
{
totalTwo = totalOne - double.Parse(startingState);
textDisplay.Text = totalTwo.ToString();
textDisplay.Text = "" + "\r\n" + calculation + "\r\n" + "_______________" + "\r\n" + totalTwo;
}
else if (multiplyuButtonpressed == true)
{
totalTwo = totalOne * double.Parse(startingState);
textDisplay.Text = totalTwo.ToString();
textDisplay.Text = "" + "\r\n" + calculation + "\r\n" + "_______________" + "\r\n" + totalTwo;
}
else if (divideButtonpressed == true)
{
totalTwo = totalOne / double.Parse(startingState);
textDisplay.Text = totalTwo.ToString();
textDisplay.Text = "" + "\r\n" + calculation + "\r\n" + "_______________" + "\r\n" + totalTwo;
}
}
private void btnMinus_Click(object sender, EventArgs e)
{
totalOne = totalOne + double.Parse(startingState);
startingState = "";
calculation += "-";
textDisplay.Clear();
textDisplay.Text = "" + "\r\n" + calculation;
plusButtonpressed = false;
minusButtonpressed = true;
multiplyuButtonpressed = false;
divideButtonpressed = false;
}
private void btnMultiply_Click(object sender, EventArgs e)
{
totalOne = totalOne + double.Parse(startingState);
startingState = "";
calculation += "*";
textDisplay.Clear();
textDisplay.Text = "" + "\r\n" + calculation;
plusButtonpressed = false;
minusButtonpressed = false;
multiplyuButtonpressed = true;
divideButtonpressed = false;
}
private void btnDivide_Click(object sender, EventArgs e)
{
totalOne = totalOne + double.Parse(startingState);
startingState = "";
calculation += "/";
textDisplay.Clear();
textDisplay.Text = "" + "\r\n" + calculation;
plusButtonpressed = false;
minusButtonpressed = false;
multiplyuButtonpressed = false;
divideButtonpressed = true;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnRoot_Click(object sender, EventArgs e)
{
totalOne = double.Parse(textDisplay.Text);
totalTwo = Math.Sqrt(totalOne);
textDisplay.Clear();
textDisplay.Text = totalTwo.ToString();
totalOne = 0;
}
private void btnSin_Click(object sender, EventArgs e)
{
totalOne = double.Parse(textDisplay.Text);
totalTwo = Math.Sin(totalOne);
textDisplay.Clear();
textDisplay.Text = totalTwo.ToString();
totalOne = 0;
}
private void btnTan_Click(object sender, EventArgs e)
{
totalOne = double.Parse(textDisplay.Text);
totalTwo = Math.Tan(totalOne);
textDisplay.Clear();
textDisplay.Text = totalTwo.ToString();
totalOne = 0;
}
private void btnCos_Click(object sender, EventArgs e)
{
totalOne = double.Parse(textDisplay.Text);
totalTwo = Math.Cos(totalOne);
textDisplay.Clear();
textDisplay.Text = totalTwo.ToString();
totalOne = 0;
}
}
}
答案 0 :(得分:0)
问题在于你没有正确地跟踪你的状态。
执行=
后,您需要将结果重新放回totalOne
,以便准备接受其他操作。
另外,你正在做很多重复。用这么多代码找到错误真的很难。
请改为尝试:
public partial class Form1 : Form
{
double totalOne = 0.0;
string startingState;
string calculation;
Func<double, double, double> operation = null;
public Form1()
{
InitializeComponent();
btnClear.Click += (s, e) =>
{
startingState = "";
totalOne = 0.0;
calculation = "";
operation = null;
textDisplay.Clear();
};
var numerals = new[]
{
btnZero, btnOne, btnTwo, btnThree, btnFour, btnFive, btnSix, btnSeven, btnEight, btnNine, btnDecimal,
};
foreach (var numeral in numerals)
{
var button = numeral;
button.Click += (s, e) =>
{
startingState += button.Text;
calculation += button.Text;
textDisplay.Text = startingState + "\r\n" + calculation;
};
}
var ops = new Dictionary<Button, Func<double, double, double>>()
{
{ btnPlus, (x, y) => x + y },
{ btnMinus, (x, y) => x - y },
{ btnMultiply, (x, y) => x * y },
{ btnDivide, (x, y) => x / y },
};
foreach (var x in ops)
{
var button = x.Key;
var op = x.Value;
button.Click += (s, e) =>
{
var totalTwo = double.Parse(startingState);
totalOne = operation == null ? totalTwo : operation(totalOne, totalTwo);
startingState = "";
calculation += button.Text;
textDisplay.Text = "" + "\r\n" + calculation;
operation = op;
};
}
btnEqual.Click += (s, e) =>
{
if (operation != null)
{
var totalTwo = double.Parse(startingState);
totalOne = operation(totalOne, totalTwo);
textDisplay.Text = String.Join(Environment.NewLine, new[] { "", calculation, "_______________", totalOne.ToString() });
startingState = totalOne.ToString();
operation = null;
}
};
}
}
现在,使用此代码,我可以这样做:
答案 1 :(得分:0)
这是一种方法 - 如果不完全理解你的代码正在做什么,它有点难以描述,但原则可能会有所帮助。
现在,您的计算器的状态完全存在于您的表单中 - 控件中的值和一些变量。如果您定义了一个包含所有这些操作的类,这将变得更容易管理。
在任何给定点,您的计算器可能处于少数几个状态之一。如果您正在键入第一个号码,然后选择一个运算符(加上,除以等),那么您的状态会发生变化。现在你不再输入第一个号码了。输入的下一个是你的第二个号码。在输入第一个数字时,操作员是可接受的输入。但是如果你刚刚选择了一个操作员,那么你输入的下一个东西就不能是另一个操作员。无论您的计算器处于什么状态,您都可以按“清除”并重置为开始状态。
所有这些听起来都很多,但如果您尝试将所有逻辑构建到表单中并尝试跟踪所有这些正在更新的控件之间的状态,则会更加复杂。
如果你把它写成一个类,那么你可以专注于直接获得所有逻辑,而无需更新表单控件和处理输入的额外复杂性。您无需通过表单控件与计算器交互,而是通过设置和读取属性以及执行方法与其进行交互。
您也可以编写单元测试。您可以编写一个以Calculator类开头的测试,执行某些操作,然后检查以确保它处于您期望的状态并显示您期望的结果,而不是打开计算器表单并手动测试每个场景。 / p>
同样,这听起来很多,但为了让你的计算器正常工作,无论如何你将不得不做所有这些。你最终会一遍又一遍地测试它。编写单元测试似乎更多的工作,但最终它加快了速度,并帮助您更快地解决您的错误。
一旦你的计算器类工作,你就可以在表单中创建该类的实例。当用户与控件交互时,表单会调用类的方法和属性。操作完成后,表单会更新以反映计算器的状态(如显示答案的内容。)
这样做的另一个影响是你的计算器抽象 - 它不像一个表单那样依赖于一个实现。既然你已经完成了正确的逻辑工作并且已经为它编写了单元测试,那么你可以在控制台应用程序或网页中使用相同的类。
我强调这一点的原因是因为许多程序员(包括我自己)工作多年而没有学习编写单元测试或将逻辑与表示分开(比如在一个类中编写计算器而不是将其作为表单的一部分) 。)我上面描述的所有东西听起来更像是工作。但是一旦你学会了这些想法并实践它们,它的工作就会减少。您可以更快地获得代码,并且可以花费更少的时间来调试表单,页面或其他寻找错误的代码。