我需要评估一个在C#中作为字符串呈现给我的数学表达式.示例noddy但是得到了字符串作为表达式的点.
我需要求值然后填充一个int.
C#中没有Eval(),就像其他langugaes一样......
String myString = "3*4";
编辑:
我在VS2008上
试过Microsoft.JScript.=已弃用的方法(但仍然符合 - 警告)
但是,我已经使用的Microsoft.JScript DLL工作了
public object InvokeMember(string name,BindingFlags invokeAttr,Binder binder,object target,object [] args);
抱怨缺少";" 去搞清楚...
编辑2
解决方案 - 是codeDom之一 - 因为没有安全问题,所以它工作 - 只有我才能运行代码.非常感谢回复......
和新龙书的链接真棒
编辑3
Matt dataTable.Compute()也有效 - 对于安全意识更好.(注明参数检查)
所有其他答案都可能过度杀伤.
如果您只需要简单的算术运算,请执行此操作.
DataTable dummy = new DataTable(); Console.WriteLine(dummy.Compute("15 / 3",string.Empty));
编辑:更多信息.查看MSDN文档以Expression
获取System.Data.DataColumn
该类的属性."表达式语法"中的内容概述了除算术运算符外还可以使用的命令列表.(例如,IIF,LEN等).谢谢大家投票给我的第一个答案!
我看到它的方式,你有两个选择 - 使用表达式求值程序或构建,编译和运行C#代码.
我会选择表达式评估程序库,因为您不必担心任何安全问题.也就是说,您可能无法在中型信任环境中使用代码生成,例如大多数共享托管服务器.
以下是生成用于计算表达式的代码的示例:http: //www.vbforums.com/showthread.php?t = 397264
几个星期前,我在C#中做了个人练习.
这是相当多的代码,并且在某些地方评论很差.但它确实适用于许多测试用例.
请享用!
using System; using System.Collections.Generic; using System.Text.RegularExpressions; namespace StackOverflow { class Start { public static void Main(string[] args) { Evaluator ev; string variableValue, eq; Console.Write("Enter equation: "); eq = Console.ReadLine(); while (eq != "quit") { ev = new Evaluator(eq); foreach (Variable v in ev.Variables) { Console.Write(v.Name + " = "); variableValue = Console.ReadLine(); ev.SetVariable(v.Name, Convert.ToDecimal(variableValue)); } Console.WriteLine(ev.Evaluate()); Console.Write("Enter equation: "); eq = Console.ReadLine(); } } } class EvalNode { public virtual decimal Evaluate() { return decimal.Zero; } } class ValueNode : EvalNode { decimal value; public ValueNode(decimal v) { value = v; } public override decimal Evaluate() { return value; } public override string ToString() { return value.ToString(); } } class FunctionNode : EvalNode { EvalNode lhs = new ValueNode(decimal.Zero); EvalNode rhs = new ValueNode(decimal.Zero); string op = "+"; public string Op { get { return op; } set { op = value; } } internal EvalNode Rhs { get { return rhs; } set { rhs = value; } } internal EvalNode Lhs { get { return lhs; } set { lhs = value; } } public override decimal Evaluate() { decimal result = decimal.Zero; switch (op) { case "+": result = lhs.Evaluate() + rhs.Evaluate(); break; case "-": result = lhs.Evaluate() - rhs.Evaluate(); break; case "*": result = lhs.Evaluate() * rhs.Evaluate(); break; case "/": result = lhs.Evaluate() / rhs.Evaluate(); break; case "%": result = lhs.Evaluate() % rhs.Evaluate(); break; case "^": double x = Convert.ToDouble(lhs.Evaluate()); double y = Convert.ToDouble(rhs.Evaluate()); result = Convert.ToDecimal(Math.Pow(x, y)); break; case "!": result = Factorial(lhs.Evaluate()); break; } return result; } private decimal Factorial(decimal factor) { if (factor < 1) return 1; return factor * Factorial(factor - 1); } public override string ToString() { return "(" + lhs.ToString() + " " + op + " " + rhs.ToString() + ")"; } } public class Evaluator { string equation = ""; Dictionaryvariables = new Dictionary (); public string Equation { get { return equation; } set { equation = value; } } public Variable[] Variables { get { return new List (variables.Values).ToArray(); } } public void SetVariable(string name, decimal value) { if (variables.ContainsKey(name)) { Variable x = variables[name]; x.Value = value; variables[name] = x; } } public Evaluator(string equation) { this.equation = equation; SetVariables(); } public decimal Evaluate() { return Evaluate(equation, new List (variables.Values)); } public decimal Evaluate(string text) { decimal result = decimal.Zero; equation = text; EvalNode parsed; equation = equation.Replace(" ", ""); parsed = Parse(equation, "qx"); if (parsed != null) result = parsed.Evaluate(); return result; } public decimal Evaluate(string text, List variables) { foreach (Variable v in variables) { text = text.Replace(v.Name, v.Value.ToString()); } return Evaluate(text); } private static bool EquationHasVariables(string equation) { Regex letters = new Regex(@"[A-Za-z]"); return letters.IsMatch(equation); } private void SetVariables() { Regex letters = new Regex(@"([A-Za-z]+)"); Variable v; foreach (Match m in letters.Matches(equation, 0)) { v = new Variable(m.Groups[1].Value, decimal.Zero); if (!variables.ContainsKey(v.Name)) { variables.Add(v.Name, v); } } } #region Parse V2 private Dictionary parenthesesText = new Dictionary (); /* * 1. All the text in first-level parentheses is replaced with replaceText plus an index value. * (All nested parentheses are parsed in recursive calls) * 2. The simple function is parsed given the order of operations (reverse priority to * keep the order of operations correct when evaluating). * a. Addition (+), subtraction (-) -> left to right * b. Multiplication (*), division (/), modulo (%) -> left to right * c. Exponents (^) -> right to left * d. Factorials (!) -> left to right * e. No op (number, replaced parentheses) * 3. When an op is found, a two recursive calls are generated -- parsing the LHS and * parsing the RHS. * 4. An EvalNode representing the root node of the evaluations tree is returned. * * Ex. 3 + 5 (3 + 5) * 8 * + * * / \ / \ * 3 5 + 8 * / \ * 3 + 5 * 8 3 5 * + * / \ * 3 * * / \ * 5 8 */ /// /// Parses the expression and returns the root node of a tree. /// /// Equation to be parsed /// Text base that replaces text in parentheses ///private EvalNode Parse(string eq, string replaceText) { int randomKeyIndex = 0; eq = eq.Replace(" ", ""); if (eq.Length == 0) { return new ValueNode(decimal.Zero); } int leftParentIndex = -1; int rightParentIndex = -1; SetIndexes(eq, ref leftParentIndex, ref rightParentIndex); //remove extraneous outer parentheses while (leftParentIndex == 0 && rightParentIndex == eq.Length - 1) { eq = eq.Substring(1, eq.Length - 2); SetIndexes(eq, ref leftParentIndex, ref rightParentIndex); } //Pull out all expressions in parentheses replaceText = GetNextReplaceText(replaceText, randomKeyIndex); while (leftParentIndex != -1 && rightParentIndex != -1) { //replace the string with a random set of characters, stored extracted text in dictionary keyed on the random set of chars string p = eq.Substring(leftParentIndex, rightParentIndex - leftParentIndex + 1); eq = eq.Replace(p, replaceText); parenthesesText.Add(replaceText, p); leftParentIndex = 0; rightParentIndex = 0; replaceText = replaceText.Remove(replaceText.LastIndexOf(randomKeyIndex.ToString())); randomKeyIndex++; replaceText = GetNextReplaceText(replaceText, randomKeyIndex); SetIndexes(eq, ref leftParentIndex, ref rightParentIndex); } /* * Be sure to implement these operators in the function node class */ char[] ops_order0 = new char[2] { '+', '-' }; char[] ops_order1 = new char[3] { '*', '/', '%' }; char[] ops_order2 = new char[1] { '^' }; char[] ops_order3 = new char[1] { '!' }; /* * In order to evaluate nodes LTR, the right-most node must be the root node * of the tree, which is why we find the last index of LTR ops. The reverse * is the case for RTL ops. */ int order0Index = eq.LastIndexOfAny(ops_order0); if (order0Index > -1) { return CreateFunctionNode(eq, order0Index, replaceText + "0"); } int order1Index = eq.LastIndexOfAny(ops_order1); if (order1Index > -1) { return CreateFunctionNode(eq, order1Index, replaceText + "0"); } int order2Index = eq.IndexOfAny(ops_order2); if (order2Index > -1) { return CreateFunctionNode(eq, order2Index, replaceText + "0"); } int order3Index = eq.LastIndexOfAny(ops_order3); if (order3Index > -1) { return CreateFunctionNode(eq, order3Index, replaceText + "0"); } //no operators... eq = eq.Replace("(", ""); eq = eq.Replace(")", ""); if (char.IsLetter(eq[0])) { return Parse(parenthesesText[eq], replaceText + "0"); } return new ValueNode(decimal.Parse(eq)); } private string GetNextReplaceText(string replaceText, int randomKeyIndex) { while (parenthesesText.ContainsKey(replaceText)) { replaceText = replaceText + randomKeyIndex.ToString(); } return replaceText; } private EvalNode CreateFunctionNode(string eq, int index, string randomKey) { FunctionNode func = new FunctionNode(); func.Op = eq[index].ToString(); func.Lhs = Parse(eq.Substring(0, index), randomKey); func.Rhs = Parse(eq.Substring(index + 1), randomKey); return func; } #endregion /// /// Find the first set of parentheses /// /// /// /// private static void SetIndexes(string eq, ref int leftParentIndex, ref int rightParentIndex) { leftParentIndex = eq.IndexOf('('); rightParentIndex = eq.IndexOf(')'); int tempIndex = eq.IndexOf('(', leftParentIndex + 1); while (tempIndex != -1 && tempIndex < rightParentIndex) { rightParentIndex = eq.IndexOf(')', rightParentIndex + 1); tempIndex = eq.IndexOf('(', tempIndex + 1); } } } public struct Variable { public string Name; public decimal Value; public Variable(string n, decimal v) { Name = n; Value = v; } } }