BUAA(2021春)计算器(后缀表达式实现)(只要打出优先级表==有手就行)

48 篇文章 154 订阅

看前须知

要点介绍和简要声明.

第四次上机题汇总

栈操作(栈-基本题).

C程序括号匹配检查.

计算器(后缀表达式实现)(只要打出优先级表==有手就行).

BUAA(2021春)文本编辑操作模拟(简)a——介绍两种方法.

BUAA(2021春)银行排队模拟(生产者-消费者模拟)——理解题意有点小难.

题目内容

问题描述

从标准输入中读入一个整数算术运算表达式,如24 / ( 1 + 5%3 + 36 / 6 / 2 - 2) * ( 12 / 2 / 2 )= ,计算表达式结果,并输出。

要求:

  1. 表达式运算符只有+、-、*、/、%,表达式末尾的=字符表示表达式输入结束,表达式中可能会出现空格;

  2. 表达式中会出现圆括号,括号可能嵌套,不会出现错误的表达式;

  3. 出现除号/时,以整数相除进行运算,结果仍为整数,例如:5/3结果应为1。

  4. 要求采用逆波兰表达式来实现表达式计算。

输入形式

从键盘输入一个以=结尾的整数算术运算表达式。操作符和操作数之间可以有空格分隔。

输出形式

在屏幕上输出计算结果(为整数,即在计算过程中除法为整除)。

样例

输入

24 / ( 1 + 5%3 + 36 / 6 / 2 - 2) * ( 12 / 2 / 2 ) =

输出

18

样例说明

按照运算符及括号优先级依次计算表达式的值。

题解

易错点和难点

本题就是在考察同学对于的使用。本题有两个思路,一个是把中缀表达式转换为后缀表达式(逆波兰式),再进行计算;另一种是再中缀表达式通过栈转化为后缀表达式的过程中就把表达式计算完(笔者采用的就是这种方法)。本题需要维护两个栈,一个运算符栈,一个是操作数(数字)栈,通过频繁地入栈和出栈完成目的。

本题最难的部分在于怎么处理运算符的优先级,对于这个问题,笔者也是有一段时间思考过怎么不用动脑子的解决这个问题,最后发现不用动脑子的方法的就是把运算符的优先级表打出来(《数据结构教程(第3版)》 唐发根 北京航空航天大学出版社 的栈的应用部分,里面有具体介绍符号的优先级的大小比较和优先级表),打出优先级表之后,这道题简直就是有手就行

参考代码

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<ctype.h>
#define MAXSIZE 100
typedef int ElemType;
struct stack{
	int Top;
	ElemType data[MAXSIZE];
};
typedef struct stack Stack;
typedef struct stack *Stackp;
Stack OPFIGURE,OPTHETA;
void  push( Stackp s,  ElemType item )
{
	s->data[++s->Top]=item; 
}
int pop( Stackp s)
{
	return s->data[s->Top--]; 
}
int Gettop( Stackp s )
{
	return s->data[s->Top];
}
char Pre(char theta1,char theta2)//运算符优先级比较
{
	int i,j;
	char pre[8][8]={// +   -   *   /   (   )   =  %
		             {'>','>','<','<','<','>','>','<'},  
                     {'>','>','<','<','<','>','>','<'},  
                     {'>','>','>','>','<','>','>','>'},  
                     {'>','>','>','>','<','>','>','>'},  
                     {'<','<','<','<','<','=','0','<'},  
                     {'>','>','>','>','0','>','>','>'},  
                     {'<','<','<','<','<','0','=','<'},
					 {'>','>','>','>','<','>','>','>'},}; 
                
    switch(theta1){
    	case '+': i=0; break;  
        case '-': i=1; break;  
        case '*': i=2; break;  
        case '/': i=3; break;  
        case '(': i=4; break;  
        case ')': i=5; break;
        case '=': i=6; break;
        case '%': i=7; break;
	}
	
    switch(theta2){
    	case '+': j=0; break;  
        case '-': j=1; break;  
        case '*': j=2; break;  
        case '/': j=3; break;  
        case '(': j=4; break;  
        case ')': j=5; break;
        case '=': j=6; break;
        case '%': j=7; break;
    }
    return(pre[i][j]);
}
int Op(int a,char theta,int b)//运算符含义表达
{
	int result;
	
	switch(theta){
		case'+':return a+b;
		case'-':return a-b;
		case'*':return a*b;
		case'%':return a%b;
		case'/':                     //判断除数是否为0,若除数为零返回错误提示
		        if(b!=0)
		        return a/b;
		        else
		        {
		        	exit(0);
				}
	}
    
}
int IsTheta(char c) //判断是否为运算符,是运算符返回1,若不是返回0
{
	switch(c){
		case '+':   
        case '-':  
        case '*':   
        case '/':   
        case '(':   
        case ')': 
        case '%': 
        case '=': 
                 return 1;
		 default:
		         return 0;		   
	}
}
int EvaluateExpression(char *expression)  //表达式运算 
{
	ElemType a,b,theta,tmp,X1,X2;
	
	char ch;
	int i=0;
	
	OPFIGURE.Top=-1;
	OPTHETA.Top=-1;
	push(&OPTHETA,'=');  //把 = 压入运算符栈 
	ch=expression[i++];     // ch 读取表达式的下一个字符  
	
	while(ch!='=' || Gettop(&OPTHETA)!='=')
	{
		if(IsTheta(ch)) //判断是否为运算符 
		{
			switch(Pre(Gettop(&OPTHETA),ch)) // 比较 ch 和栈顶运算符  OPTHETA.data 的优先级
			{
				case'<':
						push(&OPTHETA,ch);
						ch=expression[i++];
						break;
				case'>':
						theta=pop(&OPTHETA); 
					    b=pop(&OPFIGURE);
					    a=pop(&OPFIGURE);
					    push(&OPFIGURE,Op(a,theta,b));
					    break;
				case'=':
						tmp=pop(&OPTHETA);
					    ch=expression[i++]; //读取下一位字符并将指针向后偏移一位
					    break;
			} 
			
		}
		else if(isdigit(ch)) //判断是否为数字 
		{
			X1=ch-'0'; //将字符形式转化为数字
			push(&OPFIGURE,X1);
			X2=X1;
			ch=expression[i++]; //读取下一位字符并将指针向后偏移一位
			
			while(isdigit(ch)) //判断下一位是否还是数字
			{
				X1=ch-'0';
				X2=10*X2+X1; //归并至X2
				tmp=pop(&OPFIGURE);
				push(&OPFIGURE,X2);
				ch=expression[i++];  //读取下一位字符并将指针向后偏移一位
				
			} 
		}
		else if(ch==' ') //判断是否为空格
		{
			while(ch==' ')
			{
				ch=expression[i++];
			}
		}
		else //出现非法字符 
		{
			exit(0); 
		}
	}
	return(Gettop(&OPFIGURE));
}
int main()
{	
	char expression[100];
	int result;
	gets(expression);
	result=EvaluateExpression(expression);
	printf("%d\n",result);
	return 0;
}

补充测试的数据

输入

1=

输出

1

输入

1+(8/9+8)*(5*7+6)/(4+8)=

输出

28

输入

(1+3+4*5*(36/9+37))/(7+81/10+3*6)=

输出

24

题单链接

有考虑过负数和乘方怎么解决吗好兄弟

负数.
乘方.

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值