当前位置 : 主页 > 网络编程 > c#编程 >

C# 实现Eval(字符串表达式)的三种方法

来源:互联网 收集:自由互联 发布时间:2021-05-09
一、背景 假如给定一个字符串表达式 "-12 * ( - 2.2 + 7.7 ) - 44 * 2" ,让你计算结果,熟悉JavaScript的都知道有个 Eval 函数可以直接进行计算,而C#中却没有这个函数,下面提供三种实现方式

一、背景

假如给定一个字符串表达式"-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; \n");
            code.Append("namespace ADOGuy { \n");
            code.Append(" public class _Evaluator { \n");
            code.Append(" public object __foo() ");
            code.Append("{ ");
            code.AppendFormat(" return ({0}); ", Expression);
            code.Append("}\n");
            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

以上就是C# 实现Eval(字符串表达式)的三种方法的详细内容,更多关于C# 实现Eval(字符串表达式)的资料请关注自由互联其它相关文章!

网友评论