12,954,672 members (72,419 online)
Add your own
alternative version

#### Stats

26.1K views
1.7K downloads
26 bookmarked
Posted 12 Dec 2011

# Basic mathematical expression evaluator

, 12 Dec 2011 CPOL
 Rate this:
Please Sign up or sign in to vote.
The article covers the creation process of a C# class which can be used to evaluate basic mathematical expressions

## Introduction

This article covers the creation process of a C# class which can be used to evaluate basic mathematical expressions. The evaluator will be able to understand the 4 basic arithmetic operations (+, -, *, /) and parentheses. This provides just a basic functionality, but lot of the times this can be sufficient, and it also keeps the code simple. So at the end, we will have a class which can be used to get the decimal value of a `string` expression with a simple method call.

### Structure of the Article

Please note that this is a beginners' article, at some places, it contains explanations about topics which might be new to beginners, these paragraphs are indented. If you are familiar with the topic which is shortly described there you can just skip them, but if they sound new for you I recommend further reading on the subject since these are not the subject of this article, I just included as much that is necessary to understand the problem. Also the topic, parsing a mathematical expression, can be discussed in a much more advanced level than it is done here. I hope that this article will be easy to understand for everyone, even without any special knowledge about the subject.

The article follows a tutorial layout, so if you follow every step, you will end up with the same result as included in the downloads. However the article shows the way how I solved the problem, and the steps I went through, and not necessarily the steps required to reach the same solution. What I mean is, there will be places where I will tell you to replace some previously written code for example. I know that reading things like this raises the question in you 'So why did I have to write that code on the first time?', the answer is simple: because that time that was the proper code to write. These situations will happen when we first try to put the whole thing together, but to not get lost in details we keep some things to deal with it later. I believe these make the whole article easier to follow.

The following technologies, techniques are used in the article which might be new to you, if you are quite new to C# or programming, however I hope that I can give you an introduction about these subjects and encourage you for further learning: static methods and classes, recursive algorithms, LINQ extension methods, lambda expressions.

## Background

I have to mention that there are a lot of other solutions available, here on CodeProject too, most of them give far more functionality than mine, but this usually also results in a more complex code.

I was working on a project where I had a `TextBox` on a form, to take a quantity for input, I wanted to provide the option for the user to input some simple mathematical expressions (e.g. 5*12 or 45+4*5). Since I didn't expect any complex input, and I like creating my own solutions for problems, and also I had some time to "waste" on trying (I could have still used a ready made solution if I wouldn't succeed), so I decided that I will implement an evaluator to calculate the value of the input. I found creating it interesting and fun, I thought that I will share the whole process I went through.

Finally, I created a whole new control called `NumericTextBox` relying on the class presented in this article, but it also adds some other extra functionality to a simple `TextBox` control. I wrote about it in this post.

## Using the Code

The result of this tutorial will be a `static `class called `MathsEvaluator`, with the following `public static `methods:

• `decimal Parse(string expression)`
• `bool TryParse(string expression, out decimal value)`
• `bool IsExpression(string s)`

The `Parse` method can be used to evaluate an expression, given as `string`, and get its value as a `decimal` number. It throws `ArgumentException` if the expression is not valid.

The `TryParse` method will determine if the expression provided can be evaluated and indicate this in the return value, and also give the evaluated value in an `out `parameter. It is recommended to use this method.

The `IsExpression` will indicate in its return value, whether the given expression contains only valid characters. Note that this method only checks if there aren't any illegal characters present, however this doesn't guarantee that the expression is valid.

See some example usage:

```decimal d = MathsEvaluator.Parse("(1+2)*5-12");
//returns 3

MathsEvaluator.IsExpression("5*2+b");
//returns false

MathsEvaluator.IsExpression("12,4+*");
//!returns true!

bool b = MathsEvaluator.TryParse("1+2+3+4+5*0", out d);
//returns true, d will equal 10```

## The Problem in Details

### Required Functionality

My requirements were quite simple, to end up with a method that accepts an expression of type `string` as parameter and returns the value of the expression as a `decimal`. Also since the expression origins from user input, check if it's correct, and throw exceptions if not. The operators I expected to be understood are the following: +, -, *, /, ().

### An Expression

So how does an expression look? It stands from operations. Each operation has an operator, and (in this case) 2 operands. An operand can be either a decimal number or another expression. See Figure-1 for an example.

