伙计我正在研究一个评估字符串数学表达式的系统。
我的班级进行计算
public Double Calculate(string argExpression)
{
//get the user passed string
string ExpressionToEvaluate = argExpression;
//pass string in the evaluation object declaration.
Expression z = new Expression(ExpressionToEvaluate);
//command to evaluate the value of the **************string expression
var result = z.Evaluate();
Double results = Convert.ToDouble(result.ToString());
return results;
}
我的电话代码。
Double Finalstat = calculator.Calculate(UserQuery);
直到现在我的表情是
4 + 5 + 69 * (100*3)
然而,在测试期间,我发现表达式也可能会失真(因为它是用户构建的)。 对于像
这样的事情45+99abs - 778anv
所以我想知道是否有一种方法可以验证用户构建的(表达式),然后再将它发送到类中进行评估?
答案 0 :(得分:0)
我建议您使用CodeDom,因为它可以完美地进行验证:
CodeDomProvider provider = CSharpCodeProvider.CreateProvider("C#");
CompilerParameters options = new CompilerParameters();
options.GenerateExecutable = false;
options.GenerateInMemory = true;
// create code
string source = "using System;namespace Expression{public static class Expression{public static void Test() {\n";
source += expression; // your expression
source +=";}}}";
// compile
var result = provider.CompileAssemblyFromSource(options, source);
if (result.Errors.HasErrors)
foreach (CompilerError error in result.Errors)
; // use error.Column and .Row to get where error was, use .ErrorText to get actuall message, to example "Unknown variable aaa"
现在必须离开,希望我没有犯错(如果我这样做,有人应该纠正我^^)..直到星期一..
答案 1 :(得分:0)
解析数学表达式最初似乎很容易,但很快变得棘手,尤其是当你使用正则表达式时(这是对你的其他问题的引用)。
使用ANTLR创建一个简单的解析器来验证并最终执行表达式会更容易。 ANTLR是一种非常流行的解析器生成器,甚至可以在ASP.NET MVC中使用。
有许多方言和几个很棒的教程,但the answer to this SO question实际上展示了如何创建最终评估其输入的数学表达式解析器。
您可以在答案中查看(令人惊讶的小)语法文件,但实际使用情况非常简单:
string expression = "(12.5 + 56 / -7) * 0.5";
ANTLRStringStream Input = new ANTLRStringStream(expression);
ExpressionLexer Lexer = new ExpressionLexer(Input);
CommonTokenStream Tokens = new CommonTokenStream(Lexer);
ExpressionParser Parser = new ExpressionParser(Tokens);
Console.WriteLine(expression + " = " + Parser.parse());
问题可以追溯到2010年,当你需要java从语法中创建解析器文件时。更高版本的ANTLR删除了这一要求。
答案 2 :(得分:0)
使用正则表达式会导致问题,因为您必须验证括号:
abs(sin(log(...)))
你应该解析表达式,而不是仅仅将它与某些模式匹配。编写解析器规则也更清晰,更容易理解。作为奖励,您不仅可以获得验证,还可以获得表达式的评估。我的套件NLT包含了C#所需的一切(包括简单的计算器),并且您希望通过添加abs
来增强它。
你可以省略lexer部分,然后直接进入解析器:
expr -> "abs" "(" e:expr ")" // pattern
{ Math.Abs(e) }; // action
假设已使用求和,减法等定义expr
。
对于好奇的灵魂 - 不是"abs("
,因为在这种情况下abs ( 5 )
会给出错误(无效的表达)。