编译原理之表达式求值.docx

上传人:b****8 文档编号:10152847 上传时间:2023-02-08 格式:DOCX 页数:9 大小:15.96KB
下载 相关 举报
编译原理之表达式求值.docx_第1页
第1页 / 共9页
编译原理之表达式求值.docx_第2页
第2页 / 共9页
编译原理之表达式求值.docx_第3页
第3页 / 共9页
编译原理之表达式求值.docx_第4页
第4页 / 共9页
编译原理之表达式求值.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

编译原理之表达式求值.docx

《编译原理之表达式求值.docx》由会员分享,可在线阅读,更多相关《编译原理之表达式求值.docx(9页珍藏版)》请在冰豆网上搜索。

编译原理之表达式求值.docx

编译原理之表达式求值

编译原理之表达式求值

中缀表达式a+b*(c+d)-e

前续表达式(波兰)-e+a*b+cd

后续表达式(逆波兰)abcd+*e-+

中缀转后缀

1.构建二叉树->后续遍历

2.堆栈方法:

中缀表达式到逆波兰表达式的转换及求值(ChinaDHF)

最近要写一个工资管理软件,不可避免的要用到公式的定义及求值等问题。

对于数学表达式的计算,虽然也有直接对表达式进行扫描并按照优先级逐步计算的方法,但感觉还是不如将中缀表达式转换为逆波兰表达式更容易处理。

使用逆波兰表达式,则有以下几件工作需要去做:

1.对中缀表达式进行语法分析,或称合法性检查。

2.将中缀表达式转换为逆波兰表达式。

3.计算逆波兰表达得到我们想要的值。

以下是我为实现该功能而写的一个简单的类:

usingSystem;

usingSystem.Text;

usingSystem.Collections;

usingSystem.Text.RegularExpressions;

namespaceSeaking

{

publicclassRpnExpression

{

检查中缀表达式的合法性#region检查中缀表达式的合法性

///

///检查中缀表达式是否合法。

///

///

///

publicstaticboolIsRight(stringexp)

{

stringpMatch=@"\([^\(^\)]+\)";//匹配最“内”层括号及表达式

stringnumberMatch=@"\d+(\.\d+)?

";//匹配数字

stringexMatch=@"^0([-+*/]0)*$";//匹配无括号的、用0替换所有的数字后的表达式exp=Regex.Replace(exp,numberMatch,"0");//为简化检测,用0替换所有的数字

while(Regex.IsMatch(exp,pMatch))

{

foreach(MatchmatchinRegex.Matches(exp,pMatch))

{

stringtmp=match.Value;

tmp=tmp.Substring(1,tmp.Length-2);//去掉"("和")"

if(!

Regex.IsMatch(tmp,exMatch))returnfalse;

}

exp=Regex.Replace(exp,pMatch,"0");//将最内层的括号及括号内表达式直接用一个0代替

}

returnRegex.IsMatch(exp,exMatch);

}

#endregion

生成逆波兰表达式#region生成逆波兰表达式

///

///获取逆波兰表达式。

///

///

///

publicstaticstringRpnExp(stringexp)

{

if(!

IsRight(exp))thrownewApplicationException("非法的中缀表达式。

");

StackskOp=newStack();//定义操作符堆栈

StringBuilderrpn=newStringBuilder();//逆波兰表达式

char[]charExp=exp.ToCharArray();//将中缀表达式转换为char数组

stringdigit=string.Empty;//数字字符串

for(inti=0;i

{

charchr=charExp[i];

if(char.IsDigit(chr)||chr=='.')//如果是数字或小数点,添加到数字字符串中

{

digit+=chr;

}

elseif("+-*/".IndexOf(chr)>=0)//如果是运算符

{

if(digit.Length>0)

{

rpn.Append("<"+digit+">");//首先将数字添加到逆波兰表达式

digit=string.Empty;

}

//弹出操作符并添加到逆波兰表达式,直至遇到左括号或优先级较低的操作符while(skOp.Count>0)

{

charopInStack=(char)skOp.Pop();

if(opInStack=='('||Power(opInStack)

{

skOp.Push(opInStack);

break;

}

else

{

rpn.Append(opInStack);

}

}

skOp.Push(chr);//将当前操作符压入堆栈中

}

elseif(chr=='(')//遇到左括号,直接压入堆栈中

{

skOp.Push(chr);

}

elseif(chr==')')//遇到右括号

{

if(digit.Length>0)//先将数字添加到逆波兰表达式

{

rpn.Append("<"+digit+">");

digit=string.Empty;

}

while(skOp.Count>0)//弹出运算符并添加到逆波兰表达式,直至遇到左括号{

charopInStack=(char)skOp.Pop();

if(opInStack=='(')

{

break;

}

else

{

rpn.Append(opInStack);

}

}

}

}

//到达字符串末尾后,首先将数字添加到逆波兰表达式

if(digit.Length>0)

{

rpn.Append("<"+digit+">");

}

//弹出所有操作符并添加到逆波兰表达式

while(skOp.Count>0)

{

charopInStack=(char)skOp.Pop();

rpn.Append(opInStack);

}

returnrpn.ToString();

}

///

///获取操作符的优先级。

///

///

///

privatestaticintPower(charo)

{

switch(o)

{

case'+':

case'-':

return1;

case'*':

case'/':

return2;

default:

return0;

}

}

#endregion

计算逆波兰表达式的值#region计算逆波兰表达式的值///

///获取中缀表达式的值。

///

///

///

publicstaticdoubleGetValue(stringexp)

{

returnGetValueByRpn(RpnExp(exp));

}

///

///获取逆波兰表达式的值。

///

///

///

publicstaticdoubleGetValueByRpn(stringrpnExp)

{

Stackstack=newStack();

char[]expChar=rpnExp.ToCharArray();

stringdigit=string.Empty;

doubleresult=0;

for(inti=0;i

{

charc=expChar[i];

if(c=='<')

{

digit=string.Empty;

}

elseif(c=='>')

{

stack.Push(digit);

}

elseif(char.IsDigit(c)||c=='.')

{

digit+=c.ToString();

}

elseif(c=='+'||c=='-'||c=='*'||c=='/')

{

doubled2=Convert.ToDouble(stack.Pop());

doubled1=Convert.ToDouble(stack.Pop());

result=math(d1,d2,c);

stack.Push(result);

}

}

returnresult;

}

///

///四则运算。

///

///

///

///

///

privatestaticdoublemath(doubled1,doubled2,charo){

switch(o)

{

case'+':

returnd1+d2;

case'-':

returnd1-d2;

case'*':

returnd1*d2;

case'/':

returnd1/d2;default:

return0d;

}

}

#endregion

}

}

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 从业资格考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1