c# - 相同的算法一次有效,第二次出错
问题描述
好吧,在我得到答案之前,这个问题可能会被关闭......我正在尝试编写一个非常简单的计算器,它可以完美地工作:
private void button1_Click(object sender, EventArgs e)
{
string[] input = rtbInput.Text.Split(' ');
rtbInput.Text += " = " + CalculateNumber(input).ToString();
}
long CalculateNumber(string[] input)
{
long curValue = 0;
curValue = long.Parse(input[0]);
//LOOK FOR PARENTHASIS, LAST INDEX, SEARCH FROM THERE UNTIL FIRST INDEX, RUN THIS AGAIN FOR THAT.
//THEN REPLACE "5 + (3 + 3)" with 5 + 6. So calculate 3 + 3 = 6 and replace ( until ) with answer.
if (rtbInput.Text.Contains("(") && rtbInput.Text.Contains(")"))
{
int c = 0;
int startNum;
int len;
string s = "No";
}
int i = 0;
while (i < (input.Length - 1))
{
switch (input[i])
{
case "+":
curValue += long.Parse(input[i + 1]);
break;
case "-":
curValue -= long.Parse(input[i + 1]);
break;
case "*":
curValue = curValue * long.Parse(input[i + 1]);
break;
case "/":
curValue = curValue / long.Parse(input[i + 1]);
break;
}
i++;
}
return curValue;
}
这非常有效。但是当尝试添加计算Parenthasis“(3 * 3)= 9”的能力时,我实现了这个代码:
long CalculateNumber(string[] input)
{
long curValue = 0;
curValue = long.Parse(input[0]);
//LOOK FOR PARENTHASIS, LAST INDEX, SEARCH FROM THERE UNTIL FIRST INDEX, RUN THIS AGAIN FOR THAT.
//THEN REPLACE "5 + (3 + 3)" with 5 + 6. So calculate 3 + 3 = 6 and replace ( until ) with answer.
if (rtbInput.Text.Contains("(") && rtbInput.Text.Contains(")"))
{
int c = 0;
int startNum;
int len;
string s = "No";
//while there are still parenthasis in the input, do this
if (c < rtbInput.Text.Split('(').Count() - 1) //REPLACE WITH WHILE
{
startNum = rtbInput.Text.LastIndexOf('(') + 1;
len = rtbInput.Text.IndexOf(')', startNum);// - startNum;
s = rtbInput.Text.Substring(startNum, len);
this.Name = s;
//NOW REPLACE THIS WITH THE RETURN OF CalculateParenthasis.Split(' ')
rtbInput.Text = rtbInput.Text.Replace("(" + s + ")", CalculateParenthasis(s.Split(' ')).ToString());
}
long CalculateParenthasis(string[] input)
{
long curValue = 0;
curValue = long.Parse(input[0]);
button1.Text += curValue.ToString();
int i = 0;
while (i < (input.Length - 1))
{
switch (input[i])
{
case "+":
curValue += long.Parse(input[i + 1]);
break;
case "-":
curValue -= long.Parse(input[i + 1]);
break;
case "*":
curValue = curValue * long.Parse(input[i + 1]);
break;
case "/":
curValue = curValue / long.Parse(input[i + 1]);
break;
}
i++;
}
return curValue;
}
正如您所看到的,CalculateParenthasis() 函数的工作方式与 CalculateNumber() 完全相同,但采用括号之间的数字,但在 switch 语句中出现此错误,表示输入字符串的格式错误?什么?我几乎不知道如何问这个问题,似乎是一件很小很容易出错的事情,但我就是看不到。
解决方案
根据我的测试,我重现了您遇到的问题。
但是,我发现由于它的复杂性,我们很难完成它。
因此,我建议您使用反向波兰算法来制作计算器。
我做了一个代码示例来制作它,你可以参考它。
代码:
public class Example
{
public static Stack<string> operStack = new Stack<string>();
public static Stack<string> numStack = new Stack<string>();
static bool IsNumber(string s)
{
return Regex.IsMatch(s, @"\d+");
}
static bool IsSiZe(string s)
{
string ts = "+-*/";
return ts.IndexOf(s) > -1;
}
static int Level(string s)
{
int i = 0;
switch (s)
{
case ",":
i = 0;
break;
case "(":
case ")":
case "#":
i = 1;
break;
case "+":
case "-":
i = 2;
break;
case "*":
case "/":
i = 3;
break;
}
return i;
}
public static void Calc(Stack<string> numStack, Stack<string> operStack)
{
int rightnum = int.Parse(numStack.Pop());
int leftnum = int.Parse(numStack.Pop());
string oper = operStack.Pop();
switch (oper)
{
case "+":
numStack.Push((leftnum + rightnum).ToString());
break;
case "-":
numStack.Push((leftnum - rightnum).ToString());
break;
case "*":
numStack.Push((leftnum * rightnum).ToString());
break;
case "/":
numStack.Push((leftnum / rightnum).ToString());
break;
}
}
public static void ToNiBoLan(string exp)
{
operStack.Push("#"); //Push into the stack for comparsion
string token = "";
for (int i = 0; i < exp.Length; i++)
{
if (IsNumber(exp[i].ToString())) //If it is number
{
token += exp[i].ToString();
}
else if (exp[i].ToString() == "(")
{
operStack.Push(exp[i].ToString());
if (IsNumber(token))
numStack.Push(token);
token = "";
}
else if (IsSiZe(exp[i].ToString()))
{
if (IsNumber(token))
numStack.Push(token);
token = "";
int item = Level(exp[i].ToString()).CompareTo(Level(operStack.Peek())); //Comparison operator precedence
if (item > 0) //If the priority is higher than the top of the stack, the operator is pushed onto the stack
{
operStack.Push(exp[i].ToString());
}
else //If the operator is less than or equal to the top of the stack, calculate and push the operator onto the stack
{
Calc(numStack, operStack);
operStack.Push(exp[i].ToString());
}
}
else if (exp[i].ToString() == ")")
{
if (IsNumber(token))
numStack.Push(token);
token = "";
while (operStack.Peek() != "(")
{
Calc(numStack, operStack);
}
token = numStack.Pop(); //Take out the numbers for the next calculation
operStack.Pop(); //Eligible left parenthesis popped
}
else //End of traversal
{
if (IsNumber(token))
numStack.Push(token);
token = "";
while (numStack.Count > 1)
{
Calc(numStack, operStack);
}
}
}
}
}
在winforms中使用它:
private void button1_Click(object sender, EventArgs e)
{
//For comparison, add "#" at the end of the expression
string text = richTextBox1.Text.Trim() + "#";
Example.ToNiBoLan(text);
richTextBox1.Text = Example.numStack.Pop().ToString();
}
推荐阅读
- php - 我试图将同一张表中的 2 列相乘,并直接在 laravel 的 where 语句中使用结果
- ios - Nativescript BitmapFactory 调整大小在 iOS 中不起作用
- spring-boot - 使用 XQuery 进行日志记录
- xamarin - 使用 xamarin 表单从页面中删除向后滑动手势
- javascript - 如何强制 VSCode 使用本地安装的 TypeScript
- python-3.x - TypeError: 不支持的操作数类型 -: 'datetime.datetime' 和 'datetime.time'
- javascript - 如何使用 chart.js 和 symfony 3 制作图表
- sql - postgreSQL 递归 - 查找包含多个员工和其他公司不同工作的所有循环
- amazon-web-services - AWS Api 网关自定义域路由到错误的基本 url
- javascript - 计算元素的响应宽度以定义大小