编译原理课程设计简单计算器实现教材.docx
《编译原理课程设计简单计算器实现教材.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计简单计算器实现教材.docx(15页珍藏版)》请在冰豆网上搜索。
![编译原理课程设计简单计算器实现教材.docx](https://file1.bdocx.com/fileroot1/2023-1/22/d9393120-252c-4b3a-a0c6-43b44fcffbb3/d9393120-252c-4b3a-a0c6-43b44fcffbb31.gif)
编译原理课程设计简单计算器实现教材
课程设计报告
课程:
编译原理
学号:
姓名:
班级:
11级嵌入式应用技术班
教师:
时间:
2014年6月
计算机科学与技术系
设计名称:
简单计算器的实现
设计内容、目的与要求:
设计内容:
计算器的功能要求如下:
可以支持加(+)、减(-)、乘(*)、除(/)运算,如3+4-5*2/2;支持括号运算,如(4+5)*5/8。
用户输入表达式后,转化为逆波兰式并执行计算,最后输出该表达式的结果。
设计目的:
1、对单词的构词规则有明确的定义;
2、编写的分析程序能够正确识别源程序中的语法符号;
3、计算器源程序的以.c格式输出;
4、对于源程序中的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的分析;
5、计算器能够实现加,减,乘,除,混合运算,多项式运算
设计要求:
1、将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。
2、掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化。
计划与进度安排:
5月20日—5月21日:
确定本次课程设计研究课题:
实现简单计算器。
5月22日—5月30日:
进行需求分析,分析该计算器具有哪些功能,并明确该课题的一些要求。
5月31日—6月3日:
查找相关资料和书籍,了解本课题涉及有关知识,如:
编译原理的一些基本概念,逆波兰式的基本概念,以及逆波兰式的转化问题等。
6月4日—6月8日:
概要设计,将程序的几大模块分开来设计,画出程序的流程图
6月8日—6月10日:
详细设计,写出代码并进行调试
6月10日—6月12日:
运行程序,如果能够实现本次课程设计则进行优化,如果不能满足要求则继续改进。
6月13日—6月15日:
对本次课程设计进行分析总结。
设计过程、步骤(可加页):
一、需求分析
1.1总述
在日常的学习与工作过程中,经常遇到计算表达式数值的问题,诸如34-(8+5*10)。
如果人为地分步计算,难免因疏漏了括号或字符而导致结果出错。
表达式计算器具有计算表达式结果的功能,大大方便了学习与工作。
本次开发的表达式计算器能帮我们对数据进行有效的运算,如通过四则运算能实现对输入数据的加减乘除。
本课程设计结合了编译原理中的利用算符优先分析法完成中缀表达式到逆波兰式的转化,并计算输入表达式的结果。
1.2编写表达式计算器的意义
我们每个人都使用过计算器,专用的计算器都是一个现成的器件,是由运算芯片完成运算功能的。
而且只能进行单纯的加、减、乘、除运算,不能进行表达式运算。
那么如何用计算机来实现一个基于表达式的计算器呢?
用计算机来实现一个基于表达式的计算器,也就是用编写程序(即软件)的方法来实现。
所谓的编译程序是指这样的一种程序,它能够把某一种语言程序(称为源语言程序)转换成另一种语言程序(称为目标语言程序),而后者与前者在逻辑上是等价的。
四则混合计算器的输入是一个由字符组成的表达式(源程序),如果这个表达式是合法的,则输出是这个表达式的计算结果(目标代码);否则输出错误信息。
因此四则混合计算器是一个典型的编译程序。
编译原理是计算机软件专业的一门重要的专业必修课。
尽管编译过程与外文书刊的翻译工作过程比较类似,但由于编译程序所翻译的毕竟不是自然语言,必然有其自身特性,因而学生普遍认为这门课程是专业课中比较难于学习的。
即使学习了编译原理这门课,大多数学生也不可能就开发出一个编译程序。
事实上,许多从事计算机专业的人士也未能编写出一个完整的编译系统。
而编制四则混合运算的计算器,就等价于编写一个小的编译系统,而且又具有可实现性,因此,把这个题目作为编译原理学习的一个测验题目是非常适合的。
现有的编译程序通常有两大类:
一类是翻译,另一类是解释。
所谓翻译,是指在计算机中放置一个能为计算机直接执行的翻译程序,它以某一种程序设计语言(源语言)所编写的程序(源程序)作为翻译或加工的对象,当计算机执行翻译程序时,就将它翻译为与之等价的另一种语言目标语言的程序(目标程序)。
如C编译程序就是一种翻译程序,它的源语言和目标语言分别是相应的C语言和机器语言。
解释程序也是以源程序作为它的输入,它与编译的主要区别是在解释程序的执行过程中不产生目标程序,而是边解释边执行源程序本身。
1.3功能要求
要求:
实现具有加、减、乘、除、括号等运算的简单计算器,输入表达式,转换为逆波兰式,输出该表达式的值。
二、概要设计
2.1开发环境
操作系统:
Windows7
开发平台:
VC++6.0
开发语言:
C
2.2总体设计
程序在VC++6.0中使用面向对象的技术实现了计算器。
程序主要结构如下:
1.定义部分:
定义常量、变量、数据结构。
2.初始化:
设立算符优先分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);
3.控制部分:
从键盘输入一个表达式符号串;
4.利用算符优先分析算法进行表达式处理:
根据算符优先分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
5.对生成的逆波兰式进行计算。
2.2.1逆波兰式定义
将运算对象写在前面,而把运算符号写在后面。
用这种表示法表示的表达式也称做后缀式。
逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。
采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。
2.2.2逆波兰表达式的运算法则
利用一个栈单纯地从左至右扫描逆波兰式中各个字符,就能计算出他们的值。
战中保存的是未被使用的全部的运算对象它们或者是已经扫描过的,或者是某种运算所产生的结果。
运算规则如下:
如果扫描的字符是操作符,则其值进栈,并扫描下一个字符
如果扫描的字符是一个二目运算符,则对栈顶的两个操作数执行该运算,并用运算的结果代替这两个元素。
如果扫描的字符是一个一目运算符,则对栈顶的操作数执行该运算,并用运算的结果代替该运算对象。
2.2.3逆波兰式生成的设计思想及算法
(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,表达式以“/0”结束。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:
将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将此运算符栈顶的运算从栈中弹出,将该字符入栈。
(4)重复上述操作直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
图一生成逆波兰式流程图
2.2.4表达式计算的设计思想及算法
(1)构造一个栈,存放运算对象。
(2)读入一个用逆波兰式表示的简单算术表达式。
(3)自左至右扫描该简单算术表达式并判断该字符,如果该字符是运算对象,则将该字符入栈。
若是运算符,如果此运算符是二目运算符,则将对栈顶部的两个运算对象进行该运算,将运算结果入栈,并且将执行该运算的两个运算对象从栈顶弹出。
如果该字符是一目运算符,则对栈顶部的元素实施该运算,将该栈顶部的元素弹出,将运算结果入栈。
(4)重复上述操作直至扫描完整个简单算术表达式的逆波兰式,确定所有字符都得到正确处理,我们便可以求出该简单算术表达式的值。
图二表达式结果计算流程图
结果与分析(可以加页):
图三实现计算器加法功能
图四实现计算器减法功能
图五实现计算器乘法功能
图六实现计算器除法功能
图七实验计算器混合运算功能
设计体会与建议:
在期末的课程设计中,我们小组讨论选择一个比较熟悉的课题——简单计算器的实现。
本课题的设计要求是实现具有加、减、乘、除、括号等运算的简单计算器,输入表达式,输出该表达式的值。
从大一学习C语言,到大三学习JAVA,我们都接触过实现计算器的实验,对于本次的课程设计,我们还是有点基础。
而这次的课程设计我们选择是用C语言编写的。
设计的主要原理是用后缀表达式和堆栈实现对表达式的分析后进行计算。
在编程的过程中,有些C语言的知识已经忘记,我重新找出C语言的书,一边重温之前学习的知识,一边编写代码。
在此,我运用到编译原理中间代码生成的一种形式——逆波兰式。
逆波兰式生成的要点是运算对象顺序不变,运算符紧跟运算对象之后。
掌握了这个要点,理解起来还是很容易的。
在这次的课程设计中,通过我们小组的积极配合,共同努力,我们很顺利的完成这次任务。
但是我感觉有两点不足,就是我们不能实现小数的计算,再者就是运行的界面不够美观。
这两点需要提升。
总的来说,对于这次课程设计我很满意。
这学期学习编译原理这门课程,一开始我认为学习编译原理就是了解一些原理,理论的知识,是不需要编写代码的,但是在第一堂课经过老师的介绍之后,我了解到,虽然本课程是编译原理,书本上讲到的都是一些理论知识,但是无论是哪一门课程都是需要有实践作为基础才能够将其学习的更好。
在第一次课上,老师就声明这门课比较难,要认真学,所以我很认真的对待这门课程。
本次课程设计是实现一个简易的计算器,经过大一以到大三的学习,再重新运用C语言编程感觉还挺上手的,这也可以让我重新复习一下C语言的知识。
这次课程设计采用逆波兰式的知识,这可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。
本次设计使我进一步端正了我的学习态度,学会了实事求是,对自己要严格要求。
我觉得动手做设计之前,头脑里必须清楚该怎么做,这一点是很重要的。
就目前来说,我的动手能力虽然差一点,但我想,通过我的不懈努力,在这方面,我总会得到提高。
在此次的课程设计中我最大的体会就是进一步认识到了理论联系实践的重要性。
总而言之,此次课程设计让我学到了好多平时在课堂上学不到的东西,增加了我的知识运用能力,增强我的实际操作能力。
我相信经过实践后的学习我可以将编译原理这门课程掌握的更好。
编译原理是一门比较难懂但是又非常核心的计算机课程,在学习的过程中对什么是编译程序,编译程序工作的基本过程及其各阶段的基本任务,熟悉了编译程序总流程框图,了解了编译程序的生成过程、构造工具及其相关的技术有了大致的了解。
但是要想真正理解,那就需要实践。
本次课程设计就是一个将课本上的知识运用于实践的过程。
本次课程设计是实现一个简单的计算器,该计算器可以支持加(+)、减(-)、乘(*)、除(/)运算,如3+4-5*2/2。
支持括号运算,如(4+5)*5/8。
用户输入表达式后,转化为逆波兰式并执行计算,最后输出结果。
通过本次的课程设计,加深了对于编译原理中算符优先分析算法的理解,通过自己编写一个程序去实现这个算法,增强了对于编译原理的理解和应用能力,从另一个方面,提高了理论与实践相结合的能力,锻炼了使用VC6等编程环境将课上所学习的各种理论知识转换为可执行的应用程序并使用其解决问题的能力,为进一步深入学习编译原理打下了良好的基础,加深了动手能力的锻炼。
通过课程设计,与其他两名同组的同学一起,以编译原理课上所学知识为基础,通过编程实现一个能够实现简单计算器的程序。
在此过程中遇到了许许多多的问题,我们相互协同合作,充分利用了网络搜索引擎的强大功能和学校图书馆的大量相关书籍,最终解决了所遇到的各种各样的问题,完成了预定的任务。
虽然实现了该简单计算器,但我们深知,本次课程设计还存在一些不足。
比如:
我们还可以将算法进行优化;计算器的功能不够强大,可以加以改进成为一个科学计算器;没有制作界面,不够美观实用等。
由于时间有限,这些不足我们只能在接下来的时间里继续研究探讨。
源代码:
#include
#include
#defineMaxSize99
voidtranslate(charstr[],charexp[])
{
struct
{
chardata[MaxSize];
inttop;
}op;
charch;
inti=0,t=0;
op.top=-1;
ch=str[i];
i++;
while(ch!
='\0')
{
switch(ch)
{
case'(':
op.top++;op.data[op.top]=ch;
break;
case')':
while(op.data[op.top]!
='(')
{
exp[t]=op.data[op.top];
op.top--;
t++;
}
op.top--;
break;
case'+':
case'-':
while(op.top!
=-1&&op.data[op.top]!
='(')
{
exp[t]=op.data[op.top];
op.top--;
t++;
}
op.top++;
op.data[op.top]=ch;
break;
case'*':
case'/':
while(op.data[op.top]=='/'||op.data[op.top]=='*')
{
exp[t]=op.data[op.top];
op.top--;
t++;
}
op.top++;
op.data[op.top]=ch;
break;
case'':
break;
default:
while(ch>='0'&&ch<='9')
{
exp[t]=ch;t++;
ch=str[i];i++;
}
i--;
exp[t]='';
t++;
}
ch=str[i];
i++;
}
while(op.top!
=-1)
{
exp[t]=op.data[op.top];
t++;
op.top--;
}
exp[t]='\0';
}
floatcal_value(charexp[])
{
struct
{
floatdata[MaxSize];
inttop;
}st;
floatd;
charch;
intt=0;
st.top=-1;
ch=exp[t];
t++;
while(ch!
='\0')
{
switch(ch)
{
case'+':
st.data[st.top-1]=st.data[st.top-1]+st.data[st.top];
st.top--;
break;
case'-':
st.data[st.top-1]=st.data[st.top-1]-st.data[st.top];
st.top--;
break;
case'*':
st.data[st.top-1]=st.data[st.top-1]*st.data[st.top];
st.top--;
break;
case'/':
if(st.data[st.top]!
=0)
st.data[st.top-1]=st.data[st.top-1]/st.data[st.top];
else
{
printf("\n\terror");
}
st.top--;
break;
default:
d=0;
while(ch>='0'&&ch<='9')
{
d=10*d+ch-'0';
ch=exp[t];
t++;
}
st.top++;
st.data[st.top]=d;
}
ch=exp[t];
t++;
}
returnst.data[st.top];
}
intmain()
{
charch;
while
(1)
{
charstr[MaxSize],exp[MaxSize];
printf("请输入一个表达式:
\n");
gets(str);
printf("原表达式:
%s\n",str);
translate(str,exp);
printf("逆波兰式:
%s\n",exp);
printf("计算机结果:
%g\n",cal_value(exp));
printf("continueyorn?
:
");
scanf("%c",&ch);
if(ch=='Y'||ch=='y')
{
gets(str);
}
else
{
break;
}
}
//system("pause");
return0;
}