一、背景

假如给定一个字符串表达式"-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(字符串表达式)的三种方法的更多相关文章

  1. [Python]实现字符串倒序的三种方法

    a=" 1: print(a[::-1]) 2: b=list(a) b.reverse() print(''.join(b)) 3: c=len(a)-1 str_1=[] while(c ...

  2. python字符串连接的三种方法及其效率、适用场景详解

    python字符串连接的方法,一般有以下三种:方法1:直接通过加号(+)操作符连接website=& 39;python& 39;+& 39;tab& 39;+& ...

  3. ibatis SQLmap mysql模糊查询字符串拼的三种方法

    在通常情况下iBATIS的参数在sqlmap中使用#param#的形式,参数名以’#’包着,但当使用sql的LIKE语句时就发生了问题,在单引号中无法使用#param#这种形式,下面列举出了3种方法来 ...

  4. 【转】C语言中字符串输入的三种方法

    在网上看到,讲的还算详细,转过来学习一下...... ======================================================================= 使 ...

  5. Shell中字符串分割的三种方法

    问题:对于’1,2,3,4,5’这样的字符串输出采用,分隔开的1 2 3 4 5 特征:在字符串中没有空格 解决方法1: #!/bin/bash var=’1,2,3,4,5’ var=${var// ...

  6. 将字符串str1复制为字符串str2的三种方法

    1.自己编写函数,将两个字符串进行复制 #include<iostream> using namespace std; int main(){ char str1[]="I lo ...

  7. 在Java中按字节获得字符串长度的三种方法

    转载:http://www.blogjava.net/nokiaguy/archive/2010/04/11/317982.html 由于Java是基于Unicode编码的,因此,一个汉字的长度为1, ...

  8. python字符串连接的三种方法

    1.+号连接 a="hello," b="world!" c=a+b print(c) 有一点需要注意的是,字符串类型是不可变的,所以每一次应用加号连接字符串都 ...

  9. C#中去除字符串空格的三种方法

    static void Main() { //demo1 除去空格,提取出各个单词 string s = "a b c"; string[] word = s.Split(new ...

  10. c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)

    c#封装DBHelper类   public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...

随机推荐

  1. Windows Server系统 PaddleOCR失败解决方案

    因PaddleOCR引用了Opencv,在windows server 上 使用opencv出现 DLL load failed错误,发现缺失部分dll:MFPlat.dll.MF.dll.MFRea ...

  2. 基于FPGA的计算器设计---第一版

    欢迎各位朋友关注"郝旭帅电子设计团队",本篇为各位朋友介绍基于FPGA的计算器设计---第一版. 功能说明: 1. 计算器的显示屏幕为数码管. 2. 4x4矩阵键盘作为计算器的输入 ...

  3. FlexBox 行间距

    问题背景 在Flex布局方式下, 父容器约定是换行的方式, 不足以容纳一行子元素的时候, 会单独进行折行, 那么折行的行间距如何处理呢? 解决办法 通过在子Item上面设置margin-top可以模拟 ...

  4. oidc-client.js踩坑吐槽贴

    前言 前面选用了IdentityServer4做为认证授权的基础框架,感兴趣的可以看上篇<微服务下认证授权框架的探讨>,已经初步完成了authorization-code与implicit ...

  5. MySQL学习笔记-数据定义语言

    SQL-数据定义语言(DDL) 一.操作数据库 1.查询 # 查询所有数据库 show databases; # 查询当前数据库 select database(); 2.创建 create data ...

  6. jquery的全局函数 多库并存

            // jQuery的全局函数 , 也称钩子函数         // 所谓的钩子函数 是 与 其他函数绑定的函数         // 作用是 监听 函数的执行 当函数执行到某个状态时 ...

  7. 可观测性平台夜莺开源项目发布V6正式版!

    夜莺开源项目在2023.7月底发布了V6版本,这个版本开始,项目目标不止于做一款开源监控系统,而是要做一款开源可观测性平台,不过路漫漫其修远兮,初期只是把日志数据源引入并完成了基本的可视化,后续会着力 ...

  8. 神奇的JavaScript弱等价类型转换

    JavaScript语言特性 - 类型转换 JavaScript这门语言的类型系统从来没有它表面看起来的那样和善,虽然比起Java.C#等一众强类型语言,它的弱类型使用起来似乎是如此便利,但正因为它极 ...

  9. redis查询 第1个数据库,而不是默认的第0个数据库

    redis查询 第1个数据库,而不是默认的第0个数据库 spring.redis.database = 1 默认: spring.redis.database = 0 car-test:0>ge ...

  10. Pytest 失败重运行

    需安装第三方插件:pytest-rerun.pytest-rerunfailures 失败重试和失败重运行的区别 失败重试:[--reruns=1],用例执行失败后,会立即开始重试一次此用例,再执行下 ...