问题
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 ?
回答1:
I'd suggest you to use CodeDom as it can perfectly do validation:
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..
回答2:
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 is a very popular parser generator that is even used in 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.
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. Later versions of ANTLR removed this requirement.
回答3:
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
.
You can omit lexer section, and go right to parser:
expr -> "abs" "(" e:expr ")" // pattern
{ Math.Abs(e) }; // action
assuming expr
is already defined with sum, subtraction, and so on.
For curious soul -- not "abs("
because in such case as abs ( 5 )
would give error (invalid expression).
来源:https://stackoverflow.com/questions/20422853/validating-a-string-mathematical-expression