在假期间我写了一个用于计算表达式的C++类,终于明白了计算器的基本工作原理。以下是相关的代码,共有三个文件,分别是源文件,头文件和栈模板类头文件。
//Expression.cpp
#include "Expression.h"
#include
#include
using namespace std;
#define InitError \
this->error=new string[error]; \
this->error[0]="Error 0:A Number Divided By Zero."; \
this->error[1]="Error 1:Null Value."; \
this->error[2]="Error 2:Unknown Char."; \
this->error[3]="Error 3:Symbol After Symbol."; \
this->error[4]="Error 4:\'.\' After \'.\'";
Expression::Expression(int max,char depart,int error)
:stack(max),num(max),depart(depart)
{
InitError
}
Expression::~Expression()
{
if(error)
delete [] error;
}
Expression::Expression(string str,int max,char depart,int error)
:stack(max),num(max),depart(depart),str(str)
{
InitError
}
#undef InitError
void Expression::ReadString(string str)
{
this->str=str;
}
void Expression::Reset(int max)
{
stack.Reset(max);
stack.Clear();
num.Reset(max);
num.Clear();
}
inline bool Expression::Issymbol(char ch)//是否为运算符号
{
return ch=='*'||ch=='/'||ch=='^'||ch=='+'||ch=='-';
}
inline bool Expression::Isnum(char ch)//是否为数字或者小数点
{
return (ch>='0'&&ch<='9')||ch=='.';
}
inline bool Expression::Over(char ch1,char ch2)//运算符的优先级的判断
{
if(ch1=='(')
if(ch2=='(')
return false;
else
return true;
if(ch1=='^')
if(ch2=='^')
return false;
else
return true;
if(ch1=='*'||ch1=='/')
if(ch2=='+'||ch2=='-')
return true;
return false;
}
double Expression::Caculate1()//result保存了后缀表达式的值
{
try
{
PreRead();
}
catch(string e)
{
throw(e);
}
result=0;
behind="";
int max=str.length();
stack.Clear();
for(int i=0;i
//Expression.h
#ifndef _Expression_h_
#define _Expression_h_
#define _stack_max_ 10 //这里规定了递归的深度,太小程序会出现内存错误
//太大会浪费较多内存
#include
#include
using namespace std;
#include "stack.h"
class Expression
{
public:
Expression(int max=_stack_max_,char depart='#',int error=5);
Expression(string str,int max=_stack_max_,char depart='#',int error=5);
virtual ~Expression();
void ReadString(string str);
void Reset(int max);
double Caculate1();
double GetResult();
string GetBehind();
protected:
virtual void LoadSymbol();//此函数必须在子类中重写
virtual void PreRead();//此函数可以不用在子类中重写
inline virtual bool Issymbol(char ch);//这里应与LadSymbol()中的符号对应
inline bool Over(char ch1,char ch2);
inline bool Isnum(char ch);
inline double StrToDouble(string str);
char depart;
string str;
string behind;
string *error;
double result;
CStack
stack;
CStack
num;
};
#endif
//stack.h
#ifndef _Stack_h_
#define _Stack_h_
template
class CStack
{
public:
CStack(int max);
CStack(CStack
&temp);
~CStack();
bool IsEmpty();
bool IsFull();
bool Push(T temp);
T& Popup();
T Top();
void Clear();
void Reset(int max);
int GetMax();
private:
int max;
int top;
T* stack;
};
template
CStack
::CStack(int max)
{
this->max=max;
top=-1;
stack=new T[max];
}
template
CStack
::CStack(CStack
&temp):max(temp.max),top(temp.top) { stack=new T[max]; for(int i=0;i<=top;i++) stack[i]=temp.stack[i]; } template
CStack
::~CStack() { if(stack) delete [] stack; } template
bool CStack
::IsEmpty() { return (top<0||top>=max); } template
bool CStack
::IsFull() { return top==max-1; } template
bool CStack
::Push(T temp) { if(IsFull()) return false; stack[++top]=temp; return true; } template
T& CStack
::Popup() { return stack[top--]; } template
void CStack
::Clear() { top=-1; } template
void CStack
::Reset(int max) { if(this->max>=max) return; T* temp=new T[max]; for(int i=0;i<=top;i++) temp[i]=stack[i]; this->max=max; delete [] stack; stack=temp; } template
T CStack
::Top() { return stack[top]; } template
int CStack
::GetMax() { return max; } #endif
#include "Expression.h"
#include
#include
using namespace std;
#define InitError \
this->error=new string[error]; \
this->error[0]="Error 0:A Number Divided By Zero."; \
this->error[1]="Error 1:Null Value."; \
this->error[2]="Error 2:Unknown Char."; \
this->error[3]="Error 3:Symbol After Symbol."; \
this->error[4]="Error 4:\'.\' After \'.\'";
Expression::Expression(int max,char depart,int error)
:stack(max),num(max),depart(depart)
{
InitError
}
Expression::~Expression()
{
if(error)
delete [] error;
}
Expression::Expression(string str,int max,char depart,int error)
:stack(max),num(max),depart(depart),str(str)
{
InitError
}
#undef InitError
void Expression::ReadString(string str)
{
this->str=str;
}
void Expression::Reset(int max)
{
stack.Reset(max);
stack.Clear();
num.Reset(max);
num.Clear();
}
inline bool Expression::Issymbol(char ch)//是否为运算符号
{
return ch=='*'||ch=='/'||ch=='^'||ch=='+'||ch=='-';
}
inline bool Expression::Isnum(char ch)//是否为数字或者小数点
{
return (ch>='0'&&ch<='9')||ch=='.';
}
inline bool Expression::Over(char ch1,char ch2)//运算符的优先级的判断
{
if(ch1=='(')
if(ch2=='(')
return false;
else
return true;
if(ch1=='^')
if(ch2=='^')
return false;
else
return true;
if(ch1=='*'||ch1=='/')
if(ch2=='+'||ch2=='-')
return true;
return false;
}
double Expression::Caculate1()//result保存了后缀表达式的值
{
try
{
PreRead();
}
catch(string e)
{
throw(e);
}
result=0;
behind="";
int max=str.length();
stack.Clear();
for(int i=0;i
//Expression.h
#ifndef _Expression_h_
#define _Expression_h_
#define _stack_max_ 10 //这里规定了递归的深度,太小程序会出现内存错误
//太大会浪费较多内存
#include
#include
using namespace std;
#include "stack.h"
class Expression
{
public:
Expression(int max=_stack_max_,char depart='#',int error=5);
Expression(string str,int max=_stack_max_,char depart='#',int error=5);
virtual ~Expression();
void ReadString(string str);
void Reset(int max);
double Caculate1();
double GetResult();
string GetBehind();
protected:
virtual void LoadSymbol();//此函数必须在子类中重写
virtual void PreRead();//此函数可以不用在子类中重写
inline virtual bool Issymbol(char ch);//这里应与LadSymbol()中的符号对应
inline bool Over(char ch1,char ch2);
inline bool Isnum(char ch);
inline double StrToDouble(string str);
char depart;
string str;
string behind;
string *error;
double result;
CStack
stack;
CStack
num;
};
#endif
//stack.h
#ifndef _Stack_h_
#define _Stack_h_
template
class CStack
{
public:
CStack(int max);
CStack(CStack
&temp);
~CStack();
bool IsEmpty();
bool IsFull();
bool Push(T temp);
T& Popup();
T Top();
void Clear();
void Reset(int max);
int GetMax();
private:
int max;
int top;
T* stack;
};
template
CStack
::CStack(int max)
{
this->max=max;
top=-1;
stack=new T[max];
}
template
CStack
::CStack(CStack
&temp):max(temp.max),top(temp.top) { stack=new T[max]; for(int i=0;i<=top;i++) stack[i]=temp.stack[i]; } template
CStack
::~CStack() { if(stack) delete [] stack; } template
bool CStack
::IsEmpty() { return (top<0||top>=max); } template
bool CStack
::IsFull() { return top==max-1; } template
bool CStack
::Push(T temp) { if(IsFull()) return false; stack[++top]=temp; return true; } template
T& CStack
::Popup() { return stack[top--]; } template
void CStack
::Clear() { top=-1; } template
void CStack
::Reset(int max) { if(this->max>=max) return; T* temp=new T[max]; for(int i=0;i<=top;i++) temp[i]=stack[i]; this->max=max; delete [] stack; stack=temp; } template
T CStack
::Top() { return stack[top]; } template
int CStack
::GetMax() { return max; } #endif