表达式求值(链栈)

问题

在这里插入图片描述

缺陷

1.输入必须正确输入算符(运算符+界限符)和操作数,若输入非(算符和操作数),无法判断出(因为默认非算符的数都为操作数,否则无法保留两位数及以上的运算结果)
2.输入的操作数必须为个位数,因为输入类型是字符,只能读取一个字符(且,输入类型不能是int型,int无法写入算符)
3.运算结果只能返回255个值(ASCII码只能表示255个:-128127其中0127才有对照表)范围:(-176+48=-128,再小就超出范围)-1760(‘0’为48)79(79+48=127,再大就超出范围了),超出范围(过小则变为79逐渐变小;过大则变为-176逐渐变大)
4.算符匹配错误返回-1

#include <stdio.h>
#include <stdlib.h>
#include<iostream>
#include<string>
using namespace std;
typedef enum {da , xiao, deng, ERROR }pre;//枚举元素得是字母与数字组成的符号序列
typedef char ElemType;
typedef struct StackNode* StackLink;
struct StackNode{
	ElemType data;
	StackLink next;
};
//初始化
void InitStack(StackLink &S){
	S = NULL;
	return;
}
//入栈
void Push(StackLink &S, ElemType e){
	StackLink p = (StackLink)malloc(sizeof(StackNode));
	p->data = e;
	p->next = S;
	S = p;
	return;
}
//出栈
void Pop(StackLink &S, ElemType &e){
	e = S->data;
	S = S->next;
	return;
}
//返回栈顶元素
ElemType GetHead(StackLink S){
	if (S == NULL)return 0;
	return S->data;
}
//堆栈判空
bool StackEmpty(StackLink S){
	if (S == NULL)return true;
	return false;
}

//算符判断优先级
pre Precede(ElemType x,ElemType y){
	if ((x == '('&&y == '#') || (x == ')'&&y == '(') || (x == '#'&&y == ')'))
		return ERROR;
	else if (x == '+'||x=='-'){
		if (y == '+' || y == '-' || y == ')' || y == '#')
			return da ;
		else
			return xiao ;
	}
	else if (x == '*'||x=='/'){
		if (y == '+' || y == '-' || y == '*' || y == '/' || y == ')' || y == '#')
			return da ;
		else
			return xiao ;
	}
	else if (x == '('){
		if (y == ')')
			return deng;
		else
			return xiao ;
	}
	else if (x == ')')
		return da ;
	else{
		if (y == '#')
			return  deng;
		else
			return xiao ;
	}
}
//运算
ElemType Operate(ElemType a, ElemType x, ElemType b){
	int c = a - '0',d = b - '0';
	ElemType sum;
	if (x == '+')
		sum=(c + d + '0');
	else if (x == '-')
		sum=(c - d + '0');
	else if (x == '*')
		sum=(c*d + '0');
	else
		sum=(c / d + '0');
	return sum;
}

//表达式求值
//1.输入必须正确输入算符(运算符+界限符)和操作数,若输入非(算符和操作数),无法判断出(因为默认非算符的数都为操作数,否则无法保留两位数及以上的运算结果)
//2.输入的操作数必须为个位数,因为输入类型是字符,只能读取一个字符
//3.输入类型不能是int型,int无法写入算符
//表达式以#开头#结尾,开头的#用程序写,压入栈,结尾的#通过键盘输入
int EvaluateExpression(){
	StackLink OPND, OPTR;
	InitStack(OPND);//初始化OPND栈,寄存操作数或运算结果
	InitStack(OPTR);//初始化OPTR栈,寄存算符
	Push(OPTR, '#');//表达式起始符#入栈
	ElemType p,theta,a,b;//p是键盘输入的,theta,a和b是算符和两个操作数(当输入为算符且优先级高时运算用:a theta b)
	cin >> p;
	while (p != '#'||GetHead(OPTR)!='#'){//表达式没有扫描完毕或OPTR的栈顶元素不为‘#’
		//如果是算符就比较优先级(当出现优先级高的算符就运算,优先级低的就入栈)
		if (p == '+' || p == '-' || p == '*' || p == '/' || p == '(' || p == ')'||p=='#')
			switch (Precede(GetHead(OPTR),p))
		{
			case xiao://若优先级低,先把算符压入OPTR不计算
				Push(OPTR, p);
				cin >> p;
				break;
			case da://若优先级高,则进行运算,弹出OPTR栈顶的算符和OPND的两个数
				//输入)的情况下优先级总是高【(则等于,可消掉括号】,前一个算符参与后运算不输入新p,)会循环到下一次和前一个算符再比较优先级直到遇到(
				Pop(OPTR, theta);//p为弹出的算符
				Pop(OPND, b);//先出的是后进的
				Pop(OPND, a);//后出的是先进的
				Push(OPND, Operate(a, theta, b));//运算结果压入OPND
				break;
			case deng://若优先级相等(只有()和##两种情况)则括号匹配成功,消去栈顶的(/#并且不让p入栈,写新p
				//(##其实不会出现,当p为#且栈顶元素为#时就退出循环了已经)
				Pop(OPTR, p);//p是弹出的废弃算符
				cin >> p;
				break;
			default:
				return -1;
		}
		//如果是操作数就入栈OPND
		else{
			Push(OPND, p);
			cin >> p;
		}	
	}
		int sum = GetHead(OPND)-'0';
		return sum;
}
int main(){
	printf("结果是:%d",EvaluateExpression());
	system("PAUSE");
	return 0;
}

