栈的应用--算术表达式求值

本文介绍了一种使用双栈处理算术表达式的算法,包括运算符和操作数的处理,通过具体代码实现了算术表达式的求值过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算术表达式求值–利用双栈

算术表达式中可以包含+,-,,/,(,)这6个运算符,要计算的表达式以字符序列的形式在程序运行时输入。为了便于实现,规定:(1) 每个表达式均以字符#开始,以#号结束,(例如,#23(13+8)-76+100# ),表达式中不能出现数字和运算符外的其它字符(空格也不行);(2)表达式中的运算数只能是非负整数;(3)输入的表达式都是合法的。
编写程序,完成输入一个合法的算述表达式,输出其运算结果。(例如,#23
(13-8)-7*6+100#,则输出: 173)
算法思想:
(1) 函数In(L,c):判断c是否为运算符

  • L是存放运算法的集合(可以用线性表表示,也可以用一维数组表示)
  • c是字符,若c是运算符则返回值1,否则返回0。也可以用别的方法

(2)函数Precede(t1,t2):

  • 判断运算符t1和t2的优先级,返回值用’>’,’<’,’=’分别表示
  • t1的优先级高于、等于、低于t2(用矩阵实现),也可以用别的方法
  • 用’0’表示两个运算符不可比。

(3)函数Operate(a,theta,b):对a和b进行二元运算theta,返回运算结果。 
(4)程序中还要有分离整数(操作数)的程序段,本实验要求是非负整数。

注意!!!

  • 在计算机内部,整形和字符都是以ASCII的形式存储的,所以将程序内将变量定义成整形和字符,计算机都可以自动转换。但因为字符占一个字节范围是-128到127,而整形占四个字节范围大的多,如果用字符定义,其运算结果只能在-128到127之间。
  • 输入时:1.输入的括号要与你定义的运算符一样(英文还是中文)
    2.要以#结尾作为结束标志
    3.一行输入
#include "stdio.h"
#include "stdlib.h"
#define MAXSIZE 100
#define ERROR 0
#define OK 1
/*typedef struct{//可以用线性表表示,也可以用一维数组表示
	int *elem;
	int length;
}SqList;*/
typedef struct{//栈的顺序存储结构
	int *base;
	int *top;
	int stacksize;
}SqStack;

int InitStack(SqStack &S)
{//栈的初始化
	S.base = (int*)malloc(MAXSIZE *sizeof(int));
	if(!S.base)  
		return ERROR;
	S.top = S.base;//栈空
	S.stacksize = MAXSIZE;
	return OK;
}

int Push(SqStack &S,int x)
{//进栈
	if (S.top - S.base == S.stacksize)//栈满  
		return ERROR; 
	*S.top++ = x; //相当于*S.top=x;S.top++;
	return OK;
}

int Pop(SqStack &S,int &x)
{//出栈
	if(S.top == S.base) //栈空
		return ERROR;
	x = *--S.top;//相当于--S.top;x=*S,top;
	return OK;
}
int GetTop (SqStack S)
{//取栈顶元素
	if(S.base == S.top) //栈空
		return ERROR;
	char e = *(S.top - 1);//注意栈的存储形式,top指针指向栈的一个空内存空间,元素入栈时,直接放在top指针
//处,再后移一个内存单元;出栈时,top指针前移一个单元,再将栈顶元素弹出,所以栈顶元素在top指针的前一个单元。
	return e;
}
int In(char c)
{//判断读入的字符是否为运算符
	int i;
	int j = 0;
	char a[7] = {'+','-','*','/','(',')','#'};
	for(i = 0;i < 7;i++)
		if(c == a[i])
			j = 1;
	return j;
}
char precede(char c1, char c2)
{//判断运算符之间的优先关系
	int x,y;
	char a[][7] = {
				//{'0','+','-','*','/','(',')','#'},
				{'>','>','<','<','<','>','>'},
				{'>','>','<','<','<','>','>'},
				{'>','>','>','>','<','>','>'},
				{'>','>','>','>','<','>','>'},
				{'<','<','<','<','<','=','0'},
				{'>','>','>','>','0','>','>'},
				{'<','<','<','<','<','0','='}};
	switch(c2)
	{
		case '+':y = 0;break;
		case '-':y = 1;break;
		case '*':y = 2;break;
		case '/':y = 3;break;
		case '(':y = 4;break;
		case ')':y = 5;break;
		case '#':y = 6;break;
	}
	switch(c1)
	{
		case '+':x = 0;break;
		case '-':x = 1;break;
		case '*':x = 2;break;
		case '/':x = 3;break;
		case '(':x = 4;break;
		case ')':x = 5;break;
		case '#':x = 6;break;
	}
	return a[x][y];
}
int Operate(int a,char theta,int b)
{//进行二元运算
	int count;
	switch(theta)
	{
		case '+':count = a + b;break;
		case '-':count = a - b;break;
		case '*':count = a * b;break;
		case '/':count = a / b;break;
	}
	return count;
}
int DestroyStack(SqStack &S)
{//销毁栈
	S.top = S.top = NULL;
	S.stacksize = 0;
	free(S.base);
	return OK;
}

int main()
 { //设OPTR和OPND分别为运算符栈和运算数栈 
	 SqStack OPTR;
	 SqStack OPND;
	 int sum = 0,c,x,theta,a,b,s;
	 //要将各变量定义成整形
	 InitStack (OPTR); 
	 InitStack (OPND); 
	 Push (OPTR, '#'); //先把#压栈 
	 c = getchar();//一个一个读取字符(不能读多位整数)
	 while (c != '#' || GetTop(OPTR) != '#')//
	 { 
		 if (In(c))  //如果c是运算符
			 switch (precede(GetTop(OPTR), c))
			{ 
				case '<': // 栈顶元素优先权低
					Push(OPTR, c); //则将字符c压栈
					c = getchar(); //读下一个
					break;
				case '>'://Pop(OPTR, theta); //栈顶运算符出栈
					Pop(OPND, b);//再出两个运算数 
					Pop(OPND, a); 
					Push(OPND, Operate(a, theta, b)); //运算结果入栈
					break; 
				case '=': // 脱括号并接收下一字符
					Pop(OPTR, x); 
					c = getchar(); 
					break;
		 }  
		 else 
		 {//分离多位的操作数,解决多位整数问题
			 while(c >= '0'&& c <= '9')
			 {
				 sum = sum*10+(c-'0');//c-'0'是将字符c转换成对应的整数再运算
				 c = getchar();
			 }
			 Push(OPND, sum);//将结果入栈
			 sum = 0;//重置sum
		 }
	 }  
	 s= GetTop(OPND);
	 DestroyStack(OPND); //销毁栈
	 DestroyStack(OPTR);
	 printf("%d\n",s);
	 return OK;
} 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值