一、实验项目要求
1.实验目的
将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。
2.实验要求
输出的格式如下:
(1)逆波兰式的生成及计算程序,编制人:姓名,学号,班级
(2)输入一以#结束的中缀表达式(包括+—*/()数字#):在此位置输入符号串如(28+68)*2#
(3)逆波兰式为:28&68+2*
(4)逆波兰式28&68+2*计算结果为192
备注:
(1)在生成的逆波兰式中如果两个数相连则用&分隔,如28和68,中间用&分隔;
(2)在此位置输入符号串为用户自行输入的符号串。
注意:
1.表达式中允许使用运算符(+-*/)、分割符(括号)、数字,结束符#;
2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);
二、理论分析或算法分析
(一)准备
1.阅读课本有关章节,
2.考虑好设计方案;
3.设计出模块结构、测试数据,初步编制好程序。
(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立算符优先分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);
(3)控制部分:从键盘输入一个表达式符号串;
(4)利用算符优先分析算法进行表达式处理:根据算符优先分析表对表达式符号
串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
(5)对生成的逆波兰式进行计算。
(二)上课上机
将源代码拷贝到机上调试,发现错误,再修改完善。第二次上机调试通过。
三、实现方法
程序流程图如图所示:
四、实验结果分析
实验结果图
遇到的问题
(1)遇到如图所示的问题:
解决办法
(1)在文件顶部加入一行#define _CRT_SECURE_NO_WARNINGS后可以解决;
在本次实验中,对语法制导翻译原理有了进一步的理解;对逆波兰式的翻译过程在实践中的应用有了深刻地认识和理解,把所学的知识应用于实践中。更深刻的理解了编译原理的实际应用;本次试验激发了我的学习兴趣,培养了我独立发现问题、分析问题、解决问题的能力。也增强了我与同学交流沟通共同解决问题的能力;理解了编译原理和各个学科之间的融合渗透,锻炼了编程的能力,达到学以致用的目的。
五、代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#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("逆波兰式的生成及计算程序,编制人:孙志英,27号,1920542班 \n");
printf("输入一以#结束的中缀表达式(包括 + - * /() 数字 # ):");
// printf("******************************************\n");
// printf("算数表达式:");
i = 0; /*获取用户输入的表达式*/
do {
i++;
scanf("%c", &str[i]);
} while (str[i] != '#' && i != max);
sum = i;
t = 1; i = 1;
ch = str[i]; i++;
while (ch != '#') {
switch (ch) {
case '(': /*判定为左括号*/
top++; stack[top] = ch;
break;
case ')': /*判定为右括号*/
while (stack[top] != '(') {
ex[t] = stack[top]; top--; t++;
}
top--;
break;
case '+': /*判定为加减号*/
case '-':
while (top != 0 && stack[top] != '(') {
ex[t] = stack[top]; top--; t++;
}
top++; stack[top] = ch;
break;
case '*': /*判定为乘除号*/
case '/':
while (stack[top] == '*' || stack[top] == '/') {
ex[t] = stack[top]; top--; t++;
}
top++; stack[top] = ch;
break;
case ' ':break;
default:while (ch >= '0'&&ch <= '9') { /*判定为数字*/
ex[t] = ch; t++;
ch = str[i]; i++;
}
i--;
ex[t] = '&'; t++;
}
ch = str[i]; i++;
}
while (top != 0) {
ex[t] = stack[top]; t++; top--;
}
ex[t] = '#';
// printf("\n\t原来表达:");
// for(j=1;j<sum;j++)
// printf("%c",str[j]);
printf("\n逆波兰式为:", ex);
for (j = 1; j < t; j++)
printf("%c", ex[j]);
}
void compvalue() { /*计算后缀表达式的值*/
float stack[max], d; /*作为栈使用*/
char ch;
int t = 1, top = 0; /*t为ex下标,top为stack下标*/
ch = ex[t]; t++;
while (ch != '#') {
switch (ch) {
case '+':
stack[top - 1] = stack[top - 1] + stack[top];
top--;
break;
case '-':
stack[top - 1] = stack[top - 1] - stack[top];
top--;
break;
case '*':
stack[top - 1] = stack[top - 1] * stack[top];
top--;
break;
case '/':
if (stack[top] != 0)
stack[top - 1] = stack[top - 1] / stack[top];
else {
printf("\n\t除零错误!\n");
exit(0); /*异常退出*/
}
top--;
break;
default:
d = 0;
while (ch >= '0'&&ch <= '9') {
d = 10 * d + ch - '0'; /*将数字字符转化为对应的数值*/
ch = ex[t]; t++;
}
top++;
stack[top] = d;
}
ch = ex[t]; t++;
}
printf("\n逆波兰式");
for (int j = 0; j < t - 1; j++)
printf("%c", ex[j]);
printf("计算结果:%g\n", stack[top]);
}
void main() {
trans();
compvalue();
}