【数据结构】栈的应用-算术表达式求值#数据结构实验任务书

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

正文

实验环境: Visual C++ 2010
 
实验目的:

1.掌握栈的定义及实现;
2.掌握利用栈求解算术表达式的方法。

实验内容:

通过修改完善教材中的算法3.4,利用栈来实现算术表达式求值的算法。对算法3.4中调用的几个函数要给出其实现过程:
(1) 函数In©:判断c是否为运算符;
(2) 函数Precede(t1,t2):判断运算符t1和t2的优先级;
(3) 函数Operate(a,theta,b):对a和b进行二元运算theta。
程序运行时,输入合法的算术表达式(中间值及最终结果要在0~9之间,可以包括加减乘除和括号),便可输出相应的计算结果。如下图*:
在这里插入图片描述
实验提示:(仅供参考,每个函数的具体实现可以有多种方法,希望有创新)
一:代码及注释部分:

#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 i=1;			/*定义一个全局变量,在下文中判断是否是运算符中调用; */
int In(char ch){   // 判断输入的是否是运算符;
	i++;
	switch(ch){
		case'+':
		case'-':
		case'*':
		case'/':
		case'=':
		case'(':
		case')':
		return OK;
		break;
   		default:
 		if(i%3==0)
		printf("输入格式错误,求出错误结果:");   /*因为这个要多次调用,所以这里制定一个判断错误机制 */
		return ERROR;
						
	}
}

 

char Precede(char a,char 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进行二元运算 ,这里用的是double是因为方便后文做以后的更改,调试想要的结果(小数位数);*/
	switch(theta){	
	case '+':
		return a+b;
		break;
		case '-':
			return a-b;
break;
			case '*':
				return a*b;
break;	
				case '/':
					return a/b;
					break;
					}
}
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(){
	puts("请输入算术表达式,负数要用(0-正数)表示,并以=结束");
	printf("%.0f\n",EvaluateExpression());				
/*这里可以按照我们的要求,把0改成想要的数字约束是否是小数,有几个小数 ;*/
	system("pause");
	return 0; 
}

二:流程图
在这里插入图片描述
三:实验分析:

1:本实验采取函数相互嵌套设计程序,书写时采用一定的缩进格式使得主函数更加简洁,整体显得美观。
2:本程序针对非法字符会做出一定的反应,即会输出提醒:输入字符错误。具有一定的健壮性。
3:本程序运行时,用户可以根据提示信息进行操作,具有一定的界面友好性。
4:本实验格式不一,具有多种书写方式,有一种更简洁的书写方式。为了程序结构不那么单一,我将这几种书写方式进行了融合,把哪几种书写方式在本程序中都有体现。
5:本实验的健壮性还不是那么完善,由于自身能力不足,在此可能有些非法字符会被判断两次,程序作出两次反应,所以这是程序的缺点之一。
6:由于按照实验要求,要进行整数测试程序。在这里我对程序设计了浮点数兼容的模式,即输入浮点数也可以进行运算,但是最后的输出需要把%.0f改成%f即可。

四:实验程序测试输出:
在这里插入图片描述
附录:栈的定义及实现:

#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED
#endif // STACK_H_INCLUDED
#define MAXSIZE 100
#include<stdlib.h>
using namespace std;
typedef char SElemType;
typedef struct
{
    char *base;
    char *top;
    int stacksize;
}SqStack;
void InitStack(SqStack &S)
{
    S.base=new char [MAXSIZE];
    if(!S.base) exit(0);
    S.top=S.base;
    S.stacksize=MAXSIZE;
}
bool Push(SqStack &S,char e)
{
    if(S.top-S.base==S.stacksize) return false;
    *S.top++=e;
    return true;
}
bool Pop(SqStack &S,char &e)
{
    if(S.top==S.base) return false;
    e=*--S.top;
    //cout<<"pop="<<*S.top;
    return true;
}
char GetTop(SqStack S)
{
    if(S.top!=S.base)
        return *(S.top-1);
}

选做内容1

