.Net下的算术表达式解析器的实现思路与源码

作为程序设计人员经常会遇到这样的情况,需要将某个指定的字符串表达式转换为算术表达式并计算其结果.使用Delphi的朋友可以在网上获取第三方控件来实现,而.Net框架类库并没有相关的处理类,正好在前不久的给一所大学开发的Web应用中也需要实现相关的处理.就抽空写了一个相关的处理类(实现了大部分的算术运算操作,需要其他运算可以在现有基础上扩展),现将部分代码贴出共大家参考,希望能够在交流中进步、互助中学习、探讨中深入:

//EnumExpress

using System;

namespace ExpressionTest

{

/// <summary>

/// EnumExpress 的摘要说明。

/// </summary>

public enum EnumExpress

{

Add,//加号

Dec,//减号

Mul,//乘号

Div,//除号

Sin,//正玄

Cos,//余玄

Tan,//正切

ATan,//余切

Sqrt,//平方根

Pow,//求幂

None,//无

}

}

//ExpressDeal

using System;

namespace ExpressionTest

{

/// <summary>

/// ExpressDeal 的摘要说明。

/// </summary>

public class ExpressDeal

{

static ExpressDeal()

{

}

private double CalculateExpress(string strExpression)

{

string strTemp="";

string strTempB="";

string strOne="";

string strTwo="";

double ReplaceValue=0;

while (strExpression.IndexOf("+")!=-1 || strExpression.IndexOf("-")!=-1

|| strExpression.IndexOf("*")!=-1 || strExpression.IndexOf("/")!=-1)

{

if (strExpression.IndexOf("*")!=-1)

{

strTemp=strExpression.Substring(strExpression.IndexOf("*")+1,strExpression.Length-strExpression.IndexOf("*")-1);

strTempB=strExpression.Substring(0,strExpression.IndexOf("*"));

strOne=strTempB.Substring(GetPrivorPos(strTempB)+1,strTempB.Length-GetPrivorPos(strTempB)-1);

strTwo=strTemp.Substring(0,GetNextPos(strTemp));

ReplaceValue=Convert.ToDouble(GetExpType(strOne))*Convert.ToDouble(GetExpType(strTwo));

strExpression=strExpression.Replace(strOne+"*"+strTwo,ReplaceValue.ToString());

}

else if (strExpression.IndexOf("/")!=-1)

{

strTemp=strExpression.Substring(strExpression.IndexOf("/")+1,strExpression.Length-strExpression.IndexOf("/")-1);

strTempB=strExpression.Substring(0,strExpression.IndexOf("/"));

strOne=strTempB.Substring(GetPrivorPos(strTempB)+1,strTempB.Length-GetPrivorPos(strTempB)-1);

strTwo=strTemp.Substring(0,GetNextPos(strTemp));

ReplaceValue=Convert.ToDouble(GetExpType(strOne))/Convert.ToDouble(GetExpType(strTwo));

strExpression=strExpression.Replace(strOne+"/"+strTwo,ReplaceValue.ToString());

}

else if (strExpression.IndexOf("+")!=-1)

{

strTemp=strExpression.Substring(strExpression.IndexOf("+")+1,strExpression.Length-strExpression.IndexOf("+")-1);

strTempB=strExpression.Substring(0,strExpression.IndexOf("+"));

strOne=strTempB.Substring(GetPrivorPos(strTempB)+1,strTempB.Length-GetPrivorPos(strTempB)-1);

strTwo=strTemp.Substring(0,GetNextPos(strTemp));

ReplaceValue=Convert.ToDouble(GetExpType(strOne))+Convert.ToDouble(GetExpType(strTwo));

strExpression=strExpression.Replace(strOne+"+"+strTwo,ReplaceValue.ToString());

}

else if (strExpression.IndexOf("-")!=-1)

{

strTemp=strExpression.Substring(strExpression.IndexOf("-")+1,strExpression.Length-strExpression.IndexOf("-")-1);

strTempB=strExpression.Substring(0,strExpression.IndexOf("-"));

strOne=strTempB.Substring(GetPrivorPos(strTempB)+1,strTempB.Length-GetPrivorPos(strTempB)-1);

strTwo=strTemp.Substring(0,GetNextPos(strTemp));

ReplaceValue=Convert.ToDouble(GetExpType(strOne))-Convert.ToDouble(GetExpType(strTwo));

strExpression=strExpression.Replace(strOne+"-"+strTwo,ReplaceValue.ToString());

}

}

return Convert.ToDouble(strExpression);

}

private double CalculateExExpress(string strExpression,EnumExpress ExpressType)

{

double retValue=0;

switch(ExpressType)

{

case EnumExpress.Sin:

retValue=Math.Sin(Convert.ToDouble(strExpression));

break;

case EnumExpress.Cos:

retValue= Math.Cos(Convert.ToDouble(strExpression));

break;

case EnumExpress.Tan:

retValue= Math.Tan(Convert.ToDouble(strExpression));

break;

case EnumExpress.ATan:

retValue= Math.Atan(Convert.ToDouble(strExpression));

break;

case EnumExpress.Sqrt:

retValue= Math.Sqrt(Convert.ToDouble(strExpression));

break;

case EnumExpress.Pow:

retValue= Math.Pow(Convert.ToDouble(strExpression),2);

break;

}

if (retValue==0) return Convert.ToDouble(strExpression);

return retValue;

}

private int GetNextPos(string strExpression)

{

int[] ExpPos=new int[4];

ExpPos[0]=strExpression.IndexOf("+");

ExpPos[1]=strExpression.IndexOf("-");

ExpPos[2]=strExpression.IndexOf("*");

ExpPos[3]=strExpression.IndexOf("/");

int tmpMin=strExpression.Length;

for (int count=1;count<=ExpPos.Length;count++)

{

if (tmpMin>ExpPos[count-1] && ExpPos[count-1]!=-1)

{

tmpMin=ExpPos[count-1];

}

}

return tmpMin;

}

private int GetPrivorPos(string strExpression)

{

int[] ExpPos=new int[4];

ExpPos[0]=strExpression.LastIndexOf("+");

ExpPos[1]=strExpression.LastIndexOf("-");

ExpPos[2]=strExpression.LastIndexOf("*");

ExpPos[3]=strExpression.LastIndexOf("/");

int tmpMax=-1;

for (int count=1;count<=ExpPos.Length;count++)

{

if (tmpMax<ExpPos[count-1] && ExpPos[count-1]!=-1)

{

tmpMax=ExpPos[count-1];

}

}

return tmpMax;

}

public string SpiltExpression(string strExpression)

{

string strTemp="";

string strExp="";

while (strExpression.IndexOf("(")!=-1)

{

strTemp=strExpression.Substring(strExpression.LastIndexOf("(")+1,strExpression.Length-strExpression.LastIndexOf("(")-1);

strExp=strTemp.Substring(0,strTemp.IndexOf(")"));

strExpression=strExpression.Replace("("+strExp+")",CalculateExpress(strExp).ToString());

}

if(strExpression.IndexOf("+")!=-1 || strExpression.IndexOf("-")!=-1

|| strExpression.IndexOf("*")!=-1 || strExpression.IndexOf("/")!=-1)

{

strExpression=CalculateExpress(strExpression).ToString();

}

return strExpression;

}

private string GetExpType(string strExpression)

{

strExpression=strExpression.ToUpper();

if (strExpression.IndexOf("SIN")!=-1)

{

return CalculateExExpress(strExpression.Substring(strExpression.IndexOf("N")+1,strExpression.Length-1-strExpression.IndexOf("N")),EnumExpress.Sin).ToString();

}

if (strExpression.IndexOf("COS")!=-1)

{

return CalculateExExpress(strExpression.Substring(strExpression.IndexOf("S")+1,strExpression.Length-1-strExpression.IndexOf("S")),EnumExpress.Cos).ToString();

}

if (strExpression.IndexOf("TAN")!=-1)

{

return CalculateExExpress(strExpression.Substring(strExpression.IndexOf("N")+1,strExpression.Length-1-strExpression.IndexOf("N")),EnumExpress.Tan).ToString();

}

if (strExpression.IndexOf("ATAN")!=-1)

{

return CalculateExExpress(strExpression.Substring(strExpression.IndexOf("N")+1,strExpression.Length-1-strExpression.IndexOf("N")),EnumExpress.ATan).ToString();

}

if (strExpression.IndexOf("SQRT")!=-1)

{

return CalculateExExpress(strExpression.Substring(strExpression.IndexOf("T")+1,strExpression.Length-1-strExpression.IndexOf("T")),EnumExpress.Sqrt).ToString();

}

if (strExpression.IndexOf("POW")!=-1)

{

return CalculateExExpress(strExpression.Substring(strExpression.IndexOf("W")+1,strExpression.Length-1-strExpression.IndexOf("W")),EnumExpress.Pow).ToString();

}

return strExpression;

}

}

}