Figure-1 The structure of an expression

So my idea was to use recursion to evaluate an expression. An expression first would be split into pieces, recursively evaluating each operand, and when we have decimal values returned by the function we can simply use the correct operator to calculate the value of the operation and return it. See Figure-2 below showing an example evaluation process.

Figure-2 The evaluation process of an expression

## Create the Project

Create a new Windows Forms Application project in Visual Studio, call it '`MathsEvaluatorDemo`', and add a `TextBox`, a `Label`, and a `Button` to the `form`, we will use these controls to test the evaluator.

Add a new Class to the project, name it `MathsEvaluator`, from now on we will work on this class, this will contain the evaluation logic. Since we won't need to instantiate this class, make it `static`, and also every method of the class will be `static`.

Create a new method in the class, call it `Parse`, it should take a `string` parameter and return a `decimal`. So far we have the following code:

```public static class MathsEvaluator
{
public static decimal Parse(string expression)
{
}
}```

For this point only go back to the `Form`, and add an event handler to the button click event to call the `Parse` method and display the result on the `label`:

```private void button1_Click(object sender, EventArgs e)
{
label1.Text = MathsEvaluator.Parse(textBox1.Text).ToString();
}```

We have set up our project, and created an empty method which will handle our evaluation process. So it's time to think about what should the `Parse` method do.

The idea is that this method will be called recursively, so there are 2 kinds of "expressions" it can get as parameter: either a number or a more complex expression (standing from operations).

## Parse a Decimal

Handling the number is easy, we just have to return it as `decimal`. So let's do this, we will use the `decimal.TryParse(string, out decimal)` method to decide if we are lucky and the expression was just a decimal value. Note that it has a `decimal out` parameter containing the parsed value, if it was able to parse, so we will just return it in this case:

```decimal d;
if (decimal.TryParse(expression, out d))
{
//The expression is a decimal number, so we are just returning it
return d;
}
else
{
}```

We can even run our first test now. Just add a `return 0;` in the `else` part (or comment out the `else` statement), because without it, it won't compile, and then run the program, enter some decimal value to the `textbox` and press the `button`, the value should appear in the `label`. This isn't a big magic, but at least we can see that what we did so far is working. Remember to remove the statement added to the `else` block for further development.

## Parse an Expression

To parse an expression, it will be a little more complicated than dealing with a number. We will have to do the following:

1. Tokenize the input `string` (split it into pieces)
2. Group the elements into operations
3. Evaluate an operation

First of all, create a new method called `CalculateValue` getting a `string` as parameter and returning `decimal`. This will take care of the evaluation of an expression, and we can keep the `Parse` method clean by calling this method, instead of writing the code there. So add the following line in the `Parse` method in the `else` block:

`return CalculateValue(expression);`

And create the new method:

```private static decimal CalculateValue(string expression)
{
}```

### Tokenizing the String

We will split the expression `string `into elements (let me explain what I mean by an element in this article: an element can be an operand (another expression or a number), or an operator) by iterating through the `string` character by character and splitting it before and after an operator is found. Note that we are not dealing with the parentheses at this point to simplify the problem.

We will need a `List` for the elements, and a `string` to store the element that we are currently reading. And also, we are defining a `char` array which will contain a list of the supported operators.

```char[] operators = {'+', '-', '*', '/'};
List<string> elements = new List<string>();
string currentElement = string.Empty;```

Now let's iterate through the `string`, and do the following:

• If the character is ' ' (space), we simply skip it
• If the character is not a space and not an operator, we add it to the end of the `currentElement string`
• If the character is an operator we reached the end of an element, so we add the `currentElement` to the list, then we add the operator itself to the list, and then we set the `currentElement` to an empty `string`, so we can collect characters for the next element.
```for (int i = 0; i < expression.Length; i++)
{
if (operators.Contains(expression[i]))
{
//The current character is an operator
elements.Add(currentElement);
elements.Add(expression[i].ToString());
currentElement = string.Empty;
}
else if (expression[i] != ' ')
{
//The current character is neither an operator nor a space
currentElement += expression[i];
}
}```

After the `for` loop, the `currentElement` might contain some characters (actually it should, to be a proper expression) which we didn't add to the list, because an operator didn't follow it, so let's add it now:

```if (currentElement.Length > 0)
{
elements.Add(currentElement);
}```

### Group Operations