进一步改进,使表达式的中间值及最终结果不局限于0~9之间的个位数。(如果完成要在实验报告中注明),如下图:

选做内容2:

将表达式转化成后缀表达式输出,利用后缀表达式求表达式的值并输出。
将中缀表达式转化成后缀表达式存储在队列中,然后利用后缀表达式求表达式的值并输出。
 将中缀表达式转化成后缀的思想:
(1)创建一空队列,用来存放后缀表达式,建立并初始化操作符栈OPTR,将表达式起始符“#”压入OPTR栈。
(2)依次读入表达式中每个字符ch,循环执行(3)至(5),直至求出整个表达式转换完毕。
(3)取出OPTR的栈顶元素,当OPTR的栈顶元素和当前读入的字符ch均为“#”时,整个中缀表达式转换完毕。
(4)若ch不是运算符,则进队,读入下一字符ch。
(5)若ch是运算符,则根据OPTR的栈顶元素和ch的优先权比较结果,做不同的处理。
① 若是小于,则ch压入OPTR栈,读入下一字符ch。
② 若是大于,则弹出OPTR栈顶的运算符,进队。
③ 若是等于,则OPTR的栈顶元素是“(”且ch是“)”,这时弹出OPTR栈顶的“(”,相当于去掉括号,然后读入下一字符ch。
 对后缀表达式进行计算的具体步骤为:
建立一个栈S从左到右读后缀表达式,读到数字就将它转换为数值压入栈S中,读到运算符则从栈中依次弹出两个数分别到Y和X,然后以“X运算符Y”的形式计算出结果,再压进栈S中。如果后缀表达式未读完,重复执行上面过程,最后输出栈顶的数值即可结束。
实验要求:
(1) 程序要添加适当的注释,程序的书写要采用缩进格式。
(2) 程序要具在一定的健壮性,即当输入数据非法时,程序也能适当地做出反应。
(3) 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。
(4) 根据实验报告模板详细书写实验报告,在实验报告中给出表达式求值算法的流程图。
(5) 将栈的定义和实现单独保存在一个头文件“stack.h”中,表达式求值的源程序保存为“calculator.cpp”,实验报告命名为“实验报告2.doc”。将stack.h、calculator.cpp和“实验报告2.doc”三个文件压缩为一个文件,按以下方式命名:学号姓名.rar,上传到移动教学平台。*

  • 10
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的基于的表达式求值的代码示例,可以作为参考: ```c++ #include <iostream> #include <stack> #include <string> using namespace std; // 返回运算符的优先级 int getPriority(char c) { if (c == '*' || c == '/') { return 2; } else if (c == '+' || c == '-') { return 1; } else { return 0; } } // 计算两个数的运算结果 int calc(int a, int b, char op) { if (op == '+') { return a + b; } else if (op == '-') { return a - b; } else if (op == '*') { return a * b; } else if (op == '/') { return a / b; } else { return 0; // 不支持的运算符 } } // 计算表达式的值 int eval(const string& expr) { stack<int> opnd; // 操作数 stack<char> optr; // 运算符 optr.push('('); // 表达式起始符 expr += '#'; // 表达式结束符 for (int i = 0; i < expr.size(); i++) { char c = expr[i]; if (c >= '0' && c <= '9') { // 数字 int num = c - '0'; while (i + 1 < expr.size() && expr[i + 1] >= '0' && expr[i + 1] <= '9') { num = num * 10 + expr[i + 1] - '0'; i++; } opnd.push(num); } else { // 运算符 while (true) { char top = optr.top(); if (top == '(' && c == ')') { // 匹配括号 optr.pop(); break; } else if (getPriority(c) > getPriority(top)) { // 当前运算符优先级高于顶运算符 optr.push(c); break; } else { // 当前运算符优先级不高于顶运算符 optr.pop(); int b = opnd.top(); opnd.pop(); int a = opnd.top(); opnd.pop(); opnd.push(calc(a, b, top)); } } } } return opnd.top(); } int main() { string expr = "1+2*3-4/2"; // 期望结果为 5 int result = eval(expr); cout << result << endl; return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君问归期魏有期

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值