利用逆波兰式制作加减乘除计算器
参照字符串公式解析器——使用“逆波兰式算法”及C#实现文章,写了一个计算器(仅支持加减乘除及括弧)的小示例。
实现思路:先将输入的中序表达式转换为逆波兰式,然后将逆波兰式计算出来。
1.各种堆栈声明:
private Stack<string> OutPutList = new Stack<string>(); private Stack<string> ResultList = new Stack<string>(); private Stack<string> OperSignList = new Stack<string>(); private int BeginIndex = 0; private int EndIndex = 0;
及枚举声明:
public enum OperSign { LeftBracket = 6,//左括号 RightBracket = 5,//右括号 Mul = 4,//乘号 Div = 3,//除号 Add = 2,//加号 Minus = 1,//减号 Default = 0//默认 }
2.解析中序表达式,转为逆波兰式(思路与参考文章相同,实现细节略有不同):
private Stack<string> Parse(string expression) { OutPutList.Clear(); ResultList.Clear(); OperSignList.Clear(); expression = expression + "#"; while (string.IsNullOrEmpty(expression) == false) { EndIndex = GetOperSignPosition(expression); string data = expression.Substring(BeginIndex, EndIndex - BeginIndex); if (string.IsNullOrEmpty(data) == false) { ResultList.Push(data); } string operSign = expression.Substring(EndIndex, 1); switch (operSign) { case "#": break; case "(": OperSignList.Push(operSign); break; case ")": while (OperSignList.Peek() != "(") { ResultList.Push(OperSignList.Pop()); } OperSignList.Pop(); break; default: { OperSign currOperSignEnum = GetOperSignEnum(operSign); OperSign peekOperSignEnum = OperSign.Default; if (OperSignList.Count == 0) { OperSignList.Push(operSign); break; } peekOperSignEnum = GetOperSignEnum(OperSignList.Peek()); var CompareResult = CompareOperSignLevel(currOperSignEnum, peekOperSignEnum); if (CompareResult <= 0 && OperSignList.Peek() != "(") { while (CompareResult <= 0) { ResultList.Push(OperSignList.Pop()); if (OperSignList.Count == 0 || OperSignList.Peek() == "(") { break; } peekOperSignEnum = GetOperSignEnum(OperSignList.Peek()); CompareResult = CompareOperSignLevel(currOperSignEnum, peekOperSignEnum); } } OperSignList.Push(operSign); } break; } expression = expression.Substring(EndIndex + 1); } while (OperSignList.Count > 0) { ResultList.Push(OperSignList.Pop()); } while (ResultList.Count > 0) { this.OutPutList.Push(ResultList.Pop()); } return OutPutList; }
3.解析过程中,用到的各种辅助函数:
private int GetOperSignPosition(string expression) { for (var i = 0; i < expression.Length; i++) { if (OperTypeString.Contains(expression[i]) == true) { return i; } } return -1; }
public int CompareOperSignLevel(OperSign ta, OperSign tb) { if (ta == tb) { return 0; } if (ta == (OperSign.LeftBracket | OperSign.RightBracket) && tb == (OperSign.RightBracket | OperSign.LeftBracket)) { return 0; } if (ta == (OperSign.Mul | OperSign.Div) && tb == (OperSign.Div | OperSign.Mul)) { return 0; } if (ta == (OperSign.Add | OperSign.Minus) && tb == (OperSign.Minus | OperSign.Add)) { return 0; } return ta - tb; }
4.计算示例如下:

备注:本示例的关键在于根据四种运算符的优先级顺序,调整OperSignList堆栈中操作符进入ResultList堆栈的顺序。即:运算符在ResultList堆栈中运算优先级越高,越靠近栈顶。
浙公网安备 33010602011771号