数据结构第二次作业(表达式求值【栈模拟】)

实验题目:栈的应用-算术表达式求值                      

实验目的

1.掌握栈的定义及实现;

2.掌握利用栈求解算术表达式的方法。

实验内容:

通过修改完善教材中的算法3.4,利用栈来实现算术表达式求值的算法。对算法3.4中调用的几个函数要给出其实现过程:

(1) 函数In(c):判断c是否为运算符;

(2) 函数Precede(t1,t2):判断运算符t1和t2的优先级;

(3) 函数Operate(a,theta,b):对a和b进行二元运算theta。

程序运行时,输入合法的算术表达式(中间值及最终结果要在0~9之间,可以包括加减乘除和括号),便可输出相应的计算结果。如下图:

 

 

实验提示 (仅供参考,每个函数的具体实现可以有多种方法,希望有创新)

1. 将栈的定义和实现单独保存在头文件“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(c)的实现可以采用以下方式:

Status In(SElemType c)//应在前面有定义typedef char SElemType;

 { // 判断c是否为运算符

   switch(c)

   {

     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之间的个位数。(如果完成要在实验报告中注明),如下图:

 

 

实验要求

(1) 程序要添加适当的注释,程序的书写要采用缩进格式

(2) 程序要具在一定的健壮性,即当输入数据非法时, 程序也能适当地做出反应。

(3) 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。

(4) 根据实验报告模板详细书写实验报告,在实验报告中给出表达式求值算法的流程图


#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#include<stack>
#include<iostream>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100
using namespace std;

int In(char ch) // 判断输入字符是否为运算符 
{
	if(ch=='+')	return OK;
	if(ch=='-')	return OK;
	if(ch=='*')	return OK;
	if(ch=='/')	return OK;
	if(ch=='(')	return OK;
	if(ch==')')	return OK;
	if(ch=='#')	return OVERFLOW;
	return ERROR;
}

char Precede(char a,char b) // 比较符号 a与符号 b的优先级.如 a 优于 b,则返回 ' > ',否则返回 ' < ' 或 ' = ' 
{
	if(b=='+')
	{
		if(a=='('||a=='#')	return '<';
		return '>';
	}
	if(b=='-')
	{
		if(a=='('||a=='#')	return '<';
		return '>';
	}
	if(b=='*')
	{
		if(a=='*'||a=='/'||a==')')	return '>';
		return '<';
	}
	if(b=='/')
	{
		if(a=='*'||a=='/'||a==')')	return '>';
		return '<';
	}
	if(b=='(')	return '<';
	if(b==')')
	{
		if(a=='(')	return '=';
		return '>';
	}
	if(b=='#')
	{
		if(a=='#')	return '=';
		return '>';
	}
}

double Operate(double a,char theta,double b) // 把 a、b进行二元运算 
{
	if(theta=='+')	return a+b;
	if(theta=='-')	return a-b;
	if(theta=='*')	return a*b;
	if(theta=='/')	return a/b;
}

double EvaluateExpression() // 计算过程 
{
	char str[10010];
	stack<double> OPND;
	stack<char> OPTR;
	scanf("%s",str);
	OPTR.push('#');
	double a,b,shu=0;
	int flag=0;
	char theta;
	for(int i=0;str[i];i++)
	{
		if(In(str[i])==0)
		{
			shu=shu*10+str[i]-'0';
			flag=1;
		}
		else
		{
			if(flag)
			{
				OPND.push(shu);
				shu=0;
				flag=0;
			}
			switch(Precede(OPTR.top(),str[i]))
			{
				case '<':
					OPTR.push(str[i]);
					break;
				case '>':
					theta=OPTR.top();	OPTR.pop();
					b=OPND.top();	OPND.pop();
					a=OPND.top();	OPND.pop();
					OPND.push(Operate(a,theta,b));
					i--; // 这里是因为判断的该符号 str[i] 还没有入栈,故需要回去判断一下 
					break;
				case '=':
					OPTR.pop();
					break;
			}
		}
	}
	return OPND.top();
}

int main()
{
	printf("\n************************************************************************\n\n");
	puts("温馨提醒:\n");
	puts("    为了方便,请您在输入表达式的结尾加一个符号 '#',以判断您的输入完成");
	puts("\n    如若忘了输入结束字符 '#',结果可能有误"); 
	printf("\n************************************************************************\n\n");
	puts("\n请输入您想要计算的表达式:\n");
	printf("\n计算结果为:%.2lf\n",EvaluateExpression());
	puts("\n\n\n\n谢谢您的使用,请按任意键退出");
	system("pause");
	return 0;
}

  • 33
    点赞
  • 175
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值