当前位置:文档之家› 编译原理(逆波兰表达式)C语言版

编译原理(逆波兰表达式)C语言版

中国计量学院《编译原理设计》课程论文题目:中缀表达式的逆波兰表示学生姓名:学号:学生专业:班级:二级学院:一、摘要编译原理是计算机科学与技术专业最重要的一门专业基础课程,内容庞大,涉及面广,知识点多。

由于该课程教、学难度都非常大,往往费了大量时间而达不到预期教学效果俗语说:学习的最好方法是实践。

本课程设计正是基于此,力求为学生提供一个理论联系实际的机会,通过布置一定难度的课题,要求学生独立完成。

我们这次课程设计的主要任务是编程实现对输入合法的中缀表达式进行词法分析、语法分析,构造相应的逆波兰式,计算后缀表达式的值输出结果。

逆波兰式也叫后缀表达式,即将运算符写在操作数之后。

通过实践,建立系统设计的整体思想,锻炼编写程序、调试程序的能力,学习文档编写规范,培养独立学习、吸取他人经验、探索前言知识的习惯,树立团队协作精神。

同时,课程设计可以充分弥补课堂教学及普通实验中知识深度与广度有限的缺陷,更好地帮助学生从全局角度把握课程体系。

关键字:逆波兰式;语法分析;中缀表达式二、实验综述在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,所以,这种表示法也称为中缀表示。

对中缀表达式的计值,并非按运算符出现的自然顺序来执行其中的各个运算,而是根据算符间的优先关系来确定运算的次序,此外,还应顾及括号规则。

因此,要从中缀表达式直接产生目标代码一般比较麻烦。

相对的,逆波兰式在计算机看来却是比较简单易懂的结构。

因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序。

三、实验意义对于实现逆波兰式算法,难度并不大,但为什么要将看似简单的中缀表达式转换为逆波兰式,原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中缀表达式是非常复杂的结构。

相对的,逆波兰式在计算机看来却是比较简单易懂的结构。

因为计算机普遍采用的内存结构是栈式结构,它执行四、系统分析词法分析基本原理:词法分析程序完成的是编译第一阶段的工作。

词法分析的作用是把符流的程序变为单词序列,输出在一个中间文件上,这个文件作为语法分析程序的输入而继续编译过程。

递归下降的原理由于时间和技术的限制,语法分析采用递归下降的方法。

递归下降法是语法分析中最易懂的一种方法。

它的主要原理是,对每个非终极符按其产生式结构构造相应语法分析子程序,其中终极符产生匹配命令,而非终极符则产生过程调用命令。

因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。

其中子程序的结构与产生式结构几乎是一致的。

五、算法实现将一个普通的中序表达式转换为逆波兰表达式的一般算法是:1 、首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。

2 、读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。

3 、从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。

4、如果不是数字,该字符则是运算符,此时需比较优先关系。

做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。

如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。

5 、重复上述操作1-2直至扫描完整个简单算术表达式,确定所有字符都得正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。

转换的基本思路:1 在表达式字符串的末尾加一个代表结束的辅助符,比如“#”。

2 从头开始扫描表达式,并判断当前的每一个字符。

3 取当前的一个字符,如果当前字符是代表数字,则进逆波兰式的栈,如果是运算符,则转入4,如果是“#”,则结束。

4 比较当前运算符与临时栈中的栈顶运算符,如果栈顶运算符比当前运算符优先级高,则弹出一个运算符放进逆波兰式栈中,并继续4。

否则把当前运算符进临时栈,转入2六、测试结果七、总结在这次的课程设计中,让我深深地体现到编程不是一件简单的事情,它需要设计者具有全面的专业知识、缜密的思维、严谨的工作态度以及较高的分析问题、解决问题的能力,而我在很多方面还有欠缺。

通过编程实现了预期的目标,尽管如此,在程序实现的过程中出现过许多没有想到的功能,原本设计的思路和方法,到真正的程序中运行的时候就达不到预想的效果。

因此,我感觉编程序实际操作是非常重要的,不亲自实践就不会发现问题,我们只有不断的发现问题,不断的解决问题,才能使一个程序尽可能的完善。

当我即将完成这个设计的时候我终于认清楚了以前老师经常提起的一个问题,那就是:一个软件开发的过程中编码不是重要的,重要的是对分析系统以及系统模型的建立。

有了一个好的系统模型之后,我们再将其划分成几个模块,那样做起来就会容易得多。

由于经验不足,时间有限,虽然在一周的时间里顺利的完成了系统的分析、设计和调试的工作,但是仍然有许多不足之处,我会在将来的软件设计过程中引以为戒。

在做课程设计期间,有目的的去学习一些将要用到的东西,仔细的考虑工作流程的规律和步骤,充分的利用手中的开发工具,使自己的开发在代码上实现少而精确,能够尽量简单的进行操作。

