Parse string with arithmetic operation [duplicate] - c#

This question already has answers here:
Is there a string math evaluator in .NET?
(18 answers)
Closed 9 years ago.
I have a string of the following type:
"23 + 323 =" or "243 - 3 ="
So the format is: number + operator + number = equal.
And I also have an int which is the answer to that question.
How can I parse the string and check if the answer is correct?
Thank You,
Miguel

Maybe using regular expressions you can do something like...
String sExpression = "23 + 323 =";
int nResult = 0;
Match oMatch = Regex.Match(#"(\d+)\s*([+-*/])\s*(\d+)(\s*=)?")
if(oMatch.Success)
{
int a = Convert.ToInt32(oMatch.Groups[1].Value);
int b = Convert.ToInt32(oMatch.Groups[3].Value);
switch(oMatch.Groups[2].Value)
{
case '+';
nResult = a + b;
break;
case '-';
nResult = a - b;
break;
case '*';
nResult = a * b;
break;
case '/';
nResult = a / b;
break;
}
}
and extend to your need.. (floats, other operators, validations, etc)

You want to split on equals then split on the operator. Then you can use some standard string processing techniques to do the operation and check it against the answer. There are probably far more efficient and/or cleaner solutions than this, this is simply the first one at my fingertips and since you didn't post any code it is what you get. Note that this also is not flexible. It only works when there are two operands and with the four primary arithmetic operators. Unless there's some requirement saying you don't use third party libraries I'd recommend using something like what's linked to in the comments. If you need to implement this in a more general sense (works with multiple operations like (x + y - z) * x ) then you have a lot more work cut out for you.
string input = "23 + 323 = 346";
string[] sides = input.Split('=');
string[] operands;
int answer = 0;
if (sides.Length == 2)
{
if (sides[0].Contains('+'))
{
operands = sides[0].Split('+');
operands[0].Trim();
operands[1].Trim();
answer = int.Parse(operands[0]) + int.Parse(operands[1]);
// note if you're serious about error handling use tryparse to ensure the values are integers
if (answer != int.Parse(sides[1].Trim()))
// answer is wrong
}
else if (sides[0].Contains('-'))
{
// same logic
}
}
else
//input formatting error

As all of the comments to your question indicate, you need some kind of tokenizer, expression parser, and expression evaluator.
The tokenizer splits the source string into separate tokens, like numbers and operators.
The expression parser scans and syntactically parses the sequence of tokens, recognizing expressions and building some kind of parse tree (i.e., an abstract expression tree).
The expression evaluator then walks the nodes of the resulting expression tree, evaluating the binary and unary subexpressions. The result is the evaluation of the top-most node in the tree.
This is all quite a complex set of things to do, so (like the other comments state), you should try to find a library that someone has already written to do all this for you.

Actually it is not that different from parsing single arithmetic expression. Here you simply evaluate two of them (on both sides of equal sign) and then check the outcome.
Well, you can go "crazy", and parse not only = but >, >= too, which will give you more flexibility.
Because in arithmetic expression parenthesis should be legal (common sense), for example (5+2)*3 you should avoid struggle with regexes and alike approaches and go with parser.
Pick one you feel comfortable with, GOLD, ANTLR, Cocoa. My own parser (generator) -- NLT -- contains already arithmetic expression example. Add single rule for checking equality and you are ready to go.

Related

regex split on comma but not inside ANY parentheses with recursion in mind

I have an example string:
string myString = "value,value,(value,(value, value, value, (value), value),value)";
The goal is to iterate through it and deserialize it into a hierarchy of class objects.
The reason why most other examples asking a similar question on here will not work is due to the recursion, looking ahead (or back) for even number of parentheses will not work.
I have considered storing it as JSON, but the object types of value will vary without notice and that has proved to confused even json.net in the past especially since the types will likely all be related by inheritance.
So, given the example string, the goal is to split on comma ",", but ignore everything in parentheses until my recursion loop digs into that sub set then uses the same regex to split its contents.
I have no code yet as I am still brainstorming this method.
Also note that the sub lists may not necessarily be the last element in the parent list as demonstrated by a couple lingering value's in my example at the end.
Please do not mark as duplicate without fully reading the question and understanding why it is NOT the same as questions like this
Although C# regular expression has a feature that lets you match recursively parenthesized groups (see this Q&A for an example) it is much easier to define such regex for the positive case (i.e. "match a word or an entire parenthesized group") vs. the negative case needed for the split (i.e. "match the comma unless it is inside a parenthesized group").
Moreover, in situations when you would like to apply the same regex recursively, there is an advantage to building a simple Recursive Descent Parser.
At the heart of the parser would be the split logic that counts parentheses while searching for commas, and splits when parentheses level is zero:
var parts = new List<string>();
var parenLevel = 0;
var lastPos = 0;
for (var i = 0 ; i != s.Length ; i++) {
switch (s[i]) {
case '(':
parenLevel++;
break;
case ')':
parenLevel--;
if (parenLevel < 0) {
throw new ArgumentException();
}
break;
case ',':
if (parenLevel == 0) {
parts.Add(s.Substring(lastPos, i-lastPos));
lastPos = i + 1;
}
break;
}
}
if (lastPos != s.Length) {
parts.Add(s.Substring(lastPos, s.Length - lastPos));
}
Demo.

String evaluation in IF condition

Lets say i have
int a = 1;
int b = 2;
string exp = "b > a";
and i want to evaluate the string expression with those variables
if(exp.SomeKindOfParseOrCast())
{
//here be magic
}
Is it possible in any simple way?
Nope, not in C# - these are parameter names, and thus are compile time values, and this expression parsing you are describing is done in runtime - the computer doesn't know the name of the parameters while it's being evaluated. Instead, you could do something a little more strict, like an expression parser - implement your own way to parse string expressions.
Very very simplified:
if(exp.Equals("b > a"))
{
if(b>a)
// do what you do if b is bigger than a
else
// do what you do with a wrong expression
}
else if (exp.Equals("a > b")
{
if(a>b)
// do what you do if a is bigger than b
else
// do what you do with a wrong expression
}
else if (exp.Equals("a = b")
{
if(a==b)
// do what you do if a is equal to b
else
// do what you do with a wrong expression
}
else
// do what you do with a badly formatted expression
if you would like to take this a step forward, you can cut spaces, make sure the expression is lowercase, etc. - there's many examples around, I personally like this one.
Is it possible in any simple way?
No, in C# this is not possible in a simple way like it were in languages such as JavaScript with its eval function. Anyway, you'd have to provide bindings of in-expression parameters to actual values.
You can use Roslyn.
Here is an example of how to compile and run your own code in runtime.
Disclaimer: I'm the owner of the project Eval Expression.NET
This library is very easy to use and allow to evaluate and compile almost all the C# language.
// For single evaluation
var value1 = Eval.Execute<bool>("b > a", new { a = 1, b = 2 });
// For many evaluation
var compiled = Eval.Compile<Func<int, int, bool>>("b > a", "a", "b");
var value2 = compiled(1, 2);

Negative value in string based C# Calculator

I'm relatively new to programming, and I'm currently working on a C# string based calculator. A lot of it works fine already, but I'm having problems with negative coefficients. My calculator engine always looks for the next operator and calculates accordingly, so the problem is that if I want to calculate "-5+6", the first operation is "-5", but it obviously can't be calculated. How can I separate operator and coefficient?
What I've come up with so far (small extract of the whole code)
if (nextOperation.Contains("+"))
{
string firstOperationResult = Calculate(nextOperation.Split('+').ToList(), "+")[0];
string partialFormulaReplacement = partialFormula.Replace(nextOperation, firstOperationResult);
return CalculateDashOperation(partialFormulaReplacement);
}
else if (nextOperation.Contains("-") && nextOperation.IndexOf("-") > 0)
{
string resultOfFirstOperation = Calculate(nextOperation.Split('-').ToList(), "-")[0];
string partialFormulaReplacement = partialFormula.Replace(nextOperation, resultOfFirstOperation);
return CalculateDashOperation(partialFormulaReplacement);
}
//added
else if (nextOperation.Contains("-") && nextOperation.IndexOf("-") == 0)
{
//what to do
}
//added
return partialFormula;
"-5" can be treated as meaning "0-5", so you could say there's an implicit zero if you see an operand in the first position of the string. Note that this approach will only work for the operators + and -.
As for the problem of attempting to calculate "-5" again, I suggest you use the 0 as an argument to your Calculate function, rather than prepending it to the string you're processing:
Calculate(new List<string>{"0", nextOperation[1]}, "-")
Also, as has been pointed out in the comments, this approach will not cover all possible cases, and if this isn't an academic exercise then there are solutions out there that already solve this problem.
The sample code looks a little short. But let's try to suggest:
nextOperation is a string containing something like "1 * -6 + 6"
In order to evaluate this expression yout have to 'encrypt' your string first.
The topic you are looking for is parenthesis
A nice explanation of the basic (in python) can be found here.
But this question is already answered here.
Use NCalc Library:
Dont reinvent wheel, * and / priorities is already implemented.
Simple expressions
Expression e = new Expression("2 + 3 * 5");
Debug.Assert(17 == e.Evaluate());
Handles mathematical functional from System.Math
Debug.Assert(0 == new Expression("Sin(0)").Evaluate());
Debug.Assert(2 == new Expression("Sqrt(4)").Evaluate());
Debug.Assert(0 == new Expression("Tan(0)").Evaluate());

How to Interpret pseudocode in c#?

I have a data interpretation algorithm & actual data. Using this algorithm, I have to interpret the actual data and display it as a report.
For this, Firstly I need to create a form which will accept some variable values from user. The variables are defined in pseudocode as below. (one example given)
AGEYEARS {
Description: Age in Years
Type: Range;
MinVal: 0;
MaxVal: 124;
Default: 0;
ErrorAction: ERT1:=04 GRT4:=960Z;
}
I have several variables like this in my Variables.txt file. I don't wish to use StreamReader, read it line by ine & interpret the variables.
Instead, I am looking for some logic, which can read XXXX { } as one object and Type:Range as Attribute:Value. This way, I can skip one step of reading the file and converting it to a understandable code.
Like this, I also have other files which has conditions to check. For ex,
IF SEX = '9' THEN
SEX:=U
ENDIF
Is there any way to interpret them easily and faster? Can someone help me with it?
I am using C# as my programming language.
So you need a parser for a DSL.
I can advise you ANTLR, which will let you build a grammar easily.
Here's a totally untested simple grammar for it:
grammar ConfigFile;
file: object+;
object: ID '{' property+ '}';
property: ID ':' value ';';
value: (ID|CHAR)+;
ID: [a-zA-Z][a-zA-Z0-9_]*;
WS: [ \t\r\n]+ -> channel(HIDDEN);
CHAR: .;
Alternate solution: You also could use regex:
(?<id>\w+)\s*\{\s*(?:(?<prop>\w+)\s*:\s*(?<value>.+?)\s*;\s*)*\}
Then extract the captured information. For each match, you'll have a group id with the name of the object. The groups prop and value will have multiple captures, each pair defining a property.
In C#:
var text = #"
AGEYEARS {
Description: Age in Years;
Type: Range;
MinVal: 0;
MaxVal: 124;
Default: 0;
ErrorAction: ERT1:=04 GRT4:=960Z;
}
OTHER {
Foo: Bar;
Bar: Baz;
}";
var re = new Regex(#"(?<id>\w+)\s*\{\s*(?:(?<prop>\w+)\s*:\s*(?<value>.+?)\s*;\s*)*\}");
foreach (Match match in re.Matches(text))
{
Console.WriteLine("Object {0}:", match.Groups["id"].Value);
var properties = match.Groups["prop"].Captures.Cast<Capture>();
var values = match.Groups["value"].Captures.Cast<Capture>();
foreach (var property in properties.Zip(values, (prop, value) => new {name = prop.Value, value = value.Value}))
{
Console.WriteLine(" {0} = {1}", property.name, property.value);
}
Console.WriteLine();
}
This solution is not as "pretty" as the parser one, but works without any external lib.
I advice you against using regular expressions. Maybe it will work at start, but if your task will become a bit more complex it might be the case regex won't solve your problem, because it technically cannot do this.
The better choice (for the price of adding library) is using some parser. For C# there might not be as many as for other languages, but there are enough -- just take your pick :-). You have Irony, Coco/R, GOLD, ANTLR, LLLPG, Sprache, or my NLT.
If you sense that you will have mathematical precedence issues (i.e. you will have to work with evaluating of expressions like "5+5*2" which should give 15, not 20) than compare top-down parsers -- ANLTR is one of them -- syntax first against bottom-up parsers -- NLT for example. Usually in the first ones you have to write rules in quirky order (you have to embed the rules) while in the latter ones you have just to set the order of them (stating * goes before +). In other words, rules are separated from precedence.

Multiple variables in switch statement in c

How to write following statement in c using switch statement in c
int i = 10;
int j = 20;
if (i == 10 && j == 20)
{
Mymethod();
}
else if (i == 100 && j == 200)
{
Yourmethod();
}
else if (i == 1000 || j == 2000) // OR
{
Anymethod();
}
EDIT:
I have changed the last case from 'and' to 'or' later. So I appologise from people who answered my question before this edit.
This scenario is for example, I just wanted to know that is it possible or not. I have google this and found it is not possible but I trust gurus on stackoverflow more.
Thanks
You're pressing for answers that will unnaturally force this code into a switch - that's not the right approach in C, C++ or C# for the problem you've described. Live with the if statements, as using a switch in this instance leads to less readable code and the possibility that a slip-up will introduce a bug.
There are languages that will evaluate a switch statement syntax similar to a sequence of if statements, but C, C++, and C# aren't among them.
After Jon Skeet's comment that it can be "interesting to try to make it work", I'm going to go against my initial judgment and play along because it's certainly true that one can learn by trying alternatives to see where they work and where they don't work. Hopefully I won't end up muddling things more than I should...
The targets for a switch statement in the languages under consideration need to be constants - they aren't expressions that are evaluated at runtime. However, you can potentially get a behavior similar to what you're looking for if you can map the conditions that you want to have as switch targets to a hash function that will produce a perfect hash the matches up to the conditions. If that can be done, you can call the hash function and switch on the value it produces.
The C# compiler does something similar to this automatically for you when you want to switch on a string value. In C, I've manually done something similar when I want to switch on a string. I place the target strings in a table along with enumerations that are used to identify the strings, and I switch on the enum:
char* cmdString = "copystuff"; // a string with a command identifier,
// maybe obtained from console input
StrLookupValueStruct CmdStringTable[] = {
{ "liststuff", CMD_LIST },
{ "docalcs", CMD_CALC },
{ "copystuff", CMD_COPY },
{ "delete", CMD_DELETE },
{ NULL, CMD_UNKNOWN },
};
int cmdId = strLookupValue( cmdString, CmdStringTable); // transform the string
// into an enum
switch (cmdId) {
case CMD_LIST:
doList();
break;
case CMD_CALC:
doCalc();
break;
case CMD_COPY:
doCopy();
break;
// etc...
}
Instead of having to use a sequence of if statements:
if (strcmp( cmdString, "liststuff") == 0) {
doList();
}
else if (strcmp( cmdString, "docalcs") == 0) {
doCalc();
}
else if (strcmp( cmdString, "copystuff") == 0) {
doCopy();
}
// etc....
As an aside, for the string to function mapping here I personally find the table lookup/switch statement combination to be a bit more readable, but I imagine there are people who might prefer the more direct approach of the if sequence.
The set of expressions you have in your question don't look particularly simple to transform into a hash - your hash function would almost certainly end up being a sequence of if statements - you would have basically just moved the construct somewhere else. Jon Skeet's original answer was essentially to turn your expressions into a hash, but when the or operation got thrown into the mix of one of the tests, the hash function broke down.
In general you can't. What you are doing already is fine, although you might want to add an else clause at the end to catch unexpected inputs.
In your specific example it seems that j is often twice the value of i. If that is a general rule you could try to take advantage of that by doing something like this instead:
if (i * 2 == j) /* Watch out for overflow here if i could be large! */
{
switch (i)
{
case 10:
// ...
break;
case 100:
// ...
break;
// ...
}
}
(Removed original answer: I'd missed the fact that the condition was an "OR" rather than an "AND". EDIT: Ah, because apparently it wasn't to start with.)
You could still theoretically use something like my original code (combining two 32-bit integers into one 64-bit integer and switching on that), although there would be 2^33 case statements covering the last condition. I doubt that any compiler would actually make it through such code :)
But basically, no: use the if/else structure instead.

Categories

Resources