zoukankan      html  css  js  c++  java
  • C# 实现Eval(字符串表达式)的三种方法

    一、背景

    假如给定一个字符串表达式"-12 * ( - 2.2 + 7.7 ) - 44 * 2",让你计算结果,熟悉JavaScript的都知道有个Eval函数可以直接进行计算,而C#中却没有这个函数,下面提供三种实现方式

    二、代码

        public class Class1
        {
            #region 方法一:利用CodeCom
            [Obsolete]
            System.CodeDom.Compiler.ICodeCompiler comp = new Microsoft.CSharp.CSharpCodeProvider().CreateCompiler();
            System.CodeDom.Compiler.CompilerParameters cp = new System.CodeDom.Compiler.CompilerParameters();
            public object Eval_1(string Expression)
            {
                StringBuilder code = new StringBuilder();
                code.Append("using System; 
    ");
                code.Append("namespace ADOGuy { 
    ");
                code.Append(" public class _Evaluator { 
    ");
                code.Append(" public object __foo() ");
                code.Append("{ ");
                code.AppendFormat(" return ({0}); ", Expression);
                code.Append("}
    ");
                code.Append("} }");
                System.CodeDom.Compiler.CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString());
                System.Reflection.Assembly a = cr.CompiledAssembly;
                object _Compiled = a.CreateInstance("ADOGuy._Evaluator");
                System.Reflection.MethodInfo mi = _Compiled.GetType().GetMethod("__foo");
                return mi.Invoke(_Compiled, null);
            }
            #endregion
    
            #region 方法二:对表达式分析
            string Precede(string p, string q)
            {
                switch (p)
                {
                    case "+":
                    case "-":
                        return ("*/(".IndexOf(q) != -1) ? "<" : ">";
                    case "*":
                    case "/":
                        return (q == "(") ? "<" : ">";
                    case "(":
                        return (q == ")") ? "=" : "<";
                    case ")":
                        return (q == "(") ? "?" : ">";
                    case "#":
                        return (q == "#") ? "=" : "<";
                }
                return "?";
            }
    
            Double Operate(Double a, char o, Double b)
            {
                switch (o)
                {
                    case '+':
                        return a + b;
                    case '-':
                        return a - b;
                    case '*':
                        return a * b;
                    case '/':
                        return a / b;
                }
                return 0;
            }
    
            public Object Eval_2(string Expression)
            {
                Stack nArr = new Stack(), oArr = new Stack();
                int j = 0;
                Double a = 0, b = 0;
                string w = "";
                char o;
                MatchCollection arr = Regex.Matches(Expression.Replace(" ", "") + "#", @"(((?<=(^|())-)?d+(.d+)?|D)");
                oArr.Push('#');
                w = Convert.ToString(arr[j++]);
                while (!(w == "#" && Convert.ToString(oArr.Peek()) == "#"))
                {
                    if ("+-*/()#".IndexOf(w) != -1)
                    {
                        switch (Precede(oArr.Peek().ToString(), w))
                        {
                            case "<":
                                oArr.Push(w);
                                w = Convert.ToString(arr[j++]);
                                break;
                            case "=":
                                oArr.Pop();
                                w = Convert.ToString(arr[j++]);
                                break;
                            case ">":
                                o = Convert.ToChar(oArr.Pop());
                                b = Convert.ToDouble(nArr.Pop());
                                a = Convert.ToDouble(nArr.Pop());
                                nArr.Push(Operate(a, o, b));
                                break;
                            default:
                                return "Error";
                        }
                    }
                    else
                    {
                        nArr.Push(w);
                        w = Convert.ToString(arr[j++]);
                    }
                }
                return nArr.Pop();
            }
            #endregion
    
            #region 方法三:利用JScript的Eval
            //需要引用Microsoft.JScript
            [Obsolete]
            readonly Microsoft.JScript.Vsa.VsaEngine ve = Microsoft.JScript.Vsa.VsaEngine.CreateEngine();
    
            [Obsolete]
            public object Eval_3(string Expression)
            {
                return Microsoft.JScript.Eval.JScriptEvaluate(Expression, ve);
            }
            #endregion
        }
    

    三、测试

            static void Main(string[] args)
            {
                String strExpression = "-12 * ( - 2.2 + 7.7 ) - 44 * 2";
    
                var obj = new Class1();
                Console.WriteLine($"方法一(CodeCom法)计算结果:{obj.Eval_1(strExpression)}");
                Console.WriteLine($"方法二(分析法)计算结果:{obj.Eval_2(strExpression)}");
                Console.WriteLine($"方法三(JScript法)计算结果:{obj.Eval_3(strExpression)}");
                Console.ReadLine();
            }
    

    运行结果:
    方法一(CodeCom法)计算结果:-154
    方法二(分析法)计算结果:-154
    方法三(JScript法)计算结果:-154

  • 相关阅读:
    驱动Makefile
    ioremap
    file结构体
    Python基础-语法知识
    企业运营对 DevOps 的「傲慢与偏见」
    漂亮得不像实力派!
    如何用 OneAPM 优化你的 Node.js 应用?
    全球说:要给 OneAlert 点100个赞
    DevOps 和技术债务偿还自动化
    PHP 性能分析与实验(二)——PHP 性能的微观分析
  • 原文地址:https://www.cnblogs.com/zhaoshujie/p/13793152.html
Copyright © 2011-2022 走看看