邓俊辉数据结构 栈应用之 中缀表达式计算
学堂在线教学视频
堆栈应用之一,在线性扫描类算法中当读到足够长之后,方可处理前缀。应用在计算器中。
#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