【C语言】 利用顺序表实现使用运算符优先数法对表达式求值

【C语言】 利用顺序表实现使用运算符优先数法对表达式求值

题目要求

本题要求编写程序,对任一输入的一个算术表达式,用运算符优先数法计算并输出其值。
【假设条件】
本题假定:
(1) 表达式只包含双目运算符,即: +,-,*,/
(2) 假定表达式一定是合法的,且其中的数字均为1位整数

题目分析

首先我们需要认识到什么时运算符优先法。
在常规的计算中,我们通常会用到’+’、’-’、’*’、’/'四种基本双目运算符来进行,而在这四种符号中,我们知道,如果是一个表达式中出现了这四个符号,那么遵循“先乘除,后加减”的运算规则,同时,“+”和“-”处在同一级,应遵循从左到右依次计算,同理“×”和“÷”。那么,根据此规则,我们可以用数值对不同优先级进行定义。
我们规定,“+”和“-”的等级数值为1,“×”和“÷”的等级值高于前两者为2(当然,你可以自行定义数值,只要满足加减的等级低于乘除的等级,且加和减的等级相等即可)。并且,为了方便操作,我们将符号栈的栈底默认放置一个“#”,并将它赋值为0(最低值),这样,在进行push和pop操作时,我们可以通过“#”来判断符号栈是否是空了。(或者你也可以放置一个“=”,赋值0)。
思考一下,怎么判断什么时候该push符号,什么时候pop符号呢?

  1. 入栈 判断待插入的符号与原符号栈顶等级大小,如果待插入的符号等级大于栈顶符号等级时,才插入该符号,并将栈顶向上移动一位。(比如:先乘除、若同级的话,应该遵循从左至右,先插入的符号在左边)
  2. 出栈 当待插入的符号等级小于栈顶符号等级时,将栈顶符号取出来,并且取出来两位数值,进行运算。在运算的过程中,要注意更新符号位栈顶的运算级,并与待插入的运算符等级进行判断。只要待插入的符号等级大于栈顶可,就终止出栈的操作,回到入栈。

代码实现如下

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxsize 1024
typedef struct node{
	int top1;
	int num[maxsize];
}Lnum;//定义为装数字的栈1 
typedef struct node1{
	int top2;
	char fu[maxsize];
}Lchar;//定义装符号的栈2 
int creat(char fix[]){//创建运算式 
	char ch;
	int i=0;
	while((ch=getchar())!='\n'){
		fix[i]=ch;
		i++;
	}
	return i;
}
int panduan(char ch1){//赋值判断四种基本运算符号和默认符号的优先级 
	switch(ch1){
		case '*':return 2;break;
		case '/':return 2;break;
		case '+':return 1;break;
		case '-':return 1;break;
		case '#':return 0;break;
		default:return -1;break;//错误符号,返回-1 
	}
}
int cal(char fix[],int num){
	Lnum *stack1;
   	stack1=(Lnum*)malloc(sizeof(Lnum));//创建数字栈 
   	Lchar *stack2;
   	stack2=(Lchar*)malloc(sizeof(Lchar));//符号栈 
   	int flag1,flag2,i,temp,temp1;//先声明变量 
   	stack1->top1=0;//初始化栈顶 
   	stack2->top2=0;
   	stack2->fu[stack2->top2]='#';//符号栈的底部是'#'
   	for(i=0;i<num;++i){//遍历运算式,将不同类型的符号入栈 
   		if((fix[i]-'0')>=1&&(fix[i]-'0')<=9){
   			stack1->num[stack1->top1]=fix[i]-'0';//注意运算式是字符形式,需要减'0'来得到int类型的数值 
   			stack1->top1++;//每一次数字入栈后,栈顶就指向上面一层,故下面进行运算时需要先把栈顶指针往下回一个 
		}else{
			flag1=panduan(stack2->fu[stack2->top2]);//判断符号栈顶指针所指向的运算符优先等级 
			flag2=panduan(fix[i]);//判断此时待装入的符号优先等级 
			if(flag2>flag1){//只有待装入符号优先级大于原栈顶优先级,才装入 
				stack2->top2++;
				stack2->fu[stack2->top2]=fix[i];
			}else{//否则,数值栈取两位数,符号位取一位符号进行运算 
				stack1->top1--;
				while(flag2<=flag1){
					switch(stack2->fu[stack2->top2]){
						case '+':temp=(stack1->num[(stack1->top1)-1]+stack1->num[(stack1->top1)]);break;
						case '-':temp=(stack1->num[(stack1->top1)-1]-stack1->num[(stack1->top1)]);break;
						case '*':temp=(stack1->num[(stack1->top1)-1]*stack1->num[(stack1->top1)]);break;
						case '/':temp=(stack1->num[(stack1->top1)-1]/stack1->num[(stack1->top1)]);break;
					}
					stack1->top1--;
					stack1->num[stack1->top1]=temp;
					stack2->top2--;	
					flag1=panduan(stack2->fu[stack2->top2]);
				}
				stack2->top2++;
				stack1->top1++;
				stack2->fu[stack2->top2]=fix[i]; 
			}
		}
	}
	stack1->top1--;//入栈操作结束后数值指针始终在上面一层,所以需要将指针取回来 
	while(stack2->top2!=0){//入栈结束,将栈内保存的符号和数值取出来进行运算 
		switch(stack2->fu[stack2->top2]){
			case '+':temp1=(stack1->num[(stack1->top1)-1]+stack1->num[(stack1->top1)]);break;
			case '-':temp1=(stack1->num[(stack1->top1)-1]-stack1->num[(stack1->top1)]);break;
			case '*':temp1=(stack1->num[(stack1->top1)-1]*stack1->num[(stack1->top1)]);break;
			case '/':temp1=(stack1->num[(stack1->top1)-1]/stack1->num[(stack1->top1)]);break;
		}
		stack1->top1--;//取了两个数,但是还需要将运算结果装回,所以只需要栈顶指针往栈底下移一位即可 
		stack1->num[stack1->top1]=temp1;
		stack2->top2--; //符号栈栈顶指针下移一位 
	}
	int r = stack1->num[stack1->top1];//返回运算结果 
	free(stack1);//释放两栈 
	free(stack2);
	return r;
}
int main(){
   char fix[maxsize];
   int num=creat(fix);//创建一个装运算式子的字符串 
   int result=cal(fix,num);//计算结果,传回 
   printf("最终的计算结果为:%d\n",result);
}

PS:CS专业小透明,如果发现错误,还请各位大佬们不吝赐教。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值