编译原理之表达式求值.docx
- 文档编号:10152847
- 上传时间:2023-02-08
- 格式:DOCX
- 页数:9
- 大小:15.96KB
编译原理之表达式求值.docx
《编译原理之表达式求值.docx》由会员分享,可在线阅读,更多相关《编译原理之表达式求值.docx(9页珍藏版)》请在冰豆网上搜索。
编译原理之表达式求值
编译原理之表达式求值
中缀表达式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 } }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 表达式 求值