布尔表达式翻译为逆波兰式的算法实现

布尔表达式翻译为逆波兰式的算法实现
布尔表达式翻译为逆波兰式的算法实现

学号:

课程设计

题目布尔表达式的翻译程序设计

学院计算机学院

专业软件工程

班级

姓名

指导教师何九周

2012 年 1 月 2 日

布尔表达式的递归下降翻译程序设计

1引言

“编译原理”是一门研究设计和构造编译程序原理和方法的课程,是计算机各专业的一门重要的专业基础课。编译原理这门课程蕴含着计算机学科中解决问题的思路、形式化问题和解决问题的方法,对应用软件和系统软件的设计与开发有一定的启发和指导作用。“编译原理”是一门实践性较强的课程,要掌握这门课程中的思想,就必须要把所学到的知识付诸实践。而课程设计是将理论与实践相互联系的一种重要方式。

2概述

2.1设计题目

布尔表达式的递归下降翻译程序设计

2.2设计目的

课程设计是对学生的一种全面综合训练,是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节。通常,设计题中的问题比平时的练习题要复杂,也更接近实际。编译原理这门课程安排的课程设计的目的是旨在要求学生进一步巩固课堂上所学的理论知识,深化理解和灵活掌握教学内容,选择合适的数据逻辑结构表示问题,然后编制算法和程序完成设计要求,从而进一步培养学生独立思考问题、分析问题、解决实际问题的动手能力。

2.3设计任务内容

布尔表达式的文法:

B → TB′

B′→ and T B′|ε

T → FT ′

T′→ or FT′|ε

F → not F |true|false |(B)| i rop i

设计布尔表达式文法,给出该文法的属性文法,用递归下降分析法实现对布尔表达式的翻译,给出翻译的逆波兰式结果。

3设计环境与工具

Visual C++

4设计原则

4.1基本方法

在本程序中,输入一段布尔语句,使用递归下降的方法得到其推到过程,并利用递归下降翻译的方法的到四元式序列,最终根据生成的四元式序列分析得到逆波兰式。

4.2属性文法

B → TB′ B’.in=T.type

B′→ and T B′ B’.in=T.type addtype(and,entry,B.in)

B′→ε B’.val=ε

T → FT T.in=F.type.

T′→ or FT′ T’.in=F.type addtype(or,entry,B.in)

T′→ε T’val=ε

F → not F F.val= not.F.val

F → true F.val=true

F → false F.val=false

F →(B) F.val=B.val

F →i rop i F.val=i.lexval rop i.lexval addtype(i,entry,l.in)

5简要的分析与概要设计

在该程序中,总共包括3个主要功能,第一个功能是对输入的布尔语句进行递归下降的分析,从而得出从文法到该布尔语句的推导过程,第二个功能是使用递归下降的方法,该布尔语句的四元式序列,第三个功能对四元式序列进行扫描并分析每个四元式的结构特点,并据此将四元式转化为逆波兰式。

main 函数的流程图如下:

开始

递归下降分析得到推导过程并输出

递归下降分析得到四元式序列并输出

读四元式并得到逆波兰式并输出

结束

在开始进行本次实验中,本来计划在递归下降分析的过程中就得到逆波兰式,但是经过多次尝试之后总是存在错误,所以采用先得到四元式序列,再根据四元式序列生成逆波兰式这种效率比较低的方法。

6详细的算法描述,框图

6.1主要数据结构的设计

四元式类

在该类中,要包含四元式中的四个元素,运算结果,两个运算数以及一个运算符号

class quad

{

public:

char result[8];

char arg1[8];

char op[8];

char arg2[8];

void print()//输出该四元式

{

cout<

}

}q[20];

Word结构体

这个结构体的对要用来存储单个单词,包括一个字符串成员。struct word

{

char w[10];

void print()

{

cout<

}

}wr[200];

逆波兰式结构体

这个结构体的对象用来存储逆波兰式,它的成员是一个word数组struct nipolan

{

word nibolan[100];

} n;

翻译器类

用来存储翻译过程中的各个变量以及声明主要的函数:

class interpreter

{

private:

ifstream SourceFile;

char buffercode[200];//存放源码的缓冲区

int syn;

int current;//buffercode中当前读到的字符下标

char token[8];//记录当前读到的单词

public:

void scaner();

void B();

void B1();

void T();

void F();

void T1();

void run();

void read();

void bolon();

void toword();

char *factor();

char *expression();

char *term();

void bolan();

void reset()

{

current=0;

};

void run1()

{

scaner();

expression();

};

};

源程序:

/*

B TB′

B′ and T B′|ε T FT ′

T′ or FT′|ε

F not F |true|false |(B)| i rop i

*/

#include

#include

#include

int kk;

int tear=51;

int head=50;

int numberoftemp=0;

int numberofquad=0;

class quad

{

public:

char result[8];

char arg1[8];

char op[8];

char arg2[8];

void print()

{

cout<

}

}q[20];

void qemit(char a[],char b[],char c[],char d[])

{

strcpy(q[numberofquad].result,a);

strcpy(q[numberofquad].arg1,b);

strcpy(q[numberofquad].op,c);

strcpy(q[numberofquad].arg2,d);

numberofquad++;

}

char* newtemp()

{

char *p;

int temp=numberoftemp;

p=new char[8];

p[0]='t';

for(int i=0;;i++)

{

p[++i]=char(temp%10+48);

temp=temp/10;

if (temp==0) {p[i+1]='\0'; break;} }

numberoftemp++;

return p;

};

struct word

{

char w[10];

void print()

{

cout<

}

}wr[200];

struct nipolan

{

word nibolan[100];

} n;

int tcount=0;

int wcount=0;

char *rwtab[9]={"true","not","false","(",")","rop","i","or","and"}; class tuidao

