表达式求值

因工作需要对表达式求值,借机巩固下基础知识,使用两个栈,一个存放操作数,一个存放算符。

在表达式的开始和结尾分别放一个#,表示开始和结束。

算符栈初始的时候有一个#算符,如果是计算1+2,这里会有一个疑问,1入栈后,读到算符+,
(当前的算符)其优先级比 栈顶算符# 大,也就是栈顶算符优先级低,则需要把该算符入栈。
下一个算符是#,其优先级比栈顶算符+的小,栈顶算符优先级大,则将两个操作数出栈和栈顶算符出栈,进行运算。

如果计算表达式1+2+3*4。

1入栈后,读到算符+,
(当前的算符)其优先级比 栈顶算符# 大,也就是栈顶算符优先级低,则需要把该算符入栈。
下一个算符是+,其优先级和栈顶算符优先级相等,这里会有一个疑问,根据则将栈顶算符出栈,并去取下一个字符。(错误)

这里把栈顶的+出栈,当前算符+也没有入栈,栈顶算符变成了#。 +算符都没有了,可怎么办?

读取下一个字符是3,操作数里面有1 2 3

读取到*,比栈顶算符优先高,栈顶算符优先级低,则入栈。
读取最后一个算符#,栈顶算符优先级高,则进行计算:3*4 。

正确的运算过程是:

1入栈后,读到算符+,
(当前的算符)其优先级比 栈顶算符# 大,也就是栈顶算符优先级低,则需要把该算符入栈。
下一个算符是+,其优先级和栈顶算符优先级相等,根据运算法则,同级别时,先左后右。应该将栈顶算符和两个操作数取出,进行计算,然后将当前字符和运算结果入栈。
支持+-*/运算的代码:

public class ExpCaculate
    {
        Stack<int> optd = new Stack<int>();
        Stack<char> optr = new Stack<char>();
       
        public void run(string exp)
        {
            optr.Push('#');
            Console.WriteLine("计算表达式:" + exp);
            for (int i = 0; i < exp.Length; i++)
            {
                char ch = exp[i];

                // 识别0-9数字
                if (IsNumer(ch))
                {
                    // 从表达式里面提取数字
                    StringBuilder d = new StringBuilder();
                    d.Append(ch);
                    for (int j = i+1; j < exp.Length; j++)
                    {
                        if (IsNumer(exp[j]))
                        {
                            d.Append(exp[j]);
                            i = j;
                        }
                        else
                        {
                            break;
                        }
                    }

                    int t = int.Parse(d.ToString());
                    optd.Push(t);

                }
                else if (IsOptr(ch))
                {
                    switch (Percede(ch))
                    {
                        case ">": //当前算符优先级高, 栈顶算符优先级低
                            optr.Push(ch);
                            break;
                        case "<":
                        case "=":
                            int a = optd.Pop();
                            int b = optd.Pop();
                            char theta = optr.Pop();
                            int r = Caclulae(a, b, theta);
                            optd.Push(r);
                            optr.Push(ch);
                            break;
                        default:
                            break;
                    }
                }

            }// end for

            optr.Pop();

            while (optr.Count > 1&&optd.Count>1)
            {
                int a = optd.Pop();
                int b = optd.Pop();
                char theta = optr.Pop();
                int r = Caclulae(a, b, theta);
                optd.Push(r);
            }
            if (optd.Count == 1)
            {
                Console.WriteLine("计算结果是:" + optd.Pop());
                optr.Clear();
                optd.Clear();
            }
            else
            {
                Console.WriteLine("error :");
            }

        }

        private int Caclulae(int a, int b, char theta)
        {
            switch (theta){
                case '+':
                    return a + b;
                case '-':
                    return a - b;
                case '*':
                    return a * b;
                case '/':
                    return a / b;
            }

            return 0;
        }

        private string Percede(char ch)
        {
            if (optr.Count == 0)
            {
                return "";
            }
            char top = optr.Peek();
            switch (top)
            {
                case '+':
                case '-':
                    if (ch == '*' || ch == '/')
                    {
                        return ">";
                    }
                    else if (ch == '+' || ch == '-')
                    {
                        return "=";
                    }
                    else
                    {
                        return "<";
                    }
                case '*':
                case '/':
                    if (ch == '*' || ch == '/')
                    {
                        return "=";
                    }
                    else if (ch == '+' || ch == '-')
                    {
                        return "<";
                    }
                    else
                    {
                        return "<";
                    }
                case '#':
                    if (ch == '#')
                    {
                        return "=";
                    }
                    else
                    {
                        return ">";
                    }
            }
            return "=";
        }

        private bool IsOptr(char ch)
        {
            return ch == '+' || ch == '-' || ch == '*' || ch == '/'|| ch == '#';
        }

        public bool IsNumer(char ch)
        {
            return ch > 47 && ch < 58;
        }

    }

  

原文地址:https://www.cnblogs.com/363546828/p/8757222.html