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

 更新时间:2021年04月12日 09:12:26   作者:五维思考  
这篇文章主要介绍了C# 实现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(字符串表达式)的资料请关注脚本之家其它相关文章!

相关文章

  • C#中的yield关键字的使用方法介绍

    C#中的yield关键字的使用方法介绍

    yield这个关键字是和迭代器挂钩的,而且是与return一起以yield return的形式合用的,用来返回迭代器中的条目。
    2013-04-04
  • VS2015 C#生成dll文件的方法(32/64)

    VS2015 C#生成dll文件的方法(32/64)

    这篇文章主要介绍了VS2015 C#生成dll文件的方法(32/64),需要的朋友可以参考下
    2016-12-12
  • C#调用SQL Server中有参数的存储过程

    C#调用SQL Server中有参数的存储过程

    这篇文章介绍了C#调用SQL Server中有参数存储过程的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • C#泛型Dictionary的用法实例详解

    C#泛型Dictionary的用法实例详解

    这篇文章主要介绍了C#泛型Dictionary的用法,并以实例的形式讲述了对键值对的填充、移除及遍历等操作,需要的朋友可以参考下
    2014-09-09
  • Unity3d实现Flappy Bird游戏

    Unity3d实现Flappy Bird游戏

    这篇文章主要为大家详细介绍了Unity3d实现Flappy Bird游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • WinForm实现窗体最大化并遮盖任务栏的方法

    WinForm实现窗体最大化并遮盖任务栏的方法

    这篇文章主要介绍了WinForm实现窗体最大化并遮盖任务栏的方法,涉及C#实现WinForm窗体全屏显示的实现及调用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • C#8.0新语法using declaration

    C#8.0新语法using declaration

    这篇文章介绍了C#8.0的新语法using declaration,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • C#实现循环发送电脑屏幕截图

    C#实现循环发送电脑屏幕截图

    这篇文章主要为大家详细介绍了C#实现循环发送电脑屏幕截图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • C#实现对字符串中特定词出现次数的计数过程

    C#实现对字符串中特定词出现次数的计数过程

    LINQ(Language-Integrated Query)是C#和VB.NET中强大的查询语言,它可以用来查询集合、SQL数据库、XML文档等,在C#中,我们可以使用LINQ来简化对字符串中特定单词出现次数的计数过程,需要的朋友可以参考下
    2024-08-08
  • macOS系统下Vscode的python配置教程

    macOS系统下Vscode的python配置教程

    这篇文章主要介绍了macOS系统下Vscode的python配置教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04

最新评论