利用逆波兰式制作加减乘除计算器

参照字符串公式解析器——使用“逆波兰式算法”及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堆栈中运算优先级越高,越靠近栈顶。

 

posted @ 2017-04-11 14:09  Shapley  阅读(1177)  评论(0)    收藏  举报