数据结构C++ 栈Stack求值算法

来自邓俊辉老师的数据结构(C++版)第95页
readNumber函数(可读整数和小数)
注意:下列代码是直接用C++内部写好的stack实现的,而不是书中给出的stack模板

//发现更简洁的readNumber函数
float readNumber(string& s) {
	float sum = 0.0;
	int pos = s.find('.');
	for (int i = 0; i < s.size(); i++) {
		if (i == pos) { continue; }
		else sum = sum * 10 + (s[i] - 48);
	}
	if (pos) sum = sum / ((s.size() - pos - 1)*10);
	return sum;
}
//是对书中内容的补充,通过Stack来读取整数或小数并运算
#include<iostream>
#include<stack>
using namespace std;
typedef enum { ADD, SUB, MUI, DIV, POW, FAC, L_P, R_P, EOE } Operator;//0-8
const char pri[9][9] = {
	'>','>','<','<','<','<','<','>','>',//0
	'>','>','<','<','<','<','<','>','>',//1
	'>','>','>','>','<','<','<','>','>',//2
	'>','>','>','>','<','<','<','>','>',//3
	'>','>','>','>','>','<','<','>','>',//4
	'>','>','>','>','>','>',' ','>','>',//5
	'<','<','<','<','<','<','<','=',' ',//6
	' ',' ',' ',' ',' ',' ',' ',' ',' ',//7
	'<','<','<','<','<','<','<',' ','='//8
};
//这里取S[]的引用很关键!!!不然S++在readNumber返回后就没效果了
float readNumber(char* &S, stack<float> &opnd) {
	float x = 0.0;
	bool point=false;//判断是否为小数
	int i = 0;//计小数点后的位数
	while (isdigit(*S)||*S=='.') {
		if (*S != '.') {
			if (point == false) 	x = x * 10 + (*(S++) - 48);//减去48,ASCII转成数字
			if (point == true) { x = x * 10 + (*(S++) - 48); i++; }
		}
		else { S++; point = true; }
	}
	int temp = 1;
	for (int j = 0; j < i; j++) temp *= 10;
	x = x / temp;
	opnd.push(x);//压入操作数栈
	return x;
}
int change(char c) {
	switch (c)
	{case '+':return ADD; 
	case '-':return SUB; 
	case '*':return MUI; 
	case '/':return DIV; 
	case '^':return POW;
	case '!':return FAC; 
	case '(':return L_P;
	case ')':return R_P; 
	case '\0':return EOE;}
}
char orderBetween(char c1, char c2) {
	return pri[change(c1)][change(c2)];
}
float fac(int n) {	return (2 > n) ? 1 : n * fac(n - 1);}//自然数的阶乘(小数的阶乘呢???不会实现...)
float calcu(char optr, float opnd) {	return fac(opnd);}
float calcu(float opnd1, char op, float opnd2) {
	float result = 1;
	switch (op) //判断运算符
	{
	case '+': {result = opnd1 + opnd2; return result; }
	case '-': {result = opnd1 - opnd2; return result; }
	case '*': {result = opnd1 * opnd2; return result; }
	case '/': {result = opnd1 / opnd2; return result; }
	case '^': {for (int i = 0; i < opnd2; i++) result *= opnd1; return result; }
	}//switch
}
float evaluate(char* S) {
	stack<float> opnd; stack<char> optr;
	optr.push('\0');
	while (!optr.empty()) {
		if (isdigit(*S)) {
			readNumber(S, opnd);
			//append(RPN, opnd.top());
		}
		else
			switch (orderBetween(optr.top(), *S)) {
			case '<':
				optr.push(*S); S++;
				break;
			case '=':
				optr.pop(); S++;
				break;
			case '>': {
				char op = optr.top(); optr.pop();
				if ('!' == op) {
					//因为我没有写stack的模板,而是直接用的是C++内部的stack.h头文件
					//stack.h 中pop函数的返回值为void,所以需要在pop之前先通过top函数取栈顶(top函数返回值为栈顶元素)然后再pop出栈
					float pOpnd = opnd.top(); opnd.pop();
					opnd.push(calcu(op, pOpnd));//实施一元运算
				}
				else {
					float pOpnd2 = opnd.top(); opnd.pop();
					float pOpnd1 = opnd.top(); opnd.pop();
					opnd.push(calcu(pOpnd1, op, pOpnd2));//实施二元运算
				}
				break;
			}
			default:exit(-1);
			}//switch
	}//while
	float Result = opnd.top();//先转存计算结果,再pop
	opnd.pop();
	return Result;//弹出并返回最后的计算结果
}
int main() {
	char S1[] = "2.3+3.5"; cout << "2.3+3.5=" << evaluate(S1) << endl;
	char S2[] = "7.3-3.5"; cout << "7.3-3.5=" << evaluate(S2) << endl;
	char S3[] = "2*6"; cout << "2*6=" << evaluate(S3) << endl;
	char S4[] = "8/2"; cout << "8/2=" << evaluate(S4) << endl;
	char S5[] = "(2+3)+2^3+3!"; cout << "(2+3)+2^3+3!=" << evaluate(S5) << endl;
	return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文武好呆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值