We have a tokenized `string`, it's time to compose our first operation from it. We will use the content of the whole list as one operation, by selecting an operator, an operand, and the rest of the list will be the other operand.

To evaluate the operations from left to right, we take the last element to be the right hand operand, the element before it will be the operator and the rest of the list will be the left hand operand. This means that the right hand operand will be simply a decimal value, while the left can be either a decimal value (in case the input was something simple like: 2+5) or an expression. As shown in Figure-2, we call `Evaluate `(in our implementation it's `Parse`) for both of the operands, which will result in that the left operand will be tokenized and grouped again, and so on, until it will be simply a number and then we can calculate the result.

An example: If the input was `1+2+3-4`, we calculate it in the following way `(1+2+3)-(4)` => `((1+2)+(3))-4` => `(((1)+(2))+3)-4` => `(3+3)-4` => `6-4` => `2`.
The brackets here mean that the `Parse` method will be called with that expression as parameter.

To do this, define three `strings`: `oper` will be the operator, `operand1`, and `operand2` will be the two operands.

`string oper, operand1 = string.Empty, operand2;`

Take the last element from the list to `operand2`, the one before as the operator, and the rest of the list as `operand1`.

```operand2 = elements.Last();
elements.RemoveAt(elements.Count - 1);

oper = elements.Last();
elements.RemoveAt(elements.Count - 1);

while (elements.Count > 0)
{
operand1 = elements.Last() + operand1;
elements.RemoveAt(elements.Count - 1);
}```

Create a new method to evaluate an operation, call it `EvaluateOperation` which takes three `string` parameters and returns a `decimal`. As the last line in the `CalculateValue` method, call `EvaluateOperation` and `return` the value which it returns.

`return EvaluateOperation(oper, operand1, operand2);`

### Evaluate an Operation

We already called the `EvaluateOperation` method, so let's write it.

We start with a check if the operator, that the method received, is only 1 character long (we only support operators which stand from a single character), and `throw` an `ArgumentException` if not:

```private static decimal EvaluateOperation
(string oper, string operand1, string operand2)
{
if (oper.Length == 1)
{

}
else
{
throw new ArgumentException("Unsupported operator");
}
}```

The rest of the code goes in the body of the `if` statement.
Here is the place for the recursive call, which will convert the two `string` operands to `decimal` values:

```decimal op1 = Parse(operand1);
decimal op2 = Parse(operand2);```

With the decimal values of the operands, we can easily evaluate the value of the operation with a `switch case` construction, and then `return` the obtained value. In the `default` path, let's `throw` an exception indicating that other operators are not supported.

```decimal value = 0;
switch (oper[0])
{
case '+':
value = op1 + op2;
break;
case '-':
value = op1 - op2;
break;
case '*':
value = op1 * op2;
break;
case '/':
value = op1 / op2;
break;
default:
throw new ArgumentException("Unsupported operator");
}
return value;```

We got to the recursive call, and also did some real mathematical computation, sounds like we got to the end. Well, unfortunately not yet. Anyway it's a great time to test the solution, and take a break to drink a coffee/tea/beer/... whichever you prefer.

During the test, we should notice a few things:

• All operations are treated like if they would have the same precedence
• Parentheses are still not supported

## Precedences

To support different precedence levels, let's change the way in which we store the operators in the `CalculateValue` method. Change the `char array` to a `Dictionary` with a `char` key (this will be the operator) and an `int` value (this will be the precedence of the operator):

```Dictionary<char, int> operators = new Dictionary<char, int>
{
{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}
};```

A `Dictionary` is a collection of Key-Value pairs. Here we use the operators as keys, and their value is their precedence level.

I added the addition and subtraction with precedence 1, and multiplication and division with precedence 2.

To use this `Dictionary`, the evaluation process has to be changed. The new process can be summarized as the following:

1. Start with the highest level of precedence
2. Evaluate each operation which belongs to this level from left to right
3. Replace the two operands and the operator in the element list with the calculated value
4. Go to the next level
5. If there are no more levels, return the value obtained by the last evaluation call

To change the evaluation process, delete everything in the `CalculateValue` method from this line until the end of the function:

`string oper, operand1 = string.Empty, operand2;`

### The New Evaluation Process

The following code should be placed in the place of the previously removed lines in the `CalculateValue` method.

Define a `decimal` variable to store the calculated value, we will also `return` this at the end of the function, and a `for` loop from the highest precedence present in the `operators` dictionary until the lowest.

```//define a value which will be used as the return value of the function
decimal value = 0;

//loop from the highest precedence to the lowest
for (int i = operators.Values.Max(); i >= operators.Values.Min(); i--)
{

}

return value;```

Since the precedence levels for the operators are stored as values in the `Dictionary`, we used the `Max()` and `Min()` LINQ queries on the `ValueCollection` of the operators dictionary. The LINQ queries are available in the `System.Linq` namespace. Add the following to the `using `directives (if not included yet):

`using System.Linq;`

Since LINQ is probably not a beginner topic, let's see what is it:
"Language-Integrated Query (LINQ) is a set of features introduced in Visual Studio 2008 that extends powerful query capabilities to the language syntax of C# and Visual Basic. LINQ introduces standard, easily-learned patterns for querying and updating data, and the technology can be extended to support potentially any kind of data store." Source: MSDN.
The important part for us now is the following: It adds some extra functionality to data sources which implement the `IEnumerable` or `IEnumerable<T>` interface, as our collection does.

The rest of the code should be placed inside the `for` loop.

We need another loop which runs while there are any operations left from the current precedence level in the elements list. Let's use a `while` loop and first check if there are at least 3 elements in the list (an operator and the two operands), then the condition described before:

```//loop while there are any operators left
// in the list from the current precedence level
while (elements.Count >= 3
&& elements.Any(element => element.Length == 1
&& operators.Where(op => op.Value == i)
.Select(op => op.Key).Contains(element[0])))
{
}```

I used lambda expressions as parameters for the LINQ queries to perform this check, and I will explain what is happening here in detail in a moment.

But first about lambda expressions in a few words:

"A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types. All lambda expressions use the lambda operator =>, which is read as "goes to". The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block." Source: MSDN

For example, in the condition of the `while` loop above, there is a `Where` query on the operators `Dictionary`, the `Where` method waits a function as parameter to test each element for a condition, with the following type: `Func<KeyValuePair<char,int>, bool>`, which means that the parameter of the function is a `KeyValuePair` with `char Key` and `int Value` (an entry in the `operators` dictionary), and it should return a `bool` value. We provided a lambda expression as this function, so the left side of the expression should be one variable name (its type will be `KeyValuePair<char,int>`), here it is `op`. The right side in our example should be a boolean expression, which will indicate whether an element satisfies the `Where `condition and should be included in the collection returned by the `Where()` method, so we check whether the `Value` of the parameter(`op`) equals to the current precedence level(`i`), and the value of this comparison will be the returned value of this lambda expression.

Another example:

```//lambda expression
(x) => x > 5

//if it would be a function
bool foo(int x)
{
return x > 5;
}```

This was just an introduction to lambda expressions, many articles can be found on the internet covering this topic in much more detail.

I think the beginning (`elements.Count >= 3`) is clear, it's just a condition to check if there are at least 3 elements in the list.
Next we check if any of the elements satisfy the condition given in the brackets: `elements.Any(<condition>)`, this returns a `bool` value indicating whether there are any elements which satisfy the condition.
The condition is fulfilled if the element is an operator from the current precedence level. This will be a lambda expression where the parameter is the currently checked element from the `elements` list (`element`), first we check if its length is 1 (all of our operators are just 1 character, so it has to satisfy this condition), then we check if it is contained in a list made from the operator characters from the current precedence level:
To get the list of the operators where the `Value`(precedence) of the operator equals the current level(`i`), the following is performed: `operators.Where(op => op.Value == i)`. This is a `Where` condition used on the dictionary, which returns a part of the dictionary with elements which satisfy the condition in the brackets. The condition used here is a lambda expression returning a `bool` value, `true` if the `Value` of the dictionary entry equals `i` (as explained in the note). This will return a collection of `KeyValuePairs`, but we just need the list of the operators, so we perform a `Select` operation, to get a collection of `char`s, and we check if the collection contains an element which equals with the first character of the currently checked element from the elements list.

Now the body of the `while` loop.

We get the position of the operator which satisfied the `while` condition. This done again with lambda expressions, but we use almost the same query, the only difference will be that instead of the `Any` operation we use here the `FindIndex` operation, which returns the first index of the element which fulfills the given condition:

```//get the position of this element
int pos = elements
.FindIndex(element => element.Length == 1 &&
operators.Where(op => op.Value == i)
.Select(op => op.Key).Contains(element[0]));```

So now we have the index of the operator, the two operands will be the elements right before and right after this index, with these we can call the `EvaluateOperation` method:

```//evaluate it's value
value = EvaluateOperation(elements[pos],
elements[pos - 1], elements[pos + 1]);```

The next thing is to change these three elements in the `elements` list to the one value obtained. To achieve this, change the first to the new value, and delete the following two elements:

```//change the first operand of the operation
// to the calculated value of the operation
elements[pos - 1] = value.ToString();
//remove the operator and the second operand from the list
elements.RemoveRange(pos, 2);```

The evaluator is now ready to calculate the value of an expression evaluating the operations in the proper order.

Note: The whole code of the `CalculateValue` method (after some maintenance) will be included in the beginning of the next section.

## The Parentheses

To support parentheses in the expressions, we will modify the tokenizer code. First to keep things clean, move the current tokenizer code to a new method named `TokenizeExpression` returning a `List<string>` and taking a `string` (the expression) and a `Dictionary<char, int>` (the operators) as parameter. The new method should look like this:

```private static List<string> TokenizeExpression
(string expression, Dictionary<char, int> operators)
{
List<string> elements = new List<string>();
string currentElement = string.Empty;
for (int i = 0; i < expression.Length; i++)
{
if (operators.Keys.Contains(expression[i]))
{
//The current character is an operator
elements.Add(currentElement);
elements.Add(expression[i].ToString());
currentElement = string.Empty;
}
else if (expression[i] != ' ')
{
//The current character is neither an operator nor a space
currentElement += expression[i];
}
}

//Add the last element (which follows the last operation) to the list
if (currentElement.Length > 0)
{
elements.Add(currentElement);
}

return elements;
}```

And you should have a `CalculateValue` method similar to this:

```public static decimal CalculateValue(string expression)
{
//Dictionary to store the supported operations
//Key: Operation;
//Value: Precedence (higher number indicates higher precedence)
Dictionary<char, int> operators = new Dictionary<char, int>
{
{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'^', 3}
};

//Tokenize the expression
List<string> elements = TokenizeExpression(expression, operators);

//define a value which will be used as the return value of the function
decimal value = 0;

//loop from the highest precedence to the lowest
for (int i = operators.Values.Max(); i >= operators.Values.Min(); i--)
{
//loop while there are any operators left
// in the list from the current precedence level
while (elements.Count >= 3
&& elements.Any(element => element.Length == 1 &&
operators.Where(op => op.Value == i)
.Select(op => op.Key).Contains(element[0])))
{
//get the position of this element
int pos = elements
.FindIndex(element => element.Length == 1 &&
operators.Where(op => op.Value == i)
.Select(op => op.Key).Contains(element[0]));

//evaluate it's value
value = EvaluateOperation(elements[pos],
elements[pos - 1], elements[pos + 1]);
//change the first operand of the operation
// to the calculated value of the operation
elements[pos - 1] = value.ToString();
//remove the operator and the second operand from the list
elements.RemoveRange(pos, 2);
}
}

return value;
}```

Now, back to the brackets (I use the terms parentheses and brackets mixed in the article, in both cases I mean the same thing: "`()`"), and the new `TokenizeExpression` method.

### Tokenizing using a State Machine

We will change the tokenizer code to a simple state machine. It will have three states:

• 0 - normal mode
• 1 - after an opening bracket '('
• 2 - after a closing bracket ')'

See in Table-1 below the idea of the state machine:

StateNext character
operator
(+,-,*,/)
not space)(
00 / Add the collected string and the operator to the list.</th /> 0 / Copy character to the string.1 / Set bracket count to 0.
If the collected string is not empty, add it to the list, and add '*' also.
11 / Copy character to the string.If (bracket count is 0): 2 / -

Else: 1 / decrease bracket count, copy character to the string.
1 / Increase bracket count. Copy character to the string.
20 / Add the collected string and the operator to the list.0 / Add the collected string, and '*' to the list. Set the string to the new character.1 / Set bracket count to 0.
If the collected string is not empty, add it to the list, and add '*' also.

#### Table-1 The description of the state machine

A figure concentrating only on the state transitions:

Figure-3 The state transitions used by the state machine
(the empty arrow means 'Any other case')

A little explanation: The basic idea is still, that we are copying the characters to a `string `and when an operator comes, add it to the list followed by the operator, and start to collect again. You can see this in the first two cells of the first row. Then if an opening bracket comes, we will change `state` to `1`.

Inside the parentheses, we will count the number of brackets we went throw, with `+1` for opening bracket and `-1` for closing, so the closing bracket, for the opening bracket we received in `state 0`, will be the one which we get when the bracket count is `0`. In order to make this work, we set the bracket count to `0`. And the next thing is just a little extra, it makes possible to understand this for example `5(1+2)` as `5*(1+2)`. So in case we received an opening parenthesis and the collected `string `wasn't empty (so it didn't follow an operator, where we empty it), then we add the element that it contains to the list, and also the `'*'` operator.

