中缀表达式计算实现代码

邓俊辉数据结构 栈应用之 中缀表达式计算

学堂在线教学视频
堆栈应用之一,在线性扫描类算法中当读到足够长之后,方可处理前缀。应用在计算器中。

#include <iostream>
#include "Stack.hpp" //自定义栈,可改成标准库#include<stack>
#include <math.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
#define N_OPTR 9//操作符定义九个 

template <class T>
int readnum(char *s,Stack<T> &num);//读书,输入字符型,这里转换成数值型,涉及到多位数值的转换。 
bool  isdigit(char s);//判断某个字符是否为数字字符 
int _getprioNum(char operation1);//得到操作符优先级 函数 
char orderBetween(char operation1,char operation2);//判断操纵符优先级函数 例如:operation1高于 operation2则返回> 
template<class T>T cacul(T opNum1,char oper,T opNum2);//计算函数,计算操作符为oper 操作数为 opNum1和opNum2的计算式,单目运算符是之一opNum1作为操作数 
template <class T>T evaluat(char *s);//参数s: 中缀表达式 以\0结尾;目标参数T返回值类型,运算数类型 

int main(int argc, char *argv[]) {
	Stack<int> s; //标准库为stack<int> s;
	Stack<char> s1;//标准库为stack<char> s;
	char *num="(1+2^3!-4)*(5!-(6-(7-(89-0!))))";
	
	std::cout<<evaluat<int>(num);
	/*readnum<int>(&num,s);
	while(!s.empty())
	 std::cout<<s.pop();*/ 
	return 0;
}


//中缀表达式计算
template <class T>//参数s: 中缀表达式 以\0结尾;目标参数T返回值类型,运算数类型 
T evaluat(char *s)
{
	Stack<T> num;//操作数 //标准库为stack<T>
	Stack<char> op;//操作符 //标准库为stack<char>
	op.push('\0');//先插入一个结束符,后文判断结束 
	int i=0;
		char oper;//临时操作符 
	while(!op.empty())//扫描转换 
	{
		if(isdigit(*s))
		{
			//T n=rednum(s[i]);//多位数,转化为可计算的类型 
		  //num.push(n);
		  int len=readnum<T>(s,num);
		  for(;len;len--)s++;	
		}else //若当前字符为运算符,则视其与栈顶操作符的高低 
		  switch(orderBetween(op.top(),*s)){
		  	//分别处理
		  	case '<'://压入栈中
			   op.push(*s); s++;break;
			case '>':
				//计算
				T opNum2;T opNum1;
				opNum2=num.pop();
				oper=op.pop(); 
				if('!'==oper) num.push(cacul(opNum2,oper,opNum2));//一元运算符 
				else {
					opNum1=num.pop();
				    //二元运算符 
					num.push(cacul(opNum1,oper,opNum2));
				}
				//压入栈中再往后 
			break;
			case '=':
				/*oper=op.top();
				if(oper=='(')
				{
				 op.pop();s++;
				}
				else if(oper=='\0')//最终必须执行这里 
				 return num.pop();*/ 
				 op.pop();s++;break;  
			default:
				return -1;
		  }
	} 
	return num.pop();
} 
//判断字符s是否是数字 
bool  isdigit(char s)
{
 return (s<='9' && s>='0'); 
}

template <class T>//返回读出多少位 视频内没有这个过程但是我认为内部s不会改变位置。 
int readnum(char *s,Stack<T> &num)
{
	int wei=0;
	T n;//数字栈
	 n=(*s)-'0';
	 s++;
	 wei++;
	while(isdigit(*s))
	{
	 wei++;
	 n*=10;
	 n+=(*s)-'0';
	 s++;
	}
	num.push(n);
	return wei;
}

//判断两操作符优先级
//如operation='-', operation='*';则返回< 
char orderBetween(char operation1,char operation2) 
{
	char orderPri[N_OPTR][N_OPTR]={//[栈顶][当前] 
	//    |----------当前运算符----------------------| 
	//			+    -   *   /   ^  !  (  )  \0
	/*-- + */   '>','>','<','<','<','<','<','>','>',
	/* | - */   '>','>','<','<','<','<','<','>','>',
	/*栈 * */   '>','>','>','>','<','<','<','>','>',
	/*顶 / */   '>','>','>','>','<','<','<','>','>',
	/*运 ^ */   '>','>','>','>','>','<','<','>','>',
	/*算 !*/   '>','>','>','>','>','>',' ','>','>',
	/*符( */   '<','<','<','<','<','<','<','=',' ',
	/* |) */   ' ',' ',' ',' ',' ',' ',' ',' ',' ',
	/* -- \0*/  '<','<','<','<','<','<','<',' ','='
	};
	//找到符号的编号
	 return orderPri[_getprioNum(operation1)][_getprioNum(operation2)];
}

template<class T>
T jiecheng(T num)//计算阶乘 
{
	T res=1;
	
	if(num==0)
	 return 1; 
	for(;num!=1;num--){
		res*=num;
	}
	return res;
}

template<class T>
T cacul(T opNum1,char oper,T opNum2=1)
{
	switch (oper){
		case '+':return opNum1+opNum2;
		case '-':return opNum1-opNum2;
		case '*':return opNum1*opNum2;
		case '/':return opNum1/opNum2;
		case '^':return pow(opNum1,opNum2);
		case '!':return jiecheng<T>(opNum1);
	};
}
int _getprioNum(char operation1)
{
	switch (operation1)
	{
		case '+':return 0;
		case '-':return 1;
		case '*':return 2;
		case '/':return 3;
		case '^':return 4;
		case '!':return 5;
		case '(':return 6;
		case ')':return 7;
		case '\0':return 8;
		 
	}
}

输出结果为2013

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值