{

public:

char a[10];

char b[10];

char c[10];

char d[10];

void emit(char *m,char *n,char *p,char *q);

void print() {cout<"<

}t[100];

void tuidao::emit(char *m,char *n,char *p,char *q)

{

strcpy(a,m);

strcpy(b,n);

strcpy(c,p);

strcpy(d,q);

}

class interpreter

{

private:

ifstream SourceFile;

char buffercode[200];

int syn;

int current;

char token[8];

public:

void scaner();

void B();

void B1();

void T();

void F();

void T1();

void run();

void read();

void bolon();

void toword();

char *unit();

char *expression();

char *term();

void bolan();

void reset()

{

current=0;

};

void run1()

{

scaner();

expression();

};

};

void bolan()

{

strcpy(n.nibolan[tear].w,q[0].arg1);tear++;

strcpy(n.nibolan[tear].w,q[0].arg2);tear++;

strcpy(n.nibolan[tear].w,q[0].op);tear++;

for(int i=0;i

{

for (int j=i-1;j>=0;j--)

{

if (strcmp(q[i].arg1,q[j].result)==0)

{

if (strcmp(q[i].arg2,q[j+1].result)==0) {strcpy(n.nibolan[tear].w,q[i].op);tear++;break;}

else

{

strcpy(n.nibolan[tear].w,q[i].arg2);tear++;

strcpy(n.nibolan[tear].w,q[i].op);tear++;

break;

}

}

if

((strcmp(q[i].arg1,q[j].result)!=0)&&(strcmp(q[i].arg2,q[j+1].result) ==0))

{

strcpy(n.nibolan[tear].w,q[i].op);tear++;

strcpy(n.nibolan[head].w,q[i].arg1);head--;

break;

}

if

((strcmp(q[i].arg1,q[j].result)!=0)&&(strcmp(q[i].arg2,q[j].result)!= 0))

{

strcpy(n.nibolan[tear].w,q[i].arg1);tear++;

strcpy(n.nibolan[tear].w,q[i].arg2);tear++;

strcpy(n.nibolan[tear].w,q[i].op);tear++;

break;

}

}

}

}

void interpreter::toword()

{

current=0;

int i=0;

while (buffercode[current]!='#')

{

scaner();

strcpy(wr[wcount].w,token);

wcount++;

i++;

}

};

void interpreter::read()

{

cin.getline(buffercode,200);

cout<

}

void interpreter::run()

{

current=0;

{

scaner();

B();

}

}

void interpreter::B()

{

t[tcount].emit("B"," ","T","B'");

tcount++;

T();

B1();

}

void interpreter::B1()

{

if

(strcmp(token,rwtab[8])==0){t[tcount].emit("B'","and","T","B'");tcoun t++;scaner();T();B1();scaner();}

else t[tcount].emit("B'","empty","","");

}

void interpreter::T()

{

t[tcount].emit("T","","F","T'");

tcount++;

F();

T1();

}

void interpreter::T1()

{

if

(strcmp(token,rwtab[7])==0){t[tcount].emit("T'","or","F","T''");tcoun t++;scaner();F();T1();}

else t[tcount].emit("T'","empty","","");

}

// F not F |true|false |(B)| i rop i

void interpreter::F()

{

if(strcmp(token,rwtab[1])==0){t[tcount].emit("F","not","F","");tc ount++;scaner();F();}

else

if(strcmp(token,rwtab[0])==0){t[tcount].emit("F","","true","");tcount ++;scaner();}

else if(strcmp(token,rwtab[2])==0) {t[tcount].emit("F","","false","");tcount++;scaner();}

else

if(strcmp(token,rwtab[3])==0){t[tcount].emit("F","(","B",")");tcount+ +;scaner();B();}

else

if(strcmp(token,rwtab[6])==0){t[tcount].emit("F","i","rop","i");tcoun t++;scaner();scaner();scaner();}

}

void interpreter::scaner()

{

int m=0;

for(int i=0;i<8;i++) token[i]=' ';

while (buffercode[current]==' ') current++;

if(((buffercode[current]>='a')&&(buffercode[current]<='z'))||((bu

ffercode[current]>='A')&&(buffercode[current]<='Z')))

{

while

((((buffercode[current]>='a')&&(buffercode[current]<='z'))||((bufferc ode[current]>='A')&&(buffercode[current]<='Z')))||((buffercode[curren t]>='0')&&(buffercode[current]<='9')))

{

token[m]=buffercode[current];m++;

current++;

}

token[m++]='\0';

}

else if (buffercode[current]=='(') {token[0]='(';token[1]='\0';current++;}

else if (buffercode[current]==')') {token[0]=')';token[1]='\0';current++;}

}

char*interpreter::expression()

{

char *tp,*ep2,*eplace,*tt;

tp=new char[8];

ep2=new char[8];

eplace=new char[8];

tt=new char[8];

strcpy(eplace,term());

while(strcmp(token,"or")==0)

{

strcpy(tt,token);

scaner();

strcpy(ep2,term());

strcpy(tp,newtemp());

qemit(tp,eplace,tt,ep2);

strcpy(eplace,tp);

}

return eplace;

}

char*interpreter::term()

{

char *tp,*ep2,*eplace,*tt;

tp=new char[8];

ep2=new char[8];

eplace=new char[8];

tt=new char[8];

strcpy(eplace,unit());

while (strcmp(token,"and")==0)

{

strcpy(tt,token);

scaner();

strcpy(ep2,unit());

strcpy(tp,newtemp());

qemit(tp,eplace,tt,ep2);

strcpy(eplace,tp);

}

// scaner();

return eplace;

}

char* interpreter::unit()

{

char *fplace;

fplace=new char[8];

if ((strcmp(token,"true")==0)||(strcmp(token,"false")==0)) {

strcpy(fplace,token);

scaner();

}

if(strcmp(token,"i")==0)

{strcpy(fplace,newtemp());qemit(fplace,"i","rop","i");}

if(strcmp(token,"(")==0)

{

scaner();

strcpy(fplace,expression());

if (syn==28){return fplace;}

}

if(strcmp(token,"not")==0)

{

char *fplace1=new char[8];

scaner();

if (strcmp(token,"(")==0)

strcpy(fplace1,expression());

else strcpy(fplace1,token);

strcpy(fplace,newtemp());qemit(fplace,"","not",fplace1);

if (syn==28){return fplace;}

}

// else{error(4);}

return fplace;

}

void main()

{

interpreter in;

cout<<"请输入源代码:"<

in.read();

in.run();

cout<<"推导过程为:"<

for(int i=0;i

t[i].print();

in.toword();

cout<<"分析的单词为:"<

for (i=0;i

wr[i].print();

cout<

cout<<"四元式为:"<

in.reset();

// cout<<"here"<

in.run1();

for(i=0;i

q[i].print();

cout<<"逆波兰式为:"<

bolan();

for(i=head;i

cout<

cout<

}

6.2全局变量设计

int tear=51;//逆波兰式尾部

int head=50;//逆波兰是首部

int numberoftemp=0;//临时变量个数

int numberofquad=0;//四元式个数

6.3递归下降得到推导过程

根据递归下降的思想,对于文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分。由于描述语言的文法常常是递归定义的,因此相应的这组函数必然以相互递归的方式进行调用。该过程的基本思想为每执行一个非终结符对应的函数就根据读入的单词符号来写入该非终结符对应的推出式。

该功能的入口函数run1的流程图如下:

开始

scaner()

B()

end

非终结符B对应的函数B()

该函数首先要写入B=>TB’,然后执行T()与B1()

流程图为

非终结符T对应的函数T()

该函数首先要写入T=>FT’,然后执行F()与T1()

流程图为:

非终结符B’对应的函数B1()

在该函数中如果读入的下一个单词是“and”则写入B’=>and T B’.否则,要写入B’推出了空串。

HUNAN UNIVERSITY 课程实习报告 题目逆波兰表达式求值 学生姓名XX 学生学号 专业班级 指导老师 完成日期

一、需求分析 1.本程序要求对用户输入一个后缀表达式,打印输出其结果。 2.后缀表达式有用户通过键盘输入,其中两相邻操作数之间利用空格隔开,以“#”表达结束。如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字,如果不正确,请在字符界面上输出表达式错误提示。 3.测试数据 输入 2 3*1-# 输出 5 二、概要设计 1.抽象数据类型 为实现上述程序的功能,应以一个字符数组存储用户的输入,运算中运用到整数及浮点数。 2.算法的基本思想 根据题目要求,计算后缀表达式,需要用到堆栈来实现。算法如下: 1)假设此表达式正确从字符串第一个开始扫描,遇到运算数就先转化成为数值然后压入堆栈中, 2)如遇到运算符则弹出堆栈上面的两个元素,并进行对应的运算,将得到的值压入栈中,循环计算,然后往堆栈中压入结果,直到最后一个字符为止。 3)若表达式错误:返回错误提示。 ADT: Stack{ 操作对象:字符,整数,浮点数 基本操作: Stack(int size);//构造大小为size的栈 ~Stack();//释放内存空间 void push(const float& n);//数据进栈 float pop();//数据出栈 int length();//计算栈内元素个数 } 3.程序的流程 程序由三个模块组成: 1)输入模块:输入一个表达式的字符串。 2)计算模块:设计一个计算后缀表达式的函数。 3)输出模块:输出显示计算的结果。 三、详细设计 1.算法的具体设计 算法流程图如下:

实验报告成绩:指导教师审核(签名):年月日 预习报告□实验报告□ 语法制导把表达式翻译成逆波兰式 (一)实验目的 进一步掌握语法制导翻译的概念,理解中间语言,设计出错处理程序方法,掌握把表达式翻译成中间语言的算法。 (二)实验内容 1.从左到右扫描中缀表达式,经语法分析找出中缀表达式出现的错误并给出错误的具体位置和类型。一个运算符栈存放暂时不能出现的运算符,逆波兰区存放逆波兰表达式。 2.测试所编程序,给出正确和错误的结果。 (三)实验要求 1.学生课前要认真阅读实验指导,理解实验内容与相关理论知识的关系,并完成预习报告 2.用C语言或其它高级语言编写程序 3.写出实验报告

实验报告成绩:指导教师审核(签名):年月日 预习报告□实验报告□ 语法制导把表达式翻译成逆波兰式 (一)实验目的 通过上机实习加深对语法指导翻译原理的理解,掌握运算符优先权的算法,将语法分析所识别的表达式变换成中间代码的翻译方法。 (二)实验内容 同预习报告 (三)实验要求 1.学生课前要认真阅读实验指导,理解实验内容与相关理论知识的关系,并完成预习报告 2.用C语言或其它高级语言编写程序 3.写出实验报告 (四)实验设计思路 1)表达式生成逆波兰式的算法 1、初始化△送到运算符栈。 2、扫描左括号“(”,把△送到运算符栈。 3、扫描到变量,把它送到逆波兰区。 4、扫描到运算符 ( 1)栈内运算符比较 a.栈内运算符>=栈外运算符,把栈内运算符送到逆波兰区。 b.栈内运算符<栈外运算符,把栈外运算符入栈。 ( 2 ) 栈内是△把运算符入栈。 5、扫描右括号“)”。 ( 1 )栈内是运算符,把栈内运算符送到逆波兰区。 ( 2 )栈内是△则△退栈,读入下一个字符。 6、扫描到#(结束符) ( 1 )栈内是运算符,把栈内运算符送到逆波兰区。 ( 2 )栈内是△结束,否则继续分析。

逆波兰表达式求值 一、需求分析 1、从键盘中输入一个后缀表达式,该表示包括加减乘除等操作符,以及正整数作为操 作数等。 2、用堆栈来实现 3、测试数据 输入:2 3 * 1 – # 输出:2 3 * 1 -- =5 二、概要设计 抽象数据类型 需要一个浮点数栈来存储还没有计算的浮点数或者运算的结果。 ADT Stack 数据成员:int size; int top; //分别用于存储栈大小、栈顶位置 float *listArray;//存储浮点型数字的数组 成员函数: bool push(float it); bool pop(float& it); bool isEmpty(); //判断栈为空 bool isOne();//判断栈是否只有一个元素 算法的基本思想 1.逐一扫描字符串,用ascii码进行判断,如果该字符是数字,则利用x=x*10+str[i]-48 将数据由字符类型转换为浮点型数据; 2.如果字符是‘.’,则将‘.’转化为小数点,并将‘.’后的数据转化为小数部分; 3.遇到空格前是数据的,将x押入栈; 4.如果该字符是’+’,’-’,’*’或’/’,判断栈里的元素是否少于两个个,如果少于两个, 报错;如果大于等于两个,就弹出两个数据,并进行相应的计算; 程序的流程 输入字符串,程序对字符串依次扫描。扫描一位,处理一位。扫描完成后,判断栈里是不是只有一个数据,若是,得到正确结果;若不是,则表达式出错。 三、详细设计 物理数据类型 用浮点数类型的栈存储运算中要用的数据,需要入栈、出栈,故设计如下的浮点类型的栈: class Stack { private: int size; int top; float *listArray; public: Stack(int sz=20); ~Stack();

课程设计 题目布尔表达式的LR翻译器学院计算机科学与技术学院专业软件工程 班级软件1102 姓名李帅奇 指导教师何九周 2014 年 1 月 2 日

课程设计任务书 学生姓名:李帅奇专业班级:软件1102 指导教师:何九周工作单位:计算机科学与技术学院 题目: 布尔表达式的LR翻译器 初始条件: 程序设计语言:主要使用C语言的开发工具,或者采用LEX、YACC等工具,也可利用其他熟悉的开发工具。算法:可以根据《编译原理》课程所讲授的算法进行设计。 要求完成的主要任务:(包括课程设计工作量及其技术要求,说明书撰写等具体要求) 1.明确课程设计的目的和重要性,认真领会课程设计的题目,读懂课程设计指导书的要求,学会 设计的基本方法与步骤,学会如何运用前修知识与收集、归纳相关资料解决具体问题的方法。严格要求自己,要独立思考,按时、独立完成课程设计任务。 2.主要功能包括:利用LR分析法编制、调试其语法及语义分析程序,生成的中间代码为四元式。 编制好分析程序后计若干用例,上机测试并通过所设计的分析程序。(参考教材P181~182)进行总体设计,详细设计:包括算法的设计和数据结构设计。系统实施、调试,合理使用出错处理程序。 3.设计报告:要求层次清楚、整洁规范、不得相互抄袭。正文字数不少于0.3万字。包含内容: ①课程设计的题目。 ②目录。 ③正文:包括引言、需求分析、总体设计及开发工具的选择,设计原则(给出语法分析方法及中间代码形式的描述、文法和属性文法的设计),数据结构与模块说明(功能与流程图)、详细的算法设计、软件调试、软件的测试方法和结果、有关技术的讨论、收获与体会等。 ④结束语。 ⑤参考文献。 ⑥附录:软件清单(或者附盘)。 时间安排: 消化资料、系统调查、形式描述1天 系统分析、总体设计、实施计划3天 撰写课程设计报告书1天 指导教师签名:2014年1月2日 系主任(或责任教师)签名:2014年1月2日

一.实验目的 1.深入理解算符优先分析法 2.掌握FirstVt和LastVt集合的求法有算符优先关系表的求法 3.掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化 二.实验内容及要求 将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。 程序输入/输出示例: 输出的格式如下: (1) (2)输入一以#结束的中缀表达式(包括+—*/()数字#) (3) (4)逆波兰式 备注:(1)在生成的逆波兰式中如果两个数相连则用&分隔,如28和68,中间用&分隔; 注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、数字,结束符#; 2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好); 3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照; 三.实验过程 1、逆波兰式定义 将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表达式也称做后缀式。逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。 2、产生逆波兰式的前提 中缀算术表达式 3、逆波兰式生成的实验设计思想及算法

(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。 (2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。 (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。 (4)如果不是数字,该字符则是运算符,此时需比较优先关系。 做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将此运算符栈顶的运算

编译原理上机报告 名称:逆波兰式的产生及计算 学院:信息与控制工程学院 专业:计算机科学与技术 班级:计算机1401班 姓名:叶达成 2016年11月4日

一、上机目的 通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。 1、选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR分析分析程序,并至少完成两个题目。 2、选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。 ⑴实验前的准备 按实验的目的和要求,编写语法分析程序,同时考虑相应的数据结构。 ⑵调试 调试例子应包括符合语法规则的算术表达式,以及分析程序能够判别的若干错例。 ⑶输出 对于所输入的算术表达式,不论对错,都应有明确的信息告诉外界。 ⑷扩充 有余力的同学,可适当扩大分析对象。譬如: ①算术表达式中变量名可以是一般标识符,还可含一般常数、数组元素、函数调用等等。 ②除算术表达式外,还可扩充分析布尔、字符、位等不同类型的各种表达式。③加强语法检查,尽量多和确切地指出各种错误。 二、基本原理和上机步骤 基本原理: 将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表达式也称做后缀式。逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。 上机步骤: (1)构造一个栈,存放运算对象。 (2)读入一个用逆波兰式表示的简单算术表达式。 (3)自左至右扫描该简单算术表达式并判断该字符,如果该字符是运算对象,则将该字符入栈。若是运算符,如果此运算符是二目运算符,则将对栈顶部的两个运算对象进行该运算,将运算结果入栈,并且将执行该运算的两个运算对象从栈顶弹出。如果该字符是一目运算符,则对栈顶部的元素实施该运算,将该栈顶部的元素弹出,将运算结果入栈。 (4)重复上述操作直至扫描完整个简单算术表达式的逆波兰式,确定所有字符都得到正确处理,我们便可以求出该简单算术表达式的值。 三、上机结果 程序清单: #include #include #include #include #include #include using namespace std;

中缀表达式转逆波兰式并求值 // 标题: 栈的应用——中缀表达式转逆波兰式 // 时间: 2015年4月14日// 所有者: Vae #include #include #include #include #include #define STACK_INIT_SIZE 100 #define STACKCREATE 10 #define OK 1 #define ERROR 0 typedef struct double_stack { int *num; int *index; }DOUBLESTACK; typedef struct SqStack { DOUBLESTACK top; DOUBLESTACK base; int stacksize; }SqStack; // 函数名: InitStack // 形参类型: SqStack * // 函数功能构造一个栈void InitStack(SqStack *S) { S->base.index = (int *)malloc(sizeof(int)*STACK_INIT_SIZE);

S->base.num = (int *)malloc(sizeof(int)*STACK_INIT_SIZE); if (!(S->base.num && S->base.index)) { printf("构造栈失败!\n"); exit(-1); } S->top.num = S->base.num; S->top.index = S->base.index; S->stacksize = STACK_INIT_SIZE; return ; } // 函数名: Push // 形参类型: SqStack *, int, int // 函数功能插入e为新的栈顶元素int Push(SqStack *S, int m, int n) { if ((S->top.num - S->base.num) >= S->stacksize) { S->base.index = (int *)realloc(S- >base.index,sizeof(int)*(STACK_INIT_SIZE+STACKCREATE)); S->base.num = (int *)realloc(S- >base.num,sizeof(int)*(STACK_INIT_SIZE+STACKCREATE)); if (!(S->base.num || S->base.index))

塔里木大学信息工程学院 论文 编译原理课程设计 课目:编译原理 学生姓名:\ 学号: 学生姓名 学号: 所属学院:信息工程学院 班级:

设计任务书 指导教师(签章): 年月日

摘要: 编译原理是计算机科学与技术专业最重要的一门专业基础课程,内容庞大,涉及面广,知识点多。编译原理旨在介绍编译程序构造的一般原理和基本方法。内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成。它是计算机科学与技术专业最重要的一门专业基础课程,内容庞大,涉及面广,知识点多。由于该课程教、学难度都非常大,往往费了大量时间而达不到预期教学效果俗语说:学习的最好方法是实践。本课程设计正是基于此,力求为学生提供一个理论联系实际的机会,通过布置一定难度的课题,要求学生独立完成。我们这次课程设计的主要任务是编程实现对输入合法的中缀表达式进行词法分析、语法分析,构造相应的逆波兰式,计算后缀表达式的值输出结果。比如中缀表达式:C*(E+F),其后缀表达式为:CEF+*。逆波兰式也叫后缀表达式,即将运算符写在操作数之后。通过实践,建立系统设计的整体思想,锻炼编写程序、调试程序的能力,学习文档编写规范,培养独立学习、吸取他人经验、探索前言知识的习惯,树立团队协作精神。同时,课程设计可以充分弥补课堂教学及普通实验中知识深度与广度有限的缺陷,更好地帮助学生从全局角度把握课程体系。 关键字:逆波兰式;语法分析;中缀表达式

1 课设综述 1.1 课设来源 在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,所以,这种表示法也称为中缀表示。对中缀表达式的计值,并非按运算符出现的自然顺序来执行其中的各个运算,而是根据算符间的优先关系来确定运算的次序,此外,还应顾及括号规则。因此,要从中缀表达式直接产生目标代码一般比较麻烦。相对的,逆波兰式在计算机看来却是比较简单易懂的结构。因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序。 1.2 设计意义 对于实现逆波兰式算法,难度并不大,但为什么要将看似简单的中缀表达式转换为逆波兰式,原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中缀表达式是非常复杂的结构。相对的,逆波兰式在计算机看来却是比较简单易懂的结构。因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序。在逆波兰式中,不存在运算符的优先级问题,也不存在任何括号,计算的顺序完全按照运算符出现的先后次序进行。比中缀表达式的求值要简单得多。1.3 设计目标 编写程序,实现逆波兰式的生成和计算。首先对输入的表达式进行词法分析,然后进行语法分析,最后进行逆波兰式的输出和计算。过实践,建立系统设计的整体思想,锻炼编写程序、调试程序的能力,学习文档编写规范,培养独立学习、吸取他人经验、探索知识的习惯。 1.4 遇到的问题 如何通过递归下降方法分析表达式,并且输出词法分析、语法分析过程及结果。如何实现把中缀表达式转换成后缀表达式,并计算表达式的结果。 1.5 需解决的关键技术 本次课程设计中的关键是:通过递归下降方法分析表达式,主要有词法分析和语法分析,输出分析结果,判断表达式是否合法。如何确定操作符的优先顺序,确定数据的进栈及出栈顺序,根据后缀表达式计算表达式的结果。以及如何编写、调试、修改代码。还要了解一个题目有许多种解决方法。锻炼我们的思维能力。

学号07 成绩 编译原理上机报告 名称:逆波兰式的产生及计算 学院:信息与控制工程学院 专业:计算机科学与技术 班级:计算机1401班 姓名:叶达成 2016年11月4日

一、上机目的 通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。 1、选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR分析分析程序,并至少完成两个题目。 2、选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。 ⑴实验前的准备 按实验的目的和要求,编写语法分析程序,同时考虑相应的数据结构。 ⑵调试 调试例子应包括符合语法规则的算术表达式,以及分析程序能够判别的若干错例。 ⑶输出 对于所输入的算术表达式,不论对错,都应有明确的信息告诉外界。 ⑷扩充 有余力的同学,可适当扩大分析对象。譬如: ①算术表达式中变量名可以是一般标识符,还可含一般常数、数组元素、函数调用等等。 ②除算术表达式外,还可扩充分析布尔、字符、位等不同类型的各种表达式。③加强语法检查,尽量多和确切地指出各种错误。 二、基本原理和上机步骤 基本原理: 将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表达式也称做后缀式。逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。 上机步骤: (1)构造一个栈,存放运算对象。 (2)读入一个用逆波兰式表示的简单算术表达式。 (3)自左至右扫描该简单算术表达式并判断该字符,如果该字符是运算对象,则将该字符入栈。若是运算符,如果此运算符是二目运算符,则将对栈顶部的两个运算对象进行该运算,将运算结果入栈,并且将执行该运算的两个运算对象从栈顶弹出。如果该字符是一目运算符,则对栈顶部的元素实施该运算,将该栈顶部的元素弹出,将运算结果入栈。 (4)重复上述操作直至扫描完整个简单算术表达式的逆波兰式,确定所有字符都得到正确处理,我们便可以求出该简单算术表达式的值。 三、上机结果 程序清单: #include #include<> #include<> #include #include #include using namespace std;

HUNAN UNIVERSITY 课程实习报告 题目长浮点型逆波兰表达式求值 学生姓名毛宇锋吴淑珍王小玉 学生学号16 20 22 专业班级信息安全一班 指导老师夏艳刘炜 完成日期2014.4.8

一、需求分析 读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。 二、概要设计 抽象数据类型 为实现上述程序的功能,应以数据元素为长浮点型的栈来存储用户的输入,以及计算出的结果。 算法的基本思想 由于读入屏幕的字符,所以第一步是区分字符代表数值还是运算符,此外,还应该对字符是否为小数点做一个特别的判断。当确定系统读入的是数值时,应以double型将数值压入栈中,当确定读入的是运算符时,首先判断当前栈中的数值是否够运算(即至少有两个元素在栈中),满足该条件后分别弹出栈顶的两个元素,然后对其进行系统要求的运算,重新压入栈中。 程序的流程 程序由三个模块组成: (1)输入模块:循环输入字符,当遇到#号时结束 (2)计算模块:将输入的字符转化为相应的长浮点型数字并输出 (3)输出模块:显示最终计算结果 三、详细设计 物理数据类型 设计的关键在于读取字符型并转化为长浮点型 算法的具体步骤 循环输入字符串 1.判断当前的输入是否为数字,当结果为真时,执行字符串转换为长浮点型数的函数; 2.判断是否为操作符,并给定每一个操作符返回相应的计算结果。 算法的时空分析 由于在循环内的操作都为时间复杂度为θ(1)的,故算法的时间复杂度取决于输入字符的多少,令输入的字符为n时,算法的时间复杂度应该为θ(n)。 空间复杂度:给定栈的大小为10,即允许最多压入十个元素而不进行任何运算,由于逆波兰表达式通常最多输入两个元素即进行一次运算,所以栈的大小至少为2,这里给定10在空间的开销也很小。 输入和输出的格式 输入:在字符界面上输入一个后缀表达式,其中两相邻操作数之间利用空格隔开。以“#”表示结束。 输出:如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字,如果不正确,请在字符界面上输出表达式错误提示。 五、测试结果 为了验证测试具有普遍性,分别用个位整数、个位小数、多位整数、多位小数进行运算,如输入:4 0.2 + 10 * 3.6 – 3 / 即计算((4+0.2)*10-3.6)/3 结果应该等于12.8 下图为程序运行结果:

实验三波兰式和四元式及计算 课程编译原理实验名称波兰式和四元式第页班级11计本学号姓名 实验日期:2013年月日报告退发(订正、重做) 一、实验目的: 将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。 二、实验说明 1、逆波兰式定义 将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表达式也称做后缀式。逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。 2、产生逆波兰式的前提 中缀算术表达式 3、逆波兰式生成的实验设计思想及算法

(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。 (2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。 (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。 (4)如果不是数字,该字符则是运算符,此时需比较优先关系。 做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。 (5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得 到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。 3、逆波兰式计算的实验设计思想及算法 (1)构造一个栈,存放运算对象。 (2)读入一个用逆波兰式表示的简单算术表达式。 (3)自左至右扫描该简单算术表达式并判断该字符,如果该字符是运算对 象,则将该字符入栈。若是运算符,如果此运算符是二目运算符,则将对栈顶部的两个运算对象进行该运算,将运算结果入栈,并且将执行该运算的两个运算对象从栈顶弹出。如果该字符是一目运算符,则对栈顶部的元素实施该运算,将该栈顶部的元素弹出,将运算结果入栈。 (4)重复上述操作直至扫描完整个简单算术表达式的逆波兰式,确定所有 字符都得到正确处理,我们便可以求出该简单算术表达式的值。

数据结构—中缀表达式转后缀表达式算法及实现—栈的应用—计算表达式(C++代... 理论:(这部分很重要,看明白了,可以写出实现算法) 表达式的表示形式有中缀、前缀和后缀3中形式。中缀表达式按操作符的优先级进行计算(后面代码实现只包括+、-、*、\,小括号),即数学运算。后缀表达式中只有操作数和操作符。操作符在两个操作数之后。它的计算规则非常简单,严格按照从左到右的次序依次执行每一个操作。每遇到一个操作符,就将前面的两个数执行相应的操作。 由后缀表达式计算中缀表达式原理:计算机处理后缀表达式求值问题是比较方便的,即将遇到的操作数暂存于一个操作数栈中,凡是遇到操作数,便从栈中pop出两个操作数,并将结果存于操作数栈中,直到对后缀表达式中最后一个操作数处理完,最后压入栈中的数就是后最表达式的计算结果。 中缀表达式转换为等价的后缀表达式 中缀表达式不方便与计算机处理,通常要讲中缀表达式转换为一个与之等价的后缀表达式。等价是指两个表达式的计算顺序和计算结果完全相同。 中缀表达式:0.3/(5*2+1)# 的等价后缀表达式是:0.3 5 2 * 1 + /# 仔细观察这两个等价的表达式可知,操作数的出现次序是相同的,但运算符的出现次序是不同的。在后缀表达式中,运算符的出现次序是实际进行操作的次序;在中追表达式中,由于受到操作符的优先级和括号的影响,操作符出现次序与实际进行操作的次序很可能是不一样的。

算法描述: 将中缀表达式转换为等价的后缀表达式的过程要使用一个栈放“(”,具体可以按照下面的方式进行。 (1)从左到右一次扫描中缀表达式的每一个字符,如果是数字字符和圆点“.”则直接将它们写入后缀表达式中。 (2)如果遇到的是开括号“(”,则将它们压入一个操作符栈(不需要与栈顶操作符相比较),它表明一个新的计算层次的开始,在遇到和它匹配的闭括号“)”时,将栈中的元素弹出来并放入后缀表达式中,直到栈顶元素为“(”时,将栈顶元素“(”弹出(不需要加入后缀表达式),表明这一层括号内的操作处理完毕。 (3)如果遇到的是操作符,则将该操作符和操作符栈顶元素比较: 1、当所遇到的操作符的优先级小于或等于栈顶元素的优先级时,则取出栈顶元素放入后缀表式, 并弹出该栈顶元素,反复执行直到栈顶元素的优先级小于当前操作符的优先级; 2、当所遇到的操作符的优先级大于栈顶元素的优先级的时则将它压入栈中。 (4)重复上述步骤直到遇到中缀表达式的结束符标记“#”,弹出栈中的所有元素并放入后缀表达式中,转换结束。 如果有算法方描述的不清楚,敬请网友指出,本人表达能力较差,欢迎提出问题。 C++ 代码描述算法:

一、需求分析 1.从键盘中输入一个后缀表达式,该表达式包括加减乘除等操作符,以及正整数做诶操作数等。 2.需要利用堆栈来实现。 3.在Visual C++6.0界面操作。 问题描述: 读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要校验后缀表达式是否正确。 测试数据用例 (1)输入:2 3 * 1 - # 输出:5 (2)输入:2 3 * 1 - * # 输出:表达式有误 (3)输入: 2 0 / 4 * # 输出:表达式有误 二、概要设计 抽象数据类型 为实现上述程序的功能,则以字符型数据存储用户的输入。若为数值,则用自定义函数将其转化为整形数据;若为操作符,则仍为字符型数据,以便计算出的结果。 算法的基本思想 根据题目要求,采用堆栈来实现。该算法的基本思想是运用自定义函数求解逆波兰表达式求值问题问题。 程序的流程 程序由三个模块组成: (1)输入模块:完成表达式的输入,存入栈S中。 (2)计算模块:利用自定义函数,计算逆波兰表达式的值。 (3)输出模块:屏幕上显示出最终计算结果。 三、详细设计

物理数据类型 程序中要求输入的表达式为任意的,但必须以#标志表达式输入的结束,只有正确的逆波兰表达式才能显示出最终计算结果。 算法的具体步骤 算法的具体步骤为: 建立一个名为s的栈。 将表达式的值一个个压入栈S中。在循环中,需要分类讨论:如果表达式中的值为“#”,则将#前的元素弹出栈中;如果表达式中的值为空格,那么继续压入,如果表达式中的值为0至9的字符,则要通过一个自定义的转换函数将其转换为int型数值;如果连续几个0至9的字符中间无空格隔开,则在计算中应将其还原为多位数;若表达式中的值为运算符,则要将栈S中所压入数值弹出栈,进行相应的计算后,再将结果压入栈中(值得注意的是,运算符是不入栈的);除此之外的情况都归类为输入的表达式错误。 相应的入栈出栈及数值计算部分都由自定义函数来完成。 输入和输出的格式 输入 在字符界面上输入一个后缀表达式,其中两相邻操作数之间利用空格隔开。以“#”表示结束。 输出 如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字,如果不正确,请在字符界面上输出表达式错误提示。 四、调试分析 略。(已在老师面前调试) 五、测试结果

HUNAN UNIVERSITY 数据结构实验报告 题目逆波兰表达式求值 学生姓名王家威 学生学号201308070217 专业班级智能科学与技术1302 指导老师朱宁波

一、问题描述: 读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确 注释:后缀表达式—将运算符放在两操作数的后面。后缀表达式也称逆波兰表达式,因其使表达式求值变得轻松,所以被普遍使用。 后缀表示法有三个特征: (1)操作数的顺序与等价的中缀表达式中操作数的顺序一致 (2)不需要括号 (3)操作符的优先级不相关 二、基本要求: (1)从键盘中输入一个后缀表达式,该表示包括加减乘除等操作符,以及正整数作为操作数等。 (2)用堆栈来实现逆波兰表达式 (3)判断该表达式是否正确。 三、输入输出格式 输入输出格式 输入: 在字符界面上输入一个后缀表达式,其中两相邻操作数之间利用空格隔开。以“ #”表示结束。 输出: 如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字,如果不正确,请在字符界面上输出表达式错误提示。 四、具体设计过程 ①算法思想: (1)首先因为计算后缀表达式有先进后出,后进先出的规律,因而符合堆栈的思想。因而使用堆栈实现。 (2)其次,因为我们需要操作一串字符,因此还需要一个字符数组来存放这些字符。

(3)另外我们需要通过if语句来判断表达式的正误。 ②程序基本流程 首先假设此表达式正确从字符串第一个开始扫描,遇到运算数就先转化成为数值然后压入堆栈中, 如遇到运算符则弹出堆栈上面的两个元素(根据后缀表达式,我们知道运算符前的两个为两个操作数),并进行对应的运算,将得到的结果压入栈中,直到最后一个字符为止。 假设表达式不正确的情况,(1)是输入的数字格式不正确,例如输入数字为小数时,直接从.开始(2)表达式最后栈中还有两个或更多数(3)表达式栈中只有一个数时,仍然碰到了运算符,则我们输出“输入的逆波兰表达式错误”。 五、实验代码: CString CMFCDlg::fun(CString s) { int leng=s.GetLength(); CString C; float *stack,result; stack=new float[leng]; int i=0,j=0; int top=0; while(s[i]!='#') { if(s[i]!='+'&&s[i]!='-'&&s[i]!='*'&&s[i]!='/'&&s[i]!=' ') { if(s[i]!='.') { float zs=0,xs=0; while(s[i]!=' ') { j=i; while(s[i]!='.'&&s[i]!=' ') { zs=zs*pow(10.0,i-j)+(s[i]-'0'); i++; } j=i; if(s[i]=='.')

(编译原理)逆波兰式算法的源代码

————————————————————————————————作者:————————————————————————————————日期:

一.实验目的 1.深入理解算符优先分析法 2.掌握FirstVt和LastVt集合的求法有算符优先关系表的求法 3.掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化 二.实验内容及要求 将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。 程序输入/输出示例: 输出的格式如下: (1)逆波兰式的生成及计算程序,编制人:姓名,学号,班级 (2)输入一以#结束的中缀表达式(包括+—*/()数字#):在此位置输入符号串如(28+68)*2# (3)逆波兰式为:28&68+2* (4)逆波兰式28&68+2*计算结果为192 备注:(1)在生成的逆波兰式中如果两个数相连则用&分隔,如28和68,中间用&分隔;(2)在此位置输入符号串为用户自行输入的符号串。 注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、数字,结束符#; 2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好); 3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以 分号分割。同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照; 三.实验过程 1、逆波兰式定义 将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表达式也称做后缀式。逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。 2、产生逆波兰式的前提 中缀算术表达式 3、逆波兰式生成的实验设计思想及算法

package hfw.util; import java.util.ArrayDeque; import java.util.Deque; /** * *逆波兰式 *总结,java版的Eval:逆波兰和动态编译,推荐用动态编译,因为逆波兰式不认识"- 4",只认识"-4" *@author zyh */ public class RNP { /** * 运算数 */ private static Deque operationNum = new ArrayDeque(); /** * 运算符 */ private static Deque operator = new ArrayDeque(); /** * 将表达式转换为逆波兰式 * @param expression * @return */ private static void str2Rnp(String expression){ operationNum.clear(); operator.clear(); int index = 0; for(int i=0;i

C语言课程设计之逆波兰表达式 //逆波兰表达式(后缀表达式)reverse polish notation //程序实现的功能是将中缀表达式转变为后缀表达式,再求出其值 //主要运用的知识点有:isdigit函数,pow函数,system("cls")函数,堆栈,格式的强制转换 #include #include #include #include void shift( char notation[]); //中缀表达式转换为后缀表达式的转换函数 float calculate(float a[][2],int k); //计算后缀表达式 int judge(char notation[]); //判断输入的中缀表达式是否符合要求 int grade(char a); //返回运算符的等级 void display(float a[][2],int k); //在屏幕上显示后缀表达式 //主函数 void main() { char notation [100]; char choice; do { printf("请输入正确的中缀表达式:\n"); printf("例如:2*3+4/3-(2+1)\n"); scanf("%s",¬ation); if(judge(notation)) { shift(notation); } else printf("你的表达式有错误,请仔细检查!\n"); fflush(stdin); printf("\n你是否需要继续计算(是输入Y/y,否输入其他任意键)\n"); scanf("%c",&choice); getchar(); system("cls"); }while(choice=='Y'||choice=='y'); printf("\n程序结束,谢谢使用!\n"); } //判定函数 int judge(char notation[]) {

实验报告 姓名:孙岩 学号:1408080211 班级:惠普开发142 学校:青岛科技大学Mail: 632928843@https://www.360docs.net/doc/e417849353.html, 电话:178******** 教师:宮生文

实验报告: 实验名称:逆波兰式分析 实验目的和要求 将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。 实验内容和步骤: 一、实验内容 对于这个实验,总共用了三个函数,即主函数、算术表达式转换为后缀表达式函数、根据后缀表达式求取表达式的计算值。 主要完成的功能是接收一个包含加减乘除以及括号的算数表达式,进而将其转换为后缀表达式,从而通过此后缀表达式求出该算数表达式的值。 二、实验步骤 1、基于实验的内容,构造程序所需的模块 2、根据已建构的模块,写出各个模块的相应程序代码 3、在主函数中调用模块来完成所要得到的效果 在本程序中,首先定义了数组常量ex[max],用于存储后缀表达式,操作对象在前,运算符在后;其次,是trans()函数,它的作用是将算数表达式转换为后缀表达式;其次是compvalue()函数,它的作用是根据后缀表达式求取对应算数表达式的算数值;最后是主函数模块,主要是通过对以上几个模块的调用。 实验代码如下: #include #include #include #define max 100 char ex[max]; /*存储后缀表达式*/ void trans(){ /*将算术表达式转化为后缀表达式*/ char str[max]; /*存储原算术表达式*/ char stack[max]; /*作为栈使用*/ char ch; int sum,i,j,t,top=0; printf("*****************************************\n"); printf("*输入一个求值的表达式,以#结束。*\n"); printf("******************************************\n"); printf("算数表达式:"); i=0; /*获取用户输入的表达式*/ do{ i++; scanf("%c",&str[i]); }while(str[i]!='#' && i!=max);

一、题目 ◆3.21③假设表达式由单字母变量和双目四则运 算算符构成。试写一个算法,将一个通常书写形式 且书写正确的表达式转换为逆波兰式。 实现下列函数: char *RPExpression(char *e); /* 返回表达式e的逆波兰式 */ Stack是一个已实现的栈。 可使用的相关类型和函数: typedef char SElemType; // 栈Stack的元素类型 Status InitStack(Stack &s); Status Push(Stack &s, SElemType e); Status Pop(Stack &s, SElemType &e); Status StackEmpty(Stack s); SElemType Top(Stack s); ------------------------------------------------------------------------------------------------- 二、思路

拿到题目,要做的第一件事情,就是搞懂题目究竟要我们做什么,很显然,题目中的关键字是“逆波兰式”,那么首先我们要搞懂这个概念。 所谓的逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。逆波兰记法不需要括号来标识操作符的优先级。(摘自维基) 举个简单的例子,平常我们写的数学表达式a+b,就是一种中缀表达式,写成后缀表达式就是ab+。再举一个复杂的例子,中缀表达式(a+b)*c-(a+b)/e的逆波兰式是ab+c*ab+e/-。 在弄清楚概念以及题目的要求之后,接下来就要编写算法了。那么将一个表达式转换为逆波兰式的算法思想是什么呢? (1)首先,需要分配2个栈,栈s1用于临时存储运算符(含一个结束符号),此运算符在栈内遵循越往栈顶优先级越高的原则;栈 s2用于输入逆波兰式,为方便起见,栈s1需先放入一个优先级最低的运算符,在这里假定为'#'; (2)从中缀式的左端开始逐个读取字符x,逐序进行如下步骤: 1.若x是操作数,则分析出完整的运算数(在这里为方便,用字母代替数字),将x直接压入栈s2;

相关文档
最新文档