简体   繁体   English

验证字符串数学表达式

[英]Validating a string mathematical expression

Guys I am working on a system that evaluates string mathematical expression. 伙计们,我正在研究一个评估字符串数学表达式的系统。

my class to carry out the calculation 我班进行计算

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;
}

And my calling codes. 还有我的电话代码。

Double Finalstat = calculator.Calculate(UserQuery); 

Till now my expression were as 直到现在我的表情是

4 + 5 + 69 * (100*3)

However during testing I found that the expression may also be distorted(as it is user built). 但是在测试过程中,我发现表达式也可能会失真(因为它是用户构建的)。 To things like 对于像

45+99abs - 778anv

So I wanted to know if there is a way of validating the user-built(expression) before sending it to be evaluated in the class ? 所以我想知道是否有一种方法可以在将用户构建的(表达式)发送给班级中的用户之前对其进行验证?

I'd suggest you to use CodeDom as it can perfectly do validation: 我建议您使用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"

Have to leave now, hope I didn't make mistakes (if I did, someone should correct me ^^).. till Monday.. 现在必须离开,希望我没有犯错(如果我犯了错,应该有人纠正我^^)..直到星期一。

Parsing mathematical expressions initially seems easy but becomes tricky very quickly, especially when you use regular expressions (this is a reference to your other questions). 最初解析数学表达式似乎很容易,但很快就会变得棘手,尤其是在使用正则表达式时(这是对其他问题的引用)。

It's easier to create a simple parser using ANTLR to validate and eventually execute your expressions. 使用ANTLR创建简单的解析器来验证并最终执行表达式会更容易。 ANTLR is a very popular parser generator that is even used in ASP.NET MVC. ANTLR是非常流行的解析器生成器,甚至在ASP.NET MVC中使用。

There are many dialects available and several great tutorials, but the answer to this SO question actually shows how to create a mathematical expression parser that eventually evaluates its input. 有许多可用的方言和一些很棒的教程,但是对这个SO问题的答案实际上显示了如何创建一个数学表达式解析器,该解析器最终会评估其输入。

You can check the (surprisingly small) grammar file in the answer, but the actual usage is quite simple: 您可以在答案中检查(非常小的)语法文件,但是实际用法很简单:

  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());

The question dates to 2010 when you needed java to create your parser files from the grammar. 这个问题可以追溯到2010年,当时您需要用Java从语法中创建解析器文件。 Later versions of ANTLR removed this requirement. 更高版本的ANTLR删除了此要求。

With regexes you will have a problem due to simple fact you have to validate parentheses: 使用正则表达式,由于必须验证括号这一简单事实,您将遇到问题:

abs(sin(log(...)))

You should parse the expression, not just match it against some pattern. 您应该解析表达式,而不只是将其与某种模式匹配。 Writing parser rules is also much cleaner and easier to understand. 编写解析器规则也更加简洁和易于理解。 As a bonus you will get not only validation but also evaluation of the expression. 另外,您不仅可以验证表达式,还可以评估表达式。 My suite NLT contains everything you need for C# (there is already simple calculator included), and say you would like to enhance it by adding abs . 我的NLT套件包含C#所需的一切(已经包含了简单的计算器),并且说您想通过添加abs来增强它。

You can omit lexer section, and go right to parser: 您可以省略lexer部分,然后直接进入解析器:

expr -> "abs" "(" e:expr ")"  // pattern
        { Math.Abs(e) };      // action

assuming expr is already defined with sum, subtraction, and so on. 假设expr已经用求和,减等定义。

For curious soul -- not "abs(" because in such case as abs ( 5 ) would give error (invalid expression). 对于好奇的灵魂,请不要使用"abs("因为在诸如abs ( 5 )情况下会产生错误(无效的表达式)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM