栈应用(表达式求值)

一、说明

1、本代码只适用于操作数为一位数的运算

2、输入:以‘#’结尾的表达式

                 eg:3*(7-2)#

二、算法步骤

(1)初始化shu栈(存操作数)和fu栈(存操作符),将表达式起始符“#”压入fu栈

(2)读取表达式,读入第一个字符ch,如果表达式没有读完毕至“#”或者fu栈的栈顶元素不为“#”,则执行以下循环。

1、如果ch不是运算符,压入数栈,读入下一字符

2、如果ch是运算符,根据 fu栈的栈顶运算符(简记为t)和ch的优先级比较 结果,做不同处理

 【1】若t<ch: 将ch压入fu栈,读入下一字符

 【2】若t>ch: 弹出t,从shu栈中先后弹出两个数,进行相应运算,将结果压入shu栈

 【3】若等于,则fu栈的栈顶元素是"("且ch是")",此时弹出fu栈栈顶的"(",相当于括号匹配成功,继续读入下一个字符

(3)shu栈栈顶元素为表达式求值的结果,输出

三、代码

说明

#define ERROR ' '
#define OK 1

1、链栈的存储结构

typedef struct StackNode
{
	Elem c;
	struct StackNode* next;
}StackNode, * LinkStack;

2、入栈

Elem Push(LinkStack &s, Elem e)
{
	LinkStack p = (LinkStack)malloc(sizeof(StackNode));//申请新结点
	p->c = e;//将新结点数据域置为e
	p->next = s;//将新结点插入栈顶
	s = p;//修改栈顶指针
	return OK;
}

3、出栈

void Pop(LinkStack& s, Elem &x2)
{
	LinkStack p;
	if (s == NULL)
		return ;//栈空
	x2 = s->c;//将栈顶元素赋给x2
	p = s;//用p临时保存栈顶元素空间,以备释放
	s = s->next;//修改栈顶指针
	free(p);//释放原栈顶元素空间
}

4、得到栈顶元素

Elem GetTop(LinkStack &s)
{
	return s->c;
}

5、判断是不是运算符

Elem In(char ch)
{
	if (ch >= '0' && ch <= '9')
	{
		return 0;//是操作符返回 1 
	}
	else return 1;
}

6、运算符优先级

用二维数组列出优先级表格,比较时查表即可

char Precede(char c1, char c2)
{
	int i=0, j=0;
	char pre[7][7] = {// +   -   *   /   (   )   #//便于对照
					 {'>','>','<','<','<','>','>'},
					 {'>','>','<','<','<','>','>'},
					 {'>','>','>','>','<','>','>'},
					 {'>','>','>','>','<','>','>'},
					 {'<','<','<','<','<','=','0'},
					 {'>','>','>','>','0','>','>'},
					 {'<','<','<','<','<','0','='} };

	switch (c1) {
	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;
	}

	switch (c2) {
	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;
	}
	return(pre[i][j]);
}

7、运算

Elem Opreate(Elem &a1, Elem &x1, Elem &b1)
{
	
	switch ((char)x1)
	{
		case'+':return a1+b1;
		case'-':return a1 - b1;
		case'*':return a1*b1;
		case'/':             //判断除数是否为0,若除数为零返回错误提示                       
			if (b1!=0)
				return a1/b1;
			else
			{
				printf("Divisor can not Be zero!\n");
				exit(0);
			}
	}
}

8、完整代码

#define  _CRT_SECURE_NO_WARNINGS

#define ERROR ' '
#define OK 1

typedef int Elem;

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef struct StackNode
{
	Elem c;
	struct StackNode* next;
}StackNode, * LinkStack;

Elem Push(LinkStack &s, Elem e);
void Pop(LinkStack &s, Elem &x2);
Elem GetTop(LinkStack &s);
Elem In(char ch);
char Precede(char c1, char c2);
Elem Opreate(Elem &a1, Elem &x, Elem &b1);

Elem Push(LinkStack &s, Elem e)
{
	LinkStack p = (LinkStack)malloc(sizeof(StackNode));
	p->c = e;
	p->next = s;
	s = p;
	return 1;
}
void Pop(LinkStack& s, Elem &x2)
{
	LinkStack p;
	if (s == NULL)
		return ;
	x2 = s->c;
	p = s;
	s = s->next;
	free(p);
}

Elem GetTop(LinkStack &s)
{
	return s->c;
}
Elem In(char ch)
{
	if (ch >= '0' && ch <= '9')
	{
		return 0;
	}
	else return 1;
}
char Precede(char c1, char c2)
{
	int i=0, j=0;
	char pre[7][7] = {// +   -   *   /   (   )   #
					 {'>','>','<','<','<','>','>'},
					 {'>','>','<','<','<','>','>'},
					 {'>','>','>','>','<','>','>'},
					 {'>','>','>','>','<','>','>'},
					 {'<','<','<','<','<','=','0'},
					 {'>','>','>','>','0','>','>'},
					 {'<','<','<','<','<','0','='} };

	switch (c1) {
	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;
	}

	switch (c2) {
	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;
	}
	return(pre[i][j]);
}
Elem Opreate(Elem &a1, Elem &x1, Elem &b1)
{
	switch ((char)x1)
	{
		case'+':return a1+b1;
		case'-':return a1 - b1;
		case'*':return a1*b1;
		case'/':             //判断除数是否为0,若除数为零返回错误提示                       
			if (b1!=0)
				return a1/b1;
			else
			{
				printf("Divisor can not Be zero!\n");
				exit(0);
			}
	}
}

Elem main()
{
	LinkStack shu=NULL;
	LinkStack fu =NULL;
	char ch;
	Elem x, a, b;
	Push(fu,(Elem)'#');//将表达式起止符压入fu栈
	ch = getchar();
	while (ch != '#' || (char)GetTop(fu) != '#')//表达式没读完或fu栈的栈顶元素不为'#'
	{
		if (In(ch)==0)
		{
			Push(shu,ch-'0');
			ch = getchar();
		}
		else
		{
			switch (Precede((char)GetTop(fu), ch))
			{
				case '>'://fu栈栈顶元素优先级高
					Pop(fu,x);
					Pop(shu,b);
					Pop(shu,a);
					Push(shu, Opreate(a, x, b));
					break;

				case '<':
					Push(fu,(Elem)ch);
					ch = getchar();
					break;

				case'=':
					Pop(fu, x);
					ch = getchar();
					break;
			}
		}
	}
	printf("运算结果=%d",GetTop(shu));
	return 0;
}

四、运行

五、个人总结

我做这个题是根据书上例题中算法描述打的代码

1、遇到的第一个困难是怎么补充出比较运算符优先级的函数,解决方案已给出。

2、最初,链栈的数据域我设置的是char型,这导致了一些问题
 比如:进行运算后,得到运算结果为15(int),将15 (int)压入shu栈,我目前已知有两种方法(数字+‘0’ 或 强制类型转化), 数字+‘0’变数字字符(貌似只有0~9的数字才行)pass,

用强制类型转化,也会出现错误,应该是我用法不当。

于是最后我就干脆将数据域设为int型,需要操作符时,再强制类型转化

3、还有就是参数传递中传引用(c++中用引用,c用指针)

以上内容,如有错误,望指正!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值