从字符串数学表达式中提取变量

时间:2011-04-24 06:01:39

标签: c# string math refactoring

我想用c#从数学表达式中提取变量。我写了这段代码,它的工作正常:

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

我必须从表达式中检测SIN和COS,因此我将从变量中删除SIN和COS。

  1. 这是好方法吗?
  2. 是否可以使用正则表达式或更好的方法来执行此操作?
  3. 此代码是否需要重构?
  4. 提取后我想用输入中的值替换变量,我将计算表达式结果。

3 个答案:

答案 0 :(得分:3)

尝试绘制检测表达式的自动机。 在那之后,实现自动机的最简单方法是使用嵌套if..else的switch..case。 我认为这比以现在的方式解析字符串要容易得多。

编辑 -

这是一个非常简单的例子,仅仅是为了演示。假设我想以var1 + var2的形式检测表达式,自动机将如下所示: automata Image

Implementaion看起来像这样:

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

就像我说这很简单,你的自动机会更复杂,有更多的状态和转换。我也没有在这里包含动作,但是你可以在读完第二个操作数之后进行实际添加,这是在完成= true之后;

答案 1 :(得分:1)

我喜欢使用Shunting-yard算法: http://en.wikipedia.org/wiki/Shunting-yard_algorithm 它使eval变得容易。

答案 2 :(得分:1)

如果你想自己解决问题,你的方法似乎很好,但它没有评估它,在这种情况下我更喜欢使用先前写的解析器,如NCalc,而不是创建风团,但如果这是一个家庭作业,你只想找到变量,你的方式可以通过例如做temp += Expression[Index];来优化,也可以使用Experssion.Split(...在这种情况下更好地工作。如果你想自己解析它,你可以使用关闭码算法。