表达式计算 - 逆波兰式转换及运算示例

自定义表达式解析,涉及到三个主要步骤:
1.关键字析取
2.中序表达式转逆波兰表达式
3.逆波兰表达式运算。
下面给出一个示例,整个编码过程,在支持运算符有限的情况下,大约一天即可完成(C#实现),这个实现中涉及到的比较好的实现方式有两点:
1.我们生成了一个逆波兰式的中间结果,这个结果是对象化的。
2.支持中序表达式中函数的析取和逆波兰式运算时的函数扩展。

首先是调用代码:

        //表达式运算示例
        private void button1_Click(object sender, EventArgs e)
        {
            List<rpn.rpngenerator.op></rpn.rpngenerator.op> ops = rpn.RpnGenerator.GetCommonOps();
            List<rpn.rpngenerator.item></rpn.rpngenerator.item> mn = rpn.RpnAnalyser.GetMn(this.textBox1.Text, ref ops);
            List<rpn.rpngenerator.item></rpn.rpngenerator.item> rpn1 = rpn.RpnGenerator.GetRpnFromMn(mn);

            String s = "";
            foreach (rpn.RpnGenerator.ITEM i in rpn1)
            {
                s += i.value;
                s += " ";
            }
            this.textBox2.Text = s;

            MyRpnCalc rc = new MyRpnCalc();
            textBox3.Text = rc.Calc(rpn1).value;
        }

        //逆波兰运算重载
        class MyRpnCalc : rpn.RpnCalc
        {
            public override RpnGenerator.Data CalcOp(RpnGenerator.Op op, ref List<rpngenerator.data></rpngenerator.data> result)
            {
                RpnGenerator.Data d = new RpnGenerator.Data("");
                switch (op.value)
                {
                    case "or":
                        {
                            RpnGenerator.Data rhs2 = result.Last();
                            result.RemoveAt(result.Count - 1);
                            RpnGenerator.Data rhs1 = result.Last();
                            result.RemoveAt(result.Count - 1);

                            bool l1;
                            bool l2;
                            l1 = bool.Parse(rhs1.value);
                            l2 = bool.Parse(rhs2.value);
                            d.value = (l1 || l2).ToString();
                        }
                        break;
                    default:
                        return base.CalcOp(op, ref result);
                }

                return d;
            }
        }
    }

上面的代码中处理了函数的解析,所以涉及到一个重载函数的定义,其中“or(x,y)”即是一个扩展出的自定义函数,接下来是主体部分:

