撰文/周翔
本人開(kāi)源代碼頁(yè):http://blog.csdn.net/hifrog/category/131301.aspx
功能:用戶(hù)輸入一個(gè)字符串,判斷這個(gè)字符串是否是后綴表達式,并把它轉化為前綴表達式,并顯示。
原理:利用S屬性文法的制導翻譯生成語(yǔ)法樹(shù)節點(diǎn),其中該語(yǔ)法樹(shù)為二叉樹(shù)。非葉節點(diǎn)保存運算符,葉節點(diǎn)保存數字或變量。制導翻譯公式請參考《編譯原理》(高等教育出版社,陳意云著(zhù),2003年版)一書(shū)。筆者使用的產(chǎn)生式
加減二元運算的產(chǎn)生式:E->TE+|TE-|T
乘除二元運算的產(chǎn)生式:T->FT*|FT/|F
變量、數字、二元表達式的產(chǎn)生式:F->E|i
為了避免從左向右推導產(chǎn)生的歧意,筆者采用了從右向左推導。
其它特點(diǎn):
1.程序能自動(dòng)判斷為什么不是后綴表達式;
2.代碼長(cháng)度不超過(guò)100行。
代碼:
//*============= 代碼: 周翔 ===============*//
#include<string>
#include<iostream>
#include<csetjmp>
using namespace std;
static string expr;
static int pos;
static jmp_buf errjb;
struct BiTree
{
string data;
BiTree* lchild;
BiTree* rchild;
};
BiTree* T_MulDiv();
BiTree* F_ExpNum();
//E->TE+|TE-|T
BiTree* E_AddSub()
{
if(expr[pos]==‘+‘||expr[pos]==‘-‘)
{
BiTree* ret=new BiTree;
ret->data=expr[pos--];
ret->rchild=E_AddSub();
ret->lchild=T_MulDiv();
return ret;
}
return T_MulDiv();
}
//T->FT*|FT/|F
BiTree* T_MulDiv()
{
if(expr[pos]==‘*‘||expr[pos]==‘/‘)
{
BiTree* ret=new BiTree;
ret->data=expr[pos--];
ret->rchild=T_MulDiv();
ret->lchild=F_ExpNum();
return ret;
}
return F_ExpNum();
}
//F->E|i
BiTree* F_ExpNum()
{
BiTree* ret=new BiTree;
ret->data="";
if(isalnum(expr[pos]))
{
ret->data=expr[pos--];
ret->lchild=ret->rchild=0;
return ret;
}
if(pos<0)
{
cout<<"出錯!未預期的結尾!"<<endl;
longjmp(errjb,1);
}
if(expr[pos]==‘+‘||expr[pos]==‘-‘||expr[pos]==‘*‘||expr[pos]==‘/‘)
{
return E_AddSub();
}
cout<<"出錯!非法字符!"<<endl;
longjmp(errjb,1);
}
void PreVisit(BiTree* BT)
{
if(BT)
{
cout<<BT->data;
PreVisit(BT->lchild);
PreVisit(BT->rchild);
}
}
int main()
{
bool quit=false;
do{
if(setjmp(errjb)==0)
{
cout<<"請輸入一個(gè)表達式(按‘Q‘或‘q‘退出):"<<endl;
cin>>expr;
if(expr[0]==‘Q‘||expr[0]==‘q‘)
quit=true;
else
{
pos=expr.length()-1;
BiTree* Root=E_AddSub();
if((int)expr[pos]>0)
{
cout<<"出錯!冗余的字符!"<<endl;
longjmp(errjb,1);
}
cout<<"該后綴表達式的前綴表達式如下:"<<endl;
PreVisit(Root);
cout<<endl;
}
}
else
{
cout<<"您輸入的字符串不是后綴表達式!"<<endl;
}
}while(!quit);
return 0;
}
聯(lián)系客服