In `state 1`, a.k.a. inside the outer most parentheses, we just simply copy every character to the `string`, and keep track of how many brackets have we seen, in order to recognize the proper closing bracket for the opening one, which took us to `state 1` (Imagine: `((((5*2)+1)-2(12/4))/2)-2 )`. If we got to the closing bracket we were looking for, then change the `state` to `2`.
Note: We could change the `state` simply to 0 and we would be ready, but the 3rd state is added to handle the following situation: `(1+2)5` or `(1+2)(2+3)`. Since we added support to omit the sign of multiplication before a parentheses expression, we should also offer the support to omit it after.

In `state 2`, if we get an operator or an opening bracket, we do the same thing as in `state 0` (We already solved the missing multiplication sign in case of an opening bracket). Any other case changes the `state` to `0 `and add the expression in the `string `to the list, and add the multiplication operator also, and because this character is the first character of the next expression, set it as the new value of the `string `which we are using to collect the next expression.

### The Implementation of the State Machine

First, let's add a variable to store the `state` in front of the `for` loop:

`int state = 0;`

Now let's add a `switch case` to the `for` loop to implement different behavior for each case. And add the code we already have in the first `case` path (`case 0: ... break;`)

```switch (state)
{
case 0:
if (operators.Keys.Contains(expression[i]))
{
//The current character is an operator
elements.Add(currentElement);
elements.Add(expression[i].ToString());
currentElement = string.Empty;
}
else if (expression[i] != ' ')
{
//The current character is neither an operator
// nor a space
currentElement += expression[i];
}
break;
case 1:
break;
case 2:
break;
}```

Change it to recognize the opening bracket:

```case 0:
if (expression[i] == '(')
{
//Change the state after an opening bracket is received
state = 1;
bracketCount = 0;
if (currentElement != string.Empty)
{
//if the currentElement is not empty,
// then assuming multiplication
elements.Add(currentElement);
elements.Add("*");
currentElement = string.Empty;
}
}
else if (operators.Keys.Contains(expression[i]))
{
//The current character is an operator
elements.Add(currentElement);
elements.Add(expression[i].ToString());
currentElement = string.Empty;
}
else if (expression[i] != ' ')
{
//The current character is neither an operator
// nor a space
currentElement += expression[i];
}
break;```

Now let's implement the `case 1`:

```case 1:
if (expression[i] == '(')
{
bracketCount++;
currentElement += expression[i];
}
else if (expression[i] == ')')
{
if (bracketCount == 0)
{
state = 2;
}
else
{
bracketCount--;
currentElement += expression[i];
}
}
else if (expression[i] != ' ')
{
//Add the character to the current element,
// omitting spaces
currentElement += expression[i];
}
break;```

And finally the `case 2`:

```case 2:
if (operators.Keys.Contains(expression[i]))
{
//The current character is an operator
state = 0;
elements.Add(currentElement);
currentElement = string.Empty;
elements.Add(expression[i].ToString());
}
else if (expression[i] != ' ')
{
elements.Add(currentElement);
elements.Add("*");
currentElement = string.Empty;

if (expression[i] == '(')
{
state = 1;
bracketCount = 0;
}
else
{
currentElement += expression[i];
state = 0;
}
}
break;```

## Manage Incorrect Input

So far, we have got a working expression parser and evaluator, if we provide correct input. Now we will provide an option for the user to validate the input, and to try to parse it, without getting exceptions.

### Check Input Characters

A basic input validation would be to check whether the `string `contains illegal characters. The characters allowed for an expression would be the following: `0-9` (numbers)`; '+'; '-'; '*'; '/'; '('; ')'; '.'; ','; ' '`(space).

We create a function which checks if the `string` contains only these characters with trying to match the following regular expression: `^[0-9+*-/()., ]+\$`

```public static bool IsExpression(string s)
{
//Determines whether the string contains illegal characters
Regex RgxUrl = new Regex("^[0-9+*-/()., ]+\$");
return RgxUrl.IsMatch(s);
}```

For this, the following `using` directive is required:

`using System.Text.RegularExpressions;`

### TryParse() Method

As seen in built-in classes, we will provide a `TryParse() `method, which returns a boolean value indicating whether the expression can be parsed, and also the evaluated value as an `out `parameter.

`public static bool TryParse(string expression, out decimal value)`

To check if it can be evaluated, check first if it contains any illegal characters, then call the `Parse` method surrounded with a `try catch` block, to catch any exceptions.

```public static bool TryParse(string expression, out decimal value)
{
if (IsExpression(expression))
{
try
{
value = Parse(expression);
return true;
}
catch
{
value = 0;
return false;
}
}
else
{
value = 0;
return false;
}
}```

Basically, we just call `Parse`, but `catch` any `exception`s instead of the user, and return `false` if any occurred. If everything ran fine, we return `true` and the evaluated value in the `out `parameter.

Let's change the code in our demo application to use this method, in the button event handler:

```private void button1_Click(object sender, EventArgs e)
{
decimal d;
if (MathsEvaluator.TryParse(textBox1.Text, out d))
{
label1.Text = d.ToString();
}
else
{
label1.Text = "Unable to evaluate expression,"
+ " possible incorrect syntax.";
}
}```

## Extensibility

I would like to show how the solution can be extended to provide more functionality than that was required in the beginning.

### The ^ Operator

This section provides an example of adding support for a new operation which has two operands and the operator is a single character as the previously implemented ones.

The new operator will be `^`(aka power, e.g. `2^3 = 8` or `2^(5+5) = 1024`). It has higher precedence than any other implemented (we will mark it as 3).

Let's see a list of required changes:

1. Include it in the regular expression used in `IsExpression`
2. Add it to the `operators` `Dictionary` in the `CalculateValue` method
3. Finally, implement it in the `EvaluateOperation` function

#### Implementation

1. Change the regular expression line, to:
`Regex RgxUrl = new Regex("^[0-9+*-/^()., ]+\$");`
2. Change the `operators Dictionary` definition to:
```Dictionary<char, int> operators = new Dictionary<char, int>
{
{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'^', 3}
};```
3. Implement the `^` operation. To do this, we will use the `double Math.Pow(double, double)` method, but we have to convert the parameters to `double` and the returned value to `decimal`, because the method works on `double`s and we are using `decimal`s in the class. Add the following to the `switch` block in the `EvaluateOperation` method:
```case '^':
value = Convert.ToDecimal(
Math.Pow(Convert.ToDouble(op1),
Convert.ToDouble(op2)));
break;```

That's it! Now the evaluator supports the power operation as well.

## History

• First version

## License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

## About the Author

 Student Poland
No Biography provided

## Comments and Discussions

 First Prev Next
 My vote of 5 RyanEK18-Dec-11 15:33 RyanEK 18-Dec-11 15:33
 My vote of 5 Tushar_Patil12-Dec-11 18:22 Tushar_Patil 12-Dec-11 18:22
 My vote of 5 Thorsten Bruning12-Dec-11 5:02 Thorsten Bruning 12-Dec-11 5:02
 Thoughts PIEBALDconsult12-Dec-11 4:02 PIEBALDconsult 12-Dec-11 4:02
 Re: Thoughts Akos Orban13-Dec-11 2:19 Akos Orban 13-Dec-11 2:19
 My vote of 5 Filip D'haene12-Dec-11 3:27 Filip D'haene 12-Dec-11 3:27
 Re: My vote of 5 Akos Orban13-Dec-11 2:00 Akos Orban 13-Dec-11 2:00
 Thank you for voting!
 Last Visit: 31-Dec-99 18:00     Last Update: 28-May-17 18:24 Refresh 1

General    News    Suggestion    Question    Bug    Answer    Joke    Praise    Rant    Admin

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170525.1 | Last Updated 12 Dec 2011
Article Copyright 2011 by Akos Orban
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid