2

I want to extract variables from math expression using c#. I wrote this code and it works right:

List<string> Variables = new List<string>();
string temp = string.Empty;
Console.WriteLine("Please enter ur expression");
string Expression = Console.ReadLine().Trim();
int Index;
for (Index = 0; Index <= Expression.Length - 1; Index++)
{
    if (char.IsLetter(Expression[Index]))
    {
        temp = temp + Expression[Index];
    }
    else
    {
        if (temp.Length > 0)
        {
            Variables.Add(temp);
            temp = string.Empty;
        }
    }
}
if (temp.Length > 0)
{
    Variables.Add(temp);
}
foreach (string item in Variables)
{
    Console.WriteLine(item);
}
Console.ReadKey();

I have to detect SIN and COS from expression so I will remove SIN and COS from Variables.

  1. Is it good way ?
  2. IS it possible to do this with Regular expressions or better ways ?
  3. Does this code need refactoring ?

After extract I want replace variables with values from input and I will calculate the expression result.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Shahin
  • 12,543
  • 39
  • 127
  • 205
  • Is your goal to extract variables only or do more? – J Trana Apr 24 '11 at 06:16
  • After extract I will replace Variables with values from input and i will calculate the expression – Shahin Apr 24 '11 at 06:18
  • If you are doing the evaluation yourself vs. passing a string to a pre-built method, you will probably want to do the parsing yourself. I'll answer accordingly. – J Trana Apr 24 '11 at 06:21
  • 1
    Are you sure it parses right? From expressions ending in a variable like `a` or `b+a` it's omitting the last one (`a` in these cases). – Howard Apr 24 '11 at 06:37
  • You should add an example or two of what you are trying to parse and what the desired output is – Peter M Apr 24 '11 at 06:48
  • @Howard , Thanks :) I corrected the code. – Shahin Apr 24 '11 at 06:56

3 Answers3

3

Try sketching an automata that detects expressions. After that the simplest way to implement an automata would be a switch..case with nested if..else. I think it would be far easier than parsing the string the way you are right now.

Edit--

This is a very simple example, only for the sake of demonstration. suppose I want to detect expressions in the form of var1 + var2, the automata would look like this: automataImage

Implementaion looks like this:

done = false;
state = start;
while(!done)
{
    switch(state)
    {
    case start:
        if(expression[i] > 'a' && expression[i] < 'z')
            state = start;
        else if(expression[i] == '+')
        {
            // seen first operand and waitng for second
            // so we switch state
            state = add;
        }
        break;
    case add:
        if(expression[i] > 'a' && expression[i] < 'z')
            state = add;
        else
            done = true;
        break;
    }
}

Like I said this is very simple, your automata would be more complex with many more states and transitions. I've also not included actions here, but you could do actual addition after second operand is read which is after done = true;

atoMerz
  • 7,534
  • 16
  • 61
  • 101
  • Please describe more with real example. – Shahin Apr 24 '11 at 06:22
  • This may indicate my ignorance, but I thought it was bad form to change the value of a switch var in the middle of the statement. – Peter M Apr 24 '11 at 07:14
  • @PeterM You're right. This is just the simplest implementation that came to my mind. I'm sure there are plenty of design patterns that can be applied. – atoMerz Apr 09 '14 at 13:49
1

I like using the Shunting-yard algorithm: http://en.wikipedia.org/wiki/Shunting-yard_algorithm It makes eval easy.

J Trana
  • 2,150
  • 2
  • 20
  • 32
  • But it works with expressions like this : 5 * 2 + 22 /100 Am I right ? my expression is like this : 5 * a +bv /100 and i should replace variables with Input data after that this algorithm will be useful – Shahin Apr 24 '11 at 06:41
  • 1
    Yes, that's correct. But if you look at how the algorithm works, you can change the step for detecting and pushing a number onto the stack with detecting a variable name or a number and replacing the variable with the value at that point before pushing it on the stack. – J Trana Apr 24 '11 at 06:47
1

If you want parse experssion yourself, your ways seems good, but it doesn't evaluate it, in this cases I prefer to use previous wrote parsers like NCalc, instead of creating the wheal, but if this is a homework and you just want to find variables, your way can be optimized by for example doing temp += Expression[Index];, Also may be using Experssion.Split(... works better in this case. and if you want parse it yourself you can use shutting yard algorithm.

Saeed Amiri
  • 22,252
  • 5
  • 45
  • 83
  • ممنون سعید جان :) Using Shutting yard algorithm is next step after variables replaced by values from input or maybe I'll use converting Infix to Prefix to calculate , but how can I use 'Experssion.Split' in this case ? Its homework – Shahin Apr 24 '11 at 07:47
  • @shaahin, if there is limitation in input string format, for example you can do: `expersion.Split("0123456789-+/*)([]".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)` – Saeed Amiri Apr 24 '11 at 07:57