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(字符串表達式)的資料請關注腳本之家其它相關文章!
相關文章
macOS系統(tǒng)下Vscode的python配置教程
這篇文章主要介紹了macOS系統(tǒng)下Vscode的python配置教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04