注:此代码只能完成简单的加减乘除四则运算,但是不支持单目运算,更复杂的形式留待以后有时间再进一步完善。
#include "LinkedStack.h"
#include <cmath>
class Calculator
{
public:
Calculator()
{
t.MakeEmpty();
t.Push('#'); //栈底放一个'#'
}
void Run(); //执行表达式计算
void Clear(); //清栈
private:
void AddOperand(double value); //操作数进栈
bool Get2Operands(double & left,double & right); //从栈中退出两个操作数
void DoOperator(char op); //形成运算指令,进行计算
int isp(char ch); //判断操作符的栈内优先数
int icp(char ch); //判断操作符的栈外优先数
LinkedStack<double> s; //栈对象定义,用于后缀表达式的计算过程,存储操作数
LinkedStack<char> t; //栈对象定义,用于中缀表达式转后续表达式的过程,存储操作符
};
//读字符串并求一个后缀表达式的值,以字符'#'结束
void Calculator::Run()
{
char ch,ch1,op;
double newoperand;
cin>>ch;
while(1)
{
if(isdigit(ch)) //是操作数
{
//cout<<ch;
cin.putback(ch); //将字符放回输入流
cin>>newoperand; //重新读取操作数
AddOperand(newoperand); //将操作数放入栈中
cin>>ch; //读取下一扫描项
}
else
{
t.GetTop(ch1); //取栈顶操作符ch1
if (isp(ch1)<icp(ch)) //新输入操作符优先级高
{
t.Push(ch); //进栈
cin>>ch; //读取下一扫描项
}
else if (isp(ch1)>icp(ch)) //新输入操作符优先级低
{
t.Pop(op); //退栈
switch(op)
{
case '+':
case '-':
case '*':
case '/':
DoOperator(op); //是操作符,执行计算
break;
}
}
else //输入操作符优先级等于栈顶优先级
{
if(ch == '#')
break;
t.Pop(op);
if(op == '(')
cin>>ch;
}
}
}
assert(!s.IsEmpty());
double temp;
s.Pop(temp);
cout<<"The result is:"<<temp<<endl;
}
//清栈
void Calculator::Clear()
{
s.MakeEmpty();
}
//取两个操作数,根据操作符op形成运算指令并计算
void Calculator::DoOperator(char op)
{
double left,right;
bool result;
result = Get2Operands(left,right);
if(result == true)
{
switch(op)
{
case '+':
s.Push(left+right);
break;
case '-':
s.Push(left-right);
break;
case '*':
s.Push(left*right);
break;
case '/':
if(right == 0.0)
{
cerr<<"Divided by 0!"<<endl;
Clear();
exit(0);
}
else
s.Push(left/right);
break;
}
}
else
Clear();
}
//从操作数栈中取出两个操作数
bool Calculator::Get2Operands(double & left,double & right)
{
if(s.IsEmpty()) //栈空
{
cerr<<"Missing Right Operand!"<<endl;
return false;
}
s.Pop(right);
if(s.IsEmpty())
{
cerr<<"Missing Left Operand!"<<endl;
return false;
}
s.Pop(left);
return true;
}
//将操作数的值value进操作栈
void Calculator::AddOperand(double value)
{
s.Push(value);
}
int Calculator::isp(char ch)
{
switch (ch)
{
case '#':
return 0;
case '(':
return 1;
case '*':
case '/':
case '%':
return 5;
case '+':
case '-':
return 3;
case ')':
return 6;
}
return -1;
}
int Calculator::icp(char ch)
{
switch (ch)
{
case '#':
return 0;
case '(':
return 6;
case '*':
case '/':
case '%':
return 4;
case '+':
case '-':
return 2;
case ')':
return 1;
}
return -1;
}