课程名称:数据结构
实验目的:
1.掌握栈的定义及实现;
2.掌握利用栈求解算术表达式的方法。
实验要求:
1、 使用链式存储结构完成栈的各种基本操作;
2、 补充完成In©, Preced(t1,t2),Operate(a,theta,b)三个函数。
实验题目:栈的基本操作及其应用
实验过程:
1、通过修改完善教材中的算法3.22,利用栈来实现算术表达式求值的算法。对算法3.22中调用的几个函数要给出其实现过程:
(1) 函数In©:判断c是否为运算符;
(2) 函数Precede(t1,t2):判断运算符t1和t2的优先级;
(3) 函数Operate(a,theta,b):对a和b进行二元运算theta。
2、程序运行时,输入合法的算术表达式(中间值及最终结果要在0~9之间,可以包括加减乘除和括号),便可输出相应的计算结果。
实验提示:(仅供参考,每个函数的具体实现可以有多种方法,希望有创新)
- 将栈的定义和实现单独保存在头文件“stack.h”中,然后在表达式求值的源程序中包含此头文件(即#include“stack.h”)。
2.表达式求值源程序的具体实现
(1) 主函数如下:
void main()
{
Printf(“请输入算术表达式,并以#结束.\n”);
Printf(“the result of expression is:%d\n”,EvaluateExpression());
}
(2) 函数EvaluateExpression的实现见算法3.22
(3) 函数In©的实现可以采用以下方式:
Status In(SElemType c)// 应在前面有定义typedef char SElemType;
{ // 判断c是否为运算符
switch©
{
case'+':return TRUE;
……//补充完整default:return FALSE;
}
}
(4) 函数Precede(t1,t2)的实现可以采用以下形式:
SElemType Precede(SElemType t1,SElemType t2)
{ //根据教材表3.1,判断两个运算符的优先关系
SElemType f;
switch(t2)
{
case '+':
case '-':if(t1=='('||t1=='#')
f='<';
else
f='>';
break;……//补充完整
}
return f;
}
(5) 函数Operate(a,theta,b)的实现可以采用以下方式:
SElemType Operate(SElemType a,SElemType theta,SElemType b)
{
SElemType c;
a=a-48;
b=b-48;
switch(theta)
{
case'+':c=a+b+48;
break;……//补充完整
}
return c;
}
选做内容:进一步改进,使表达式的中间值及最终结果不局限于0~9之间的个位数。(如果完成要在实验报告中注明),如下图:
实验结果:
输入:2*(4-1)+8
输出:14
该程序能够完成个位数的四则运算。
实验分析:
1.栈的操作的特点;
2.列举调试运行过程中出现的错误并分析原因。
要求:
(1) 程序要添加适当的注释,程序的书写要采用缩进格式。
(2) 程序要具在一定的健壮性,即当输入数据非法时,程序也能适当地做出反应。
(3) 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。
(4) 上传源程序到课堂派,源程序保存为calculator.cpp。
.
.
.(给个赞再走呗)
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define TRUE 1
#define FALSE 0
typedef int status;
#define MAXSIZE 100
typedef struct stacknode//链栈的存储结构
{
char data;
struct stacknode *next;
}StackNode,*linkstack;
status InitStack(linkstack &s)//构建一个空栈s,栈顶指针置空
{
s=NULL;
return OK;
}
status Push(linkstack &s,char e)//在栈顶插入元素
{
linkstack p;//生成新的结点
p=(stacknode*)malloc(sizeof(stacknode));
if(!p) exit(OVERFLOW);// 若初始化失败则返回错误
p->data=e;//将新节点数据域置为e
p->next=s;//将结点插入栈顶
s=p;//修改栈顶指针为p
return OK;
}
status Pop(linkstack &s,char &e)//删除s的栈顶元素,用e返回其值
{
linkstack p;
if(s==NULL) return ERROR;//如果栈为空则返回错误
e=s->data;//栈顶元素赋给e
p=s;//用p保存栈顶空间准备释放
s=s->next;//修改栈顶指针
free(p);//释放原栈顶的空间
return OK;
}
char GetTop(linkstack s)//返回栈顶的元素,并且不修改栈顶指针
{
if(s==NULL)exit(1);//栈为空则返回错误
else return s->data;//返回栈顶元素的值,栈顶指针不变
}
bool In(char c)
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='#') return 1;
else return 0;
}
//比较OPTR栈顶元素和ch的优先级(运算符的优先级)
char Precede(char t1,char t2)
{
char f;
if(t1=='+'||t1=='-')
{
if(t2=='*'||t2=='/'||t2=='(') f='<';
else f='>';
}
else if(t1=='*'||t1=='/')
{
if(t2=='(') f='<';
else f='>';
}
else if(t1=='(')
{
if(t2==')') f='=';
else f='<';
}
else if(t1==')')
{
f='>';
}
else if(t1=='#')
{
if(t2=='=') f='=';
else f='<';
}
return f;
}
char Operate(char a,char theta,char b)//对出栈的两个数和操作符进行计算处理
{
char ans;
if(theta=='+') ans=(a-'0')+(b-'0')+'0';
else if(theta=='-') ans=(a-'0')-(b-'0')+'0';
else if(theta=='*') ans=(a-'0')*(b-'0')+'0';
else if(theta=='/') ans=(a-'0')/(b-'0')+'0';
return ans;
}
char EvaluateExpression()
{
printf("请输入一个表达式:");
StackNode *OPND;//定义运算数栈
StackNode *OPTR;//定义运算符栈
InitStack(OPND); //初始化OPND栈,压入操作数和运算结果
InitStack(OPTR); //初始化OPTR栈,压入操作符
Push(OPTR,'#'); //将表达式起始符'#'压入OPTR栈顶
char ch;
while(ch!='#'||GetTop(OPTR)!='#') //用ch!='#'来判断表达式是否扫描完毕,表达式
{ //没有扫描完毕或OPTR栈顶元素不为'#'则继续执行
if(!In(ch))
{
Push(OPND,ch);
scanf("%c",&ch);
}
else
switch(Precede(GetTop(OPTR),ch))
{
case '<':
Push(OPTR,ch);scanf("%c",&ch);
break;
case '>':
char theta;
char a,b;
Pop(OPTR,theta);
Pop(OPND,b);
Pop(OPND,a);
Push(OPND,Operate(a,theta,b));
break;
case '=':
char x;
Pop(OPTR,x);
scanf("%c",&ch);
break;
}
}
return GetTop(OPND);
}
int main()
{
printf("请输入算术表达式,并以#结束\n");
printf("the result of expression is:%c\n",EvaluateExpression());
return 0;
}