0.结构体和枚举类型

注意枚举元素得是字母与数字组成的符号序列

typedef enum {da , xiao, deng, ERROR }pre;//枚举元素得是字母与数字组成的符号序列
typedef char ElemType;
typedef struct StackNode* StackLink;
struct StackNode{
	ElemType data;
	StackLink next;
};

1.链栈的基本操作

//初始化
void InitStack(StackLink &S){
	S = NULL;
	return;
}
//入栈
void Push(StackLink &S, ElemType e){
	StackLink p = (StackLink)malloc(sizeof(StackNode));
	p->data = e;
	p->next = S;
	S = p;
	return;
}
//出栈
void Pop(StackLink &S, ElemType &e){
	e = S->data;
	S = S->next;
	return;
}
//返回栈顶元素
ElemType GetHead(StackLink S){
	if (S == NULL)return 0;
	return S->data;
}
//堆栈判空
bool StackEmpty(StackLink S){
	if (S == NULL)return true;
	return false;
}

2.表达式求值

2.1算符判断优先值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

typedef enum {da , xiao, deng, ERROR }pre;//枚举元素得是字母与数字组成的符号序列
typedef char ElemType;
typedef struct StackNode* StackLink;
//算符判断优先级
pre Precede(ElemType x,ElemType y){
	if ((x == '('&&y == '#') || (x == ')'&&y == '(') || (x == '#'&&y == ')'))
		return ERROR;
	else if (x == '+'||x=='-'){
		if (y == '+' || y == '-' || y == ')' || y == '#')
			return da ;
		else
			return xiao ;
	}
	else if (x == '*'||x=='/'){
		if (y == '+' || y == '-' || y == '*' || y == '/' || y == ')' || y == '#')
			return da ;
		else
			return xiao ;
	}
	else if (x == '('){
		if (y == ')')
			return deng;
		else
			return xiao ;
	}
	else if (x == ')')
		return da ;
	else{
		if (y == '#')
			return  deng;
		else
			return xiao ;
	}
}

2.2优先级较大情况下的运算

//运算
ElemType Operate(ElemType a, ElemType x, ElemType b){
	int c = a - '0',d = b - '0';
	ElemType sum;
	if (x == '+')
		sum=(c + d + '0');
	else if (x == '-')
		sum=(c - d + '0');
	else if (x == '*')
		sum=(c*d + '0');
	else
		sum=(c / d + '0');
	return sum;
}

2.3求值步骤(求值的主体函数)

注意
1.输入
——1.1.输入必须正确输入算符(运算符+界限符)和操作数,若输入非(算符和操作数),无法判断出(因为默认非算符的数都为操作数,否则无法保留两位数及以上的运算结果)
——1.2.输入的操作数必须为个位数,因为输入类型是字符,只能读取一个字符
——1.3.输入类型不能是int型,int无法写入算符

2表达式以#开头#结尾,开头的#用程序写,压入栈,结尾的#通过键盘输入
在这里插入图片描述

int EvaluateExpression(){
	StackLink OPND, OPTR;
	InitStack(OPND);//初始化OPND栈,寄存操作数或运算结果
	InitStack(OPTR);//初始化OPTR栈,寄存算符
	Push(OPTR, '#');//表达式起始符#入栈
	ElemType p,theta,a,b;//p是键盘输入的,theta,a和b是算符和两个操作数(当输入为算符且优先级高时运算用:a theta b)
	cin >> p;
	while (p != '#'||GetHead(OPTR)!='#'){//表达式没有扫描完毕或OPTR的栈顶元素不为‘#’
		//如果是算符就比较优先级(当出现优先级高的算符就运算,优先级低的就入栈)
		if (p == '+' || p == '-' || p == '*' || p == '/' || p == '(' || p == ')'||p=='#')
			switch (Precede(GetHead(OPTR),p))
		{
			case xiao://若优先级低,先把算符压入OPTR不计算
				Push(OPTR, p);
				cin >> p;
				break;
			case da://若优先级高,则进行运算,弹出OPTR栈顶的算符和OPND的两个数
				//输入)的情况下优先级总是高【(则等于,可消掉括号】,前一个算符参与后运算不输入新p,)会循环到下一次和前一个算符再比较优先级直到遇到(
				Pop(OPTR, theta);//p为弹出的算符
				Pop(OPND, b);//先出的是后进的
				Pop(OPND, a);//后出的是先进的
				Push(OPND, Operate(a, theta, b));//运算结果压入OPND
				break;
			case deng://若优先级相等(只有()和##两种情况)则括号匹配成功,消去栈顶的(/#并且不让p入栈,写新p
				//(##其实不会出现,当p为#且栈顶元素为#时就退出循环了已经)
				Pop(OPTR, p);//p是弹出的废弃算符
				cin >> p;
				break;
			default:
				return -1;
		}
		//如果是操作数就入栈OPND
		else{
			Push(OPND, p);
			cin >> p;
		}	
	}
		int sum = GetHead(OPND)-'0';
		return sum;
}

主函数

int main(){
	printf("结果是:%d",EvaluateExpression());
	system("PAUSE");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章