当前位置:文档之家› 逆波兰式求值

逆波兰式求值

一、需求分析
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中所压入数值弹出栈,进行相应的计算后,再将结果压入栈中(值得注意的是,运算符是不入栈的);除此之外的情况都归类为输入的表达式错误。

相应的入栈出栈及数值计算部分都由自定义函数来完成。

输入和输出的格式
输入
在字符界面上输入一个后缀表达式,其中两相邻操作数之间利用空格隔开。

以“#”表示结束。

输出
如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字,如果不正确,请在字符界面上输出表达式错误提示。

四、调试分析
略。

(已在老师面前调试)
五、测试结果
六、实验心得(可选)
本次实验是我第一次接触用栈来编写的程序,发现自己对栈的定义及使用还是不够熟悉;发现自己的逻辑严密性不够,在今后的编程过程中要注意加强这方面的能力。

(这个C程序是老师给我们调试了两节课所得,并不是我做实验的程序,但是觉得这个程序给我印象更深刻,故写入实验报告。


七、附录(可选)
//用栈来实现逆波兰式求值问题
#include"stdio.h"
#include"stdlib.h"
#define STACK_INIT_SIZE 100//栈的存储空间初始分配
#define STACKINCREMENT 10// 存储空间分配增量
#define TRUE 1
#define False 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;//相当于定义一个数据结构类型
typedef int SElemtype;
typedef struct
{
SElemtype *base;
int top;
int stacksize;
} SqStack;
Status InitStack(SqStack &S )
{
S.base = (SElemtype *)malloc(STACK_INIT_SIZE*sizeof(SElemtype));
if (! S.base) exit(OVERFLOW);
S.top = -1;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
int StackLength(SqStack S)
{
//获得堆栈元素的个数
return S.top+1;
}
Status Push(SqStack &S, SElemtype e)
{
//入栈
//填空
if(S.top ==99)
{//栈满
return ERROR;
}
S.base[++S.top] = e;
return OK;
}
Status Pop(SqStack &S, SElemtype &e)
{
//出栈
if(S.top==-1)return ERROR;
e=S.base[S.top--];
return OK;
}
Status IsDigital(char ch)
{
if(ch>='0'&&ch<='9')
{
return 1;
return 0;
}
int EvalValue(char *ch, SqStack &S)
{//将字符型数字转换为int型
int i=0;
SElemtype result=0;
char a;
a=ch[i];
while(IsDigital(a))
{
result=10*result+(int)(a-48);
a=ch[++i];
}
Push(S, result);
return i;
}
void EvalExpr(char ch, SqStack &S)
{
//如果ch中保存的是操作符,则从堆栈中弹出两个元素,并把操作符应用在这两个元素之上,然后把操作结果压入到栈中。

如果试图从栈中弹出两个元素是,该栈中并没有,那么该后缀表达式是不正确的。

SElemtype a,b;
Pop(S,a);
Pop(S,b);
switch(ch)
{
case '+':Push(S,a+b);break;
case '-':Push(S,b-a);break;
case '*':
Push(S,a*b);break;
case '/':if(a) Push(S,b/a);break;
default: printf("ERROR");
}
}
Status evaluate (char ch[], float & result)
{
SqStack S;
Status St;
int i;
i=0;
St = InitStack(S);
while(ch[i]!='#'&&i<100)
{
if(IsDigital(ch[i]))
{
i+=EvalValue(&ch[i], S);
}
else if(ch[i]==' ')
i++;
else{
EvalExpr(ch[i], S);
i++;
}
}
//如果到达表达式末尾时,栈中剩余元素不止一个,那么该后缀表达式是不正确的。

int a;
if(StackLength(S) ==1)
{
Pop(S,a);
result=(float)a;
}
else
{
printf("表达式错误");
return ERROR;
}
return OK;
}
main()
{
Status St;
char ch[100],c;
int i=0;
float result;
printf("请输入表达式。

#表示结束\n");
while(i<100)
{
scanf("%c",&c);
ch[i++]=c;
if(c=='#')
break;
}
ch[i] = '\0';
St = evaluate (ch, result);
if (St)
printf("result is %10.2f \n", result);
else
printf("\n表达式错误\n");
return 0;
}。

相关主题