70,027
社区成员




int priority(char op)
{
if(op=='+'||op=='-')//加减
return 1;
else if(op=='*'||op=='/'||op=='%')//乘除和求余
return 2;
else if(op=='^')//乘方
return 3;
else{//其它无效
cerr << "invalid operator " << op << "!" << endl;
return -1;
}
}
//main.cpp
#include <iostream>
#include <ctype.h>
#include <math.h>
using namespace std;
#include "Calculator.h"
int main()
{
Calculator dstk(20); //声明一个对象,此时进行初始化.构造了容量为20的栈s
dstk.Push('#'); //初始时将'#'压入栈中
dstk.InfixToPostfix(dstk); //将中缀表达式转换为后缀表达式
dstk.Pop(); //删除遗留在栈s中的#号,使栈s用于计算后缀表达式用
dstk.Eval(dstk); //计算(后缀)达式的值
dstk.OutPut(dstk); //输出表达式结果
return 0;
}
//Calculator.h
enum ResultCode{Underflow,Overflow,MissingOperand,DivideByZero};
//计算器类
class Calculator
{
public:
Calculator(int mSize); //构造函数
bool IsEmpty(){return (top==-1);}
bool IsFull(){return (top==maxSize);}
int isp(char c); //栈内优先级函数
int icp(char c); //栈外优先级函数
void Push(const char &x); //向栈中添加非数值(如运算符等)元素函数,中缀表达式转后缀时
void Pop(); //删除栈顶元素
int Top(); //返回栈顶元素
void InfixToPostfix(Calculator &dstk); //将中缀表达式转换为后缀表达式函数
void Eval(Calculator &dstk); //运行计算器函数
void Clear(Calculator &dstk); //清除计算器
void OutPut(Calculator &dstk); //输出计算结果
private:
int top,maxSize;
int *s; //栈S
void PushOperand(char x); //后缀表达式中,使操作数x进栈
void PushCalcuRes(int result); //使两个操作数的运算结果进栈
bool GetOperands(int &x,int &y,Calculator &dstk); //取出栈顶两个操作数x和y
void DoOperator(char op,Calculator &dstk); //取出栈顶两个操作数x和y,执行运算y<op>x
};
Calculator::Calculator(int mSize)
{ //构造函数的实现
maxSize=mSize;
s=new int[maxSize];
top=-1;
}
int Calculator::isp(char c)
{
//计算运算符c的栈内优先级
int priority;
switch(c)
{
case '(':priority=0;break;
case '+':
case '-':priority=5;break;
case '*':
case '/':priority=6;break;
case '#':priority=0;break;
}
return priority;
}
int Calculator::icp(char c)
{
//计算运算符c的栈内优先级
int priority;
switch(c)
{
case '(':priority=8;break;
case '+':
case '-':priority=5;break;
case '*':
case '/':priority=6;break;
case '#':priority=0;break;
}
return priority;
}
void Calculator::Push(const char &x)
{ //使运算符进栈
if(IsFull())
throw Overflow;
s[++top]=x; //新元素进栈,一定要注意前缀加与后缀加的区别
}
void Calculator::Pop()
{
//删除栈顶元素
if(IsEmpty())
throw Underflow;
top--;
}
int Calculator::Top()
{
//返回栈顶元素
if(IsEmpty())
throw Underflow;
return s[top];
}
void Calculator::InfixToPostfix(Calculator &dstk)
{
//将中缀表达式转换为后缀表达式
char ch,y;
cout<<"请输入你要计算的表达式,以#号结束:";
while(cin>>ch,ch!='#')
{
if(isdigit(ch)||isalpha(ch))
cout<<ch;
else if(ch==')')
for(y=dstk.Top(),dstk.Pop();y!='(';y=dstk.Top(),dstk.Pop())
cout<<y;
else
{
for(y=dstk.Top();icp(ch)<=isp(dstk.Top());dstk.Pop())
cout<<y;
dstk.Push(ch); //当前运算符进栈
}
}
while ((dstk.IsEmpty()==false)&&(dstk.Top()!='#'))
{
y=dstk.Top();
dstk.Pop();
cout<<y;
}
cout<<endl;
}
void Calculator::Eval(Calculator &dstk)
{
//运行计算器函数
char m; //注意,这里是字符类型的,同样可以运算,只是是转换为对应的ASCII参与运算的(我在这里犯了错误)
cout<<"请输入上面计算下来的后缀表达式:"<<endl;
while (cin>>m,m!='#')
{
switch(m)
{
case '+':
case '-':
case '*':
case '/':
case '^':
DoOperator(m,dstk);
break;
default:
//cout<<"需要进栈的元素为:"<<m<<endl; //为了测试需要进栈的元素而加。纯属调试之用
dstk.PushOperand(m); //使操作数m进栈
//cout<<"而实际进栈的元素为:"<<s[top]<<endl; //为了测试实际进栈的元素而加。纯属调试之用
}
}
}
void Calculator::Clear(Calculator &dstk)
{
//清除计算器
dstk.Clear(dstk);
}
void Calculator::OutPut(Calculator &dstk)
{
int result;
result=dstk.Top();
cout<<"所计算的表达式的值为:"<<result<<endl;
}
void Calculator::PushOperand(char m)
{
//操作数m进栈,注意,此时m是个字符,m的值是它对应的ASCII码的值(在机器内的16进制表示)
int t=m;//此时计算时用的是m的ASCII码的值,不过在机器内是用16进制表示的,这里是将其转换为10进制表示,并赋给t
if(IsFull())
throw Overflow;
t=m-48; //将其转换为对应的整型数(描述可能有点不妥),然后进栈
s[++top]=t;
}
void Calculator::PushCalcuRes(int result)
{
if(IsFull())
throw Overflow;
s[++top]=result;
}
bool Calculator::GetOperands(int & x,int &y,Calculator &dstk)
{
//取出栈顶两个操作数x和y,执行运算y<op>x
if(dstk.IsEmpty())
throw MissingOperand; //抛出下溢异常
else
{
x=dstk.Top(); //返回栈顶元素并将其转换为其对应的ASCII码值的16进制表示,类型的强制转换
dstk.Pop();
}
if(dstk.IsEmpty())
throw MissingOperand;
else
{
y=dstk.Top(); //返回栈顶元素并将其转换为其对应的ASCII码值的16进制表示,将栈内的整型数进行
dstk.Pop();
}
return true;
}
void Calculator::DoOperator(char op,Calculator &dstk)
{
//计算(后缀)表达式的值
bool result;
int x,y;
result=GetOperands(x,y,dstk); //获取两个操作数
if(result) //判断是否获取成功
switch(op)
{
case '+':dstk.PushCalcuRes(y+x);break;
case '-':dstk.PushCalcuRes(y-x);break;
case '*':dstk.PushCalcuRes(y*x);break;
case '/':
if(x==0)
throw DivideByZero;
else
dstk.PushCalcuRes(y/x);
break;
case '^':dstk.PushCalcuRes(pow(y,x));break;
}
else
Clear(dstk);
}