/* 
 * rpn.cs
 *
 * 逆波兰表达式运算辅助函数族。本实现仅对逻辑和比较运算符进行解析,仅供参考。
 *
 * 内含:
 * 1. 表达式析取(包含函数的自动解析、空白字符处理)
 * 2. 中序表达式转逆波兰表达式
 * 3. 部分逻辑运算的实现
 *
 * last edition: Aug28,2017
 * first edition: Aug25,2017
 * author: fengxh
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace rpn
{
    /// <summary>
    /// 表达式析取
    /// </summary>
    public class RpnAnalyser
    {
        /// <summary>
        /// 完整功能的表达式析取函数
        /// </summary>
        /// 待解析的中序表达式<param></param>
        /// 运算符集合,不应包含函数<param></param>
        /// <returns>可供逆波兰转换的表达式</returns>
        public static List<rpngenerator.item></rpngenerator.item> GetMn(String s, ref List<rpngenerator.op></rpngenerator.op> ops)
        {
            List<rpngenerator.item></rpngenerator.item> l = new List<rpngenerator.item></rpngenerator.item>();
            string cur = "";
            int leftMatchCnt = 0;
            int rightMatchLength = 0;

            while (s.Length != 0)
            {
                cur += s[0];
                s = s.Substring(1);
             RECHECK:
                rightMatchLength = 0;
                int oldLeftMatchCnt = leftMatchCnt;
                leftMatchCnt = 0;
                foreach (RpnGenerator.Op op in ops)
                {
                    if (op.value.Length &gt;= cur.Length && op.value.Substring(0, cur.Length) == cur) leftMatchCnt++;
                    if (cur.Length &gt;= op.value.Length)
                    {
                        if (cur.Substring(cur.Length - op.value.Length, op.value.Length) == op.value)
                        {
                            rightMatchLength = op.value.Length;
                        }
                    }
                }
                if (leftMatchCnt == 1)
                {
                    foreach (RpnGenerator.Op op in ops)
                    {
                        if (op.value == cur)
                        {
                            if (op.value == "(")
                            {
                                if (l.Count &gt; 0 && (l.Last().GetType() != typeof(RpnGenerator.Op)))
                                {
                                    RpnGenerator.Op o = new RpnGenerator.Op(l.Last().value, -1, 99);
                                    l.RemoveAt(l.Count() - 1);
                                    l.Add(o);
                                    ops.Add((RpnGenerator.Op)o.Clone());
                                }
                            }

                            l.Add((RpnGenerator.Op)op.Clone());
                            leftMatchCnt = 0;
                            break;
                        }
                    }
                    if (leftMatchCnt == 0)
                    {
                        cur = "";
                    }
                    leftMatchCnt = 0;
                }
                else if (rightMatchLength &gt; 0 && leftMatchCnt == 0 && oldLeftMatchCnt == 0)
                {
                    RpnGenerator.Data d = new RpnGenerator.Data(cur.Substring(0, cur.Length - rightMatchLength));
                    cur = cur.Substring(d.value.Length, cur.Length - d.value.Length);
                    d.value = d.value.Trim();
                    if (d.value.Length &gt; 0)
                    {
                        l.Add(d);
                    }
                    leftMatchCnt = 0;
                    if (cur.Length &gt; 0) goto RECHECK;
                }
                else if (oldLeftMatchCnt &gt; 0 && leftMatchCnt == 0)
                {
                    foreach (RpnGenerator.Op op in ops)
                    {
                        if (op.value.Length == cur.Length - 1 && cur.Substring(0, op.value.Length) == op.value)
                        {
                            l.Add((RpnGenerator.Op)op.Clone());
                            cur = cur.Substring(op.value.Length, cur.Length - op.value.Length);

                            leftMatchCnt = 0;
                            goto RECHECK;
                        }
                    }
                }
            }

            if (cur.Length != 0)
            {
                RpnGenerator.Data d = new RpnGenerator.Data(cur.Trim());
                if (d.value.Length &gt; 0)
                {
                    l.Add(d);
                }
            }

            return l;
        }
    }
    /// <summary>
    /// 中序-&gt;逆波兰转换
    /// 本模块的输入是结构化处理过的表达式,其基本元素是RpnGenerator.ITEM
    /// </summary>
    public class RpnGenerator
    {
        /// <summary>
        /// 表达式基本元素
        /// </summary>
        public class ITEM
        {
            public string value;
            public ITEM(string value)
            {
                this.value = value;
            }
        }

        /// <summary>
        /// 操作数
        /// </summary>
        public class Data : ITEM
        {
            public Data(string value)
                : base(value)
            {
            }
        }

        /// <summary>
        /// 运算符
        /// </summary>
        public class Op : ITEM, ICloneable
        {
            public Op(string value)
                : base(value)
            {
                this.cntOfData = 0;
                this.priority = 0;
            }
            public Op(string value, int cntOfData, int priority)
                :base (value)
            {
                this.cntOfData = cntOfData;
                this.priority = priority;
            }

            public Object Clone()
            {
                return new Op(this.value, this.cntOfData, this.priority);
            }

            bool isOperator1() { return cntOfData == 1; }
            bool isOperator2() { return cntOfData == 2; }
            bool isFunction() { return cntOfData == -1; }
            public int cntOfData;
            public int priority;
        }

        /// <summary>
        /// 返回内置运算符集合
        /// </summary>
        /// <returns>内置运算符集合</returns>
        public static List<op></op> GetCommonOps()
        {
            List<op></op> l = new List<op></op>();
            l.AddRange(new Op[] {
                Op_equal,
                //Op_lastOp,
                Op_leftBracket,
                Op_logic_and,
                Op_comma,
                Op_greater,
                Op_greaterOrEqual,
                Op_isEqual,
                Op_less,
                Op_lessOrEqual,
                Op_logic_not,
                Op_notEqual,
                Op_logic_or,
                Op_RightBracket
            });

            return l;
        }

        static public Op Op_lastOp = new Op("#");
        static public Op Op_leftBracket = new Op("(");
        static public Op Op_RightBracket = new Op(")");
        static public Op Op_equal = new Op("=", 2, 10);
        static public Op Op_logic_or = new Op("||", 2, 15);
        static public Op Op_logic_and = new Op("&&", 2, 15);
        static public Op Op_greater = new Op("&gt;", 2, 16);
        static public Op Op_greaterOrEqual = new Op("&gt;=", 2, 16);
        static public Op Op_less = new Op("&lt;", 2, 16);
        static public Op Op_lessOrEqual = new Op("&lt;=", 2, 16);
        static public Op Op_logic_not = new Op("!", 1, 17);
        static public Op Op_isEqual = new Op("==", 2, 20);
        static public Op Op_notEqual = new Op("!=", 2, 20);
        static public Op Op_comma = new Op(",",0, 1);


        /// <summary>
        /// 中序表达式转逆波兰表达式
        /// </summary>
        /// 中序表达式<param></param>
        /// <returns>逆波兰表达式</returns>
        static public List<item></item> GetRpnFromMn(List<item></item> input)
        {
            Stack<op></op> S1 = new Stack<op></op>();
            List<item></item> S2 = new List<item></item>();

            S1.Push(Op_lastOp);

            foreach (ITEM i in input)
            {
                if (i.GetType() == typeof(Data))
                {
                    S2.Add(i);
                }
                if (i.GetType() == typeof(Op))
                {
                    Op io = (Op)i;
                    if (io.value == "(")
                    {
                        S1.Push(io);
                    }
                    else if (io.value == ")")
                    {
                        while (S1.Peek().value != "(") S2.Add(S1.Pop());
                        S1.Pop();
                    }
                    else
                    {
                        if (io.priority &gt; S1.Peek().priority) S1.Push(io);
                        else
                        {
                            while (S1.Peek().priority &gt;= io.priority && !(S1.Peek().cntOfData == 1 && S1.Peek().cntOfData == io.cntOfData))
                            {
                                S2.Add(S1.Pop());
                            }
                            S1.Push(io);
                        }
                    }
                }
            }
            if (S1.Count != 1)
            {
                while (S1.Count &gt; 1) S2.Add(S1.Pop());
            }

            //clear comma
            List<item></item> S3 = new List<item></item>();
            foreach (ITEM i in S2)
            {
                if (i.value != ",") S3.Add(i);
            }
            return S3;
        }
    }

    public class RpnCalc
    {
        //运算主出口点
        public RpnGenerator.Data Calc(List<rpngenerator.item></rpngenerator.item> l)
        {
            List<rpngenerator.data></rpngenerator.data> result = new List<rpngenerator.data></rpngenerator.data>();

            while (l.Count &gt; 0)
            {
                RpnGenerator.ITEM i = l.First();
                l.RemoveAt(0);
                if (i.GetType() == typeof(RpnGenerator.Data))
                {
                    result.Add(GetData((RpnGenerator.Data)i));
                }
                else
                {
                    result.Add(CalcOp((RpnGenerator.Op)i, ref result));
                }
            }

            return result.First();
        }

        //原子表达式和函数运算,如果有额外的函数,需重载本函数
        public virtual RpnGenerator.Data CalcOp(RpnGenerator.Op op, ref List<rpngenerator.data></rpngenerator.data> result)
        {
            RpnGenerator.Data d = new RpnGenerator.Data("");

            switch (op.value)
            {
                //case RpnGenerator.Op_comma;
                case "=":  //RpnGenerator.Op_equal.value:
                    {
                        RpnGenerator.Data rhs2 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        SetData(rhs1, rhs2);
                        d.value = "true";
                    }
                    break;
                //case RpnGenerator.Op_lastOp:
                //case RpnGenerator.Op_leftBracket:
                case "&gt;": //RpnGenerator.Op_greater:
                    {
                        RpnGenerator.Data rhs2 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);

                        int l1;
                        int l2;
                        l1 = int.Parse(rhs1.value);
                        l2 = int.Parse(rhs2.value);
                        d.value = (l1 &gt; l2).ToString();
                    }
                    break;
                case "&gt;=": // RpnGenerator.Op_greaterOrEqual:
                    {
                        RpnGenerator.Data rhs2 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);

                        int l1;
                        int l2;
                        l1 = int.Parse(rhs1.value);
                        l2 = int.Parse(rhs2.value);
                        d.value = (l1 &gt;= l2).ToString();
                    }
                    break;
                case "==": //RpnGenerator.Op_isEqual:
                    {
                        RpnGenerator.Data rhs2 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        d.value = (rhs1.value.ToLower().Trim() == rhs2.value.ToLower().Trim()).ToString();
                    }
                    break;
                case "&lt;": //RpnGenerator.Op_less:
                    {
                        RpnGenerator.Data rhs2 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);

                        int l1;
                        int l2;
                        l1 = int.Parse(rhs1.value);
                        l2 = int.Parse(rhs2.value);
                        d.value = (l1 &lt; l2).ToString();
                    }
                    break;
                case "&lt;=": // RpnGenerator.Op_lessOrEqual:
                    {
                        RpnGenerator.Data rhs2 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);

                        int l1;
                        int l2;
                        l1 = int.Parse(rhs1.value);
                        l2 = int.Parse(rhs2.value);
                        d.value = (l1 &lt;= l2).ToString();
                    }
                    break;
                case "&&": //RpnGenerator.Op_logic_and:
                    {
                        RpnGenerator.Data rhs2 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);

                        bool l1;
                        bool l2;
                        l1 = bool.Parse(rhs1.value);
                        l2 = bool.Parse(rhs2.value);
                        d.value = (l1 && l2).ToString();
                    }
                    break;
                case "!": // RpnGenerator.Op_logic_not:
                    {
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);

                        bool l1;
                        l1 = bool.Parse(rhs1.value);
                        d.value = (!l1).ToString();

                    }
                    break;
                case "!=": // RpnGenerator.Op_notEqual:
                    {
                        RpnGenerator.Data rhs2 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);

                        d.value = (rhs1.value.ToLower().Trim() != rhs2.value.ToLower().Trim()).ToString();
                    }
                    break;
                case "||": // RpnGenerator.Op_logic_or:
                    {
                        RpnGenerator.Data rhs2 = result.Last();
                        result.RemoveAt(result.Count - 1);
                        RpnGenerator.Data rhs1 = result.Last();
                        result.RemoveAt(result.Count - 1);

                        bool l1;
                        bool l2;
                        l1 = bool.Parse(rhs1.value);
                        l2 = bool.Parse(rhs2.value);
                        d.value = (l1 || l2).ToString();
                    }
                    break;
                default:
                    {
                        throw new Exception("未处理的运算符或函数 - " + op.value);
                    }
            }

            return d;
        }

        //取值
        public virtual RpnGenerator.Data GetData(RpnGenerator.Data d)
        {
            return d;
        }

        //赋值
        public virtual void SetData(RpnGenerator.Data lhs, RpnGenerator.Data rhs)
        {
            lhs = rhs;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是将中缀算数表达式转换逆波兰式的C++代码: ```c++ #include <iostream> #include <stack> #include <string> #include <sstream> #include <vector> using namespace std; bool is_operator(const string& token) { return token == "+" || token == "-" || token == "*" || token == "/"; } int precedence(const string& token) { if (token == "+" || token == "-") { return 1; } else if (token == "*" || token == "/") { return 2; } else { return 0; } } vector<string> infix_to_postfix(const vector<string>& infix) { stack<string> s; vector<string> postfix; for (const auto& token : infix) { if (is_operator(token)) { while (!s.empty() && is_operator(s.top()) && precedence(token) <= precedence(s.top())) { postfix.push_back(s.top()); s.pop(); } s.push(token); } else if (token == "(") { s.push(token); } else if (token == ")") { while (!s.empty() && s.top() != "(") { postfix.push_back(s.top()); s.pop(); } s.pop(); } else { postfix.push_back(token); } } while (!s.empty()) { postfix.push_back(s.top()); s.pop(); } return postfix; } int evaluate_postfix(const vector<string>& postfix) { stack<int> s; for (const auto& token : postfix) { if (is_operator(token)) { int b = s.top(); s.pop(); int a = s.top(); s.pop(); if (token == "+") { s.push(a + b); } else if (token == "-") { s.push(a - b); } else if (token == "*") { s.push(a * b); } else { s.push(a / b); } } else { stringstream ss(token); int x; ss >> x; s.push(x); } } return s.top(); } int main() { // 中缀表达式: (3+4)*5-6/2 vector<string> infix = {"(", "3", "+", "4", ")", "*", "5", "-", "6", "/", "2"}; vector<string> postfix = infix_to_postfix(infix); for (const auto& token : postfix) { cout << token << " "; } cout << endl; int result = evaluate_postfix(postfix); cout << "Result: " << result << endl; return 0; } ``` 这个代码使用了 `stack` 来实现算法,其中 `infix_to_postfix` 函数将中缀表达式转换为后缀表达式, `evaluate_postfix` 函数计算后缀表达式的值。在 `main` 函数中,我们使用了 `(3+4)*5-6/2` 这个表达式来测试我们的代码,输出结果为: ``` 3 4 + 5 * 6 2 / - Result: 29 ``` 这表明我们的代码成功地将中缀表达式转换为了后缀表达式,并正确地计算表达式的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子正

thanks, bro...

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值