表達式求值(鏈棧)

問題

在這裏插入圖片描述

缺陷

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章