通过这个课程设计让我有了深刻的了解,增长了自己的动手能力,而且我认识到团队合作也十分重要。

通过这次课程设计不仅锻炼了我学习能力,在团队合作上也有很大提高附录:源代码#include<stdio.h>/*标准输入输出头文件*/#include<conio.h>/*控制台输入输出*/#include<math.h>/*数学库函数*/#include<stdlib.h>/*系统函数,分配、释放内存等*/#include<string.h>/*字符串处理*/#define MaxSize 99char calc[MaxSize],expr[MaxSize];int i,t;struct{char data[MaxSize];/*构造了一个字符串*/ int top;}Sym;/*符号*/struct{double data[MaxSize];/*构造一个双精度数组*/int top;}Num;/*数*/double ston(char x[],int *p)/*定义一函数*/{int j=*p+1,i;double n=0;char sign=x[*p];/*字符串*/if(sign=='+'||sign=='-') *p=*p+1; while(x[j]>='0'&&x[j]<='9'){j++;}for(i=*p;i<j;i++){n=n*10+(x[i]-'0');}if(x[j]=='.'){*p=++j;while(x[j]>='0'&&x[j]<='9'){j++;}for(i=*p;i<j;i++){n=n+pow(0.1,i-*p+1)*(x[i]-'0'); }}*p=j;if(sign=='-') return(-n);return(n);}void InitStack(){Sym.top=Num.top=-1;}void SymPush(){if(Sym.top<MaxSize-1){Sym.data[++Sym.top]=calc[i++]; }else{printf("Sym栈满\n");return;}}void SymPop(){if(Sym.top>=0){expr[++t]=Sym.data[Sym.top--]; }else{printf("Sym栈空\n");return;}}void NumPush(){if(Num.top<MaxSize-1){Num.data[++Num.top]=ston(expr,&i);}else{printf("Num栈满\n");return;}}void NumPop(){if(Num.top>=0){if(expr[i]!=' '){switch(expr[i]){case '+':Num.data[Num.top-1]=Num.data[Num.top-1]+Num.data[Num.top];break;case '-':Num.data[Num.top-1]=Num.data[Num.top-1]-Num.data[Num.top];break;case '*':Num.data[Num.top-1]=Num.data[Num.top-1]*Num.data[Num.top];break;case '/':Num.data[Num.top-1]=Num.data[Num.top-1]/Num.data[Num.top];break;case '%':Num.data[Num.top-1]=(int)(Num.data[(Num.top-1)])%(int)(Num.data[Num.top]);break;case '^':Num.data[Num.top-1]=pow(Num.data[Num.top-1],Num.data[Num.top]);break;}Num.top--;}}else{printf("Num栈空\n");return;}}int main(void){loop1:i=0,t=-1;system("cls");printf("********************************************\n"); printf("**********中缀表达式变逆波兰表达式**********\n");printf("********************************************\n"); printf("请输入中缀表达式:");InitStack(),gets(calc);while(calc[i]!='\0'&&calc[i]!='='){if(calc[i]>='0'&&calc[i]<='9'){while((calc[i]>='0'&&calc[i]<='9')||(calc[i]=='.')) {loop2:expr[++t]=calc[i++];}expr[++t]=' ';}else if(calc[i]=='('){SymPush();}else if(calc[i]==')'){while(Sym.data[Sym.top]!='('){SymPop();expr[++t]=' ';}Sym.data[Sym.top--]='\0';i++;}else if((calc[i]=='+'||calc[i]=='-')){if((i==0)||(!(calc[i-1]>='0'&&calc[i-1]<='9')&&calc[i-1]!=')')) goto loop2;while(Sym.top>=0 && Sym.data[Sym.top]!='('){SymPop();expr[++t]=' ';}SymPush();}else if(calc[i]=='*'||calc[i]=='/'||calc[i]=='%'){while(Sym.top>=0&&(Sym.data[Sym.top]=='*'||Sym.data[Sym.top]=='/'||Sy m.data[Sym.top]=='%'||Sym.data[Sym.top]=='^')){SymPop();expr[++t]=' ';}SymPush();}else if(calc[i]=='^'){while(Sym.top>=0&&Sym.data[Sym.top]=='^'){SymPop();expr[++t]=' ';}SymPush();}else{i++;}}while(Sym.top>=0){SymPop();expr[++t]=' ';}expr[++t]=Sym.data[++Sym.top]='\0';printf("后缀表达式:%s\n",expr);for(i=0;expr[i]!='\0';i++){if((expr[i]>='0'&&expr[i]<='9')||((expr[i]=='+'||expr[i]=='-')&&(expr[i+1]>='0'&&expr[i+1]<='9'))){NumPush();}else{NumPop();}}printf("运算结果为:%g\n",Num.data[0]); printf("Continue(y/n)?");switch(getch()){case 'y':{system("cls");goto loop1;} case 'n':default :exit(0);}getch();return(0);}。

相关主题