计算器如图所示,仅实现加减乘除及括号功能,公式错误时会有提示。
首先建立一个inputList,每次点击将内容添加至inputList中,点击后退时则删除List中最后一个元素。
每次操作后将inputList组合成串显示在输入框中;
List<string> input = new List<string>();
public string Add(string str)
{
input.Add(str);
return string.Join("", input);
}
public string delete()
{
if (input.Count > 0)
input.RemoveAt(input.Count - 1);
return string.Join("", input);
}
View Code
其次建立一个elementList,点击计算时将inputList中的字符组合成数据添加到elementList中,比如:
inputList中存放的是[1,.,2,*,1,0,+,1] 八个,组合到elementList中是[1.2,*,10,+,1] 五个。
List<string> element = new List<string>();
/// <summary>
/// 将输入的字符串进行操作符,数值的分割
/// </summary>
bool SplitEle()
{
element.Clear();
input.ForEach(i =>
{
switch (Getflag(i))
{
case enum_flag.data://数据
if (element.Count == 0 || Getflag(element.Last()) != enum_flag.data)
element.Add(i);
else
element[element.Count - 1] = element.Last() + i;
break;
case enum_flag.limit://括号
case enum_flag.symbol://操作符+-*/
element.Add(i);
break;
}
});
return true;
}
View Code
然后将我们输入的公式转换为后缀表达式,如1.2*10+1应为1.210*1+,后缀表达式换算方法如下:
初始化一个Stack栈temp,用于临时存放运算符,建立一个postFixList,用于存放后缀表达式。遍历elementList:
①.遇到操作数据,如1.2,直接加入postFixList;
②.遇到左括号"(",直接放入栈temp中,遇到右括号")",则依次取出栈中运算符并加入到postFixList中,直至取出"(",
取出的"("不要放入postFixList中,若没有则公式错误;
③.遇到运算符,则依次取出栈中优先级>=自己的运算符,放入后缀postFixList中,若碰到左括号"("或者栈空则停止,
然后将自己放入栈temp中。
遍历结束后,将栈temp中剩余的运算符全部依次取出添加至postFixList,若postFixList中存在括号,则说明公式错误不对称。
此时应该temp为空,postFixList中为[1.2,10,*,1,+],代码如下:
List<string> postFix = new List<string>();
Stack<string> temp = new Stack<string>();
/// <summary>
/// 将输入的公式转换为后缀表达式
/// </summary>
bool ConvertToPostFix()
{
bool err = false;
temp.Clear();
postFix.Clear();
element.ForEach(e =>
{
switch (Getflag(e))
{
case enum_flag.data:
postFix.Add(e);
break;
case enum_flag.limit:
if (e == "(")
temp.Push(e);
if (e == ")")
{
err = true;
while (temp.Count > 0)
{
string cur = temp.Pop();
if (cur == "(")
{
err = false;
break;
}
postFix.Add(cur);
}
}
break;
case enum_flag.symbol:
while (temp.Count > 0)
{
if (temp.Peek() == "(")
break;
if ((temp.Peek() == "+" || temp.Peek() == "-") && (e == "*" || e == "/"))
break;
postFix.Add(temp.Pop());
}
temp.Push(e);
break;
}
});
while (temp.Count > 0)
{
if (temp.Peek() == "(" || temp.Peek() == ")")
return false;
postFix.Add(temp.Pop());
}
return !err;
}
View Code
最后计算后缀表达式,计算步骤为,清空栈temp,遍历postFixList:
①.遇到操作数据,直接放入栈temp中;
②.遇到运算符,则依次取出两个栈顶元素data1和data2,与运算符进行运算,data1为右侧数据,data2为左侧数据;
然后将计算得到的值放入栈中;
遍历结束后,栈中应该只剩一个数值,即为最终结果,否则公式错误。代码如下:
/// <summary>
/// 对后缀表达式进行计算
/// </summary>
/// <returns></returns>
bool ExcuteFormula()
{
temp.Clear();
bool err = false;
postFix.ForEach(p =>
{
if (Getflag(p) == enum_flag.data)
temp.Push(p);
if (Getflag(p) == enum_flag.symbol)
{
if (temp.Count >= 2)
{
float newV = cal(temp.Pop(), temp.Pop(), p);
temp.Push(newV.ToString("0.00"));
}
else
err = true;
}
});
return !err;
}
float cal(string r, string l, string a)
{
float left = float.Parse(l);
float right = float.Parse(r);
switch (a)
{
case "+":
return left + right;
case "-":
return left - right;
case "*":
return left * right;
case "/":
return left / right;
}
return 0;
}
View Code
验证下计算过程,输入公式(1.2+1.3)*2/3,监视过程:
最初输入:
按数据分割:
后缀表达式:
栈:
结果: