📄 calculator.cpp
字号:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstring>
using namespace std;
//enum Boolean {Flase,True};
#define True 1
#define False 0
char**endp;//double strod(const char *s,char **endp);转换串S为double. *endp为未被转换的串的首地址
#include "stack.h" //包含栈类模板定义文件
class Calculator
{
private:
Stack <double> OPTR; //运算符栈
Stack <int> OPND; //操作数栈
void Enter (double num); //将操作数num压入栈
void Enter (int c); //将运算符c压入栈
//连续将两个操作数弹出栈,放在opnd1和opnd2中
int GetTwoOperands(double &opnd1,double &opnd2);
//将一个操作数弹出栈,放在opnd1中
int GetOneOperands(double &opnd1);
void Operate(double opnd1,int op,double opnd2);//双目运算符
void Operate(int op,double opnd1); //单目运算符
int In(int c) ;// 判断c是否为运算符
int Precede(int t1,int t2);// 判断两符号的优先关系
double Compute(void); //计算
public:
Calculator(void); //构造函数
void Run(void); //运行计算器程序
void Clear(void); //清空两栈
};
void Calculator::Enter (double num) //将操作数num压入栈
{OPND.Push(num);}
void Calculator::Enter (int c) //将运算符c压入栈
{OPTR.Push(c);}
//连续将两个操作数弹出栈,放在opnd1和opnd2中
//如果没有两个操作数,则返回False并输出相关信息
int Calculator::GetTwoOperands(double &opnd1,double &opnd2)
{
if(OPND.StackEmpty())//检查栈是否为空
{
cerr<<"Missing operand!"<<endl;
return False;
}
opnd1=OPND.Pop();//将右操作数弹出栈
if(OPND.StackEmpty())//检查栈是否为空
{
cerr<<"Missing operand!"<<endl;
return False;
}
opnd1=OPND.Pop();//将左操作数弹出栈
return True;
}
//将一个操作数弹出栈,放在opnd1中
//如果没有操作数,则返回False并输出相关信息
int Calculator::GetOneOperands(double &opnd1)
{
if(OPND.StackEmpty())//检查栈是否为空
{
cerr<<"Missing operand!"<<endl;
return False;
}
opnd1=OPND.Pop();//将操作数弹出栈
return True;
}
void Calculator::Operate(double opnd1,int op,double opnd2)
{
int result;
result=GetTwoOperands(opnd1,opnd2);//将两个操作数弹出栈
if(result==True)//如果成功,执行运算并将结果压入栈
{
switch(op)
{
case'+':OPND.Push(opnd2+opnd1);
break;
case'-':OPND.Push(opnd2-opnd1);
break;
case'*':OPND.Push(opnd2*opnd1);
break;
case'/':if(opnd1==0)//检查除数是否为0
{
cerr<<"Divide by 0!"<<endl;
OPND.ClearStack();
OPTR.ClearStack();//除数为0是清空栈
}
else
OPND.Push(opnd2/opnd1);
}
}
else
{
OPND.ClearStack();
OPTR.ClearStack();//操作数不够清空栈
}
}
void Calculator::Operate(int op,double opnd1)
{
int result;
result=GetOneOperands(opnd1);//将一个操作数弹出栈
if(result==True)//如果成功,执行运算并将结果压入栈
{
switch(op)
{
case'l':OPND.Push(log(opnd1));
break;
case'g':OPND.Push(log10(opnd1));
break;
case's':OPND.Push(sin(opnd1));
break;
case'o':OPND.Push(cos(opnd1));
break;
case't':OPND.Push(tan(opnd1));
break;
case'e':OPND.Push(exp(opnd1));
}
}
else
{
OPND.ClearStack();
OPTR.ClearStack();//操作数不够清空栈
}
}
//l->log;g->log10;s->sin;o->cos;t->tan;e->exp
int Calculator::Precede(int t1,int t2)
{ // 判断两符号的优先关系
int f;
switch(t2)
{
case '+':
case '-':if(t1=='('||t1=='=')
f='<';
else
f='>';
break;
case '*':
case '/':if(t1=='+'||t1=='-'||t1=='('||t1=='=')
f='<';
else
f='>';
break;
case 'l':
case 'g':
case 's':
case 'o':
case 't':if(t1=='+'||t1=='-'||t1=='('||t1=='='||t1=='*'||t1=='/')
f='<';
else
f='>';
break;
case 'e':if(t1=='e'||t1==')')
f='>';
else
f='<';
break;
case '(':if(t1==')')
{
printf("ERROR1输入非法!!!\n");
exit(1);
}
else
f='<';
break;
case ')':switch(t1)
{
case '(':f='=';
break;
case '=':printf("ERROR2输入非法!!!\n");
exit(1);
default: f='>';
}
break;
case '=':switch(t1)
{
case '=':f='=';
break;
case '(':printf("ERROR2输入非法!!!\n");
exit(1);
default: f='>';
}
}
return f;
}
int Calculator::In(int c)
{ // 判断c是否为运算符
switch(c)
{
case'+':
case'-':
case'*':
case'/':
case'l':
case'g':
case's':
case'o':
case't':
case'e':
case'(':
case')':
case'=':return True;
default:return False;
}
}
Calculator::Calculator(void) //构造函数
{}
double Calculator::Compute(void) //运行计算器程序
{ // 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
double opnd1,opnd2,d,m;int op,x;
char c; // 存放由键盘接收的字符串
char z[10]; // 存放浮点数字符串
int i;
// 初始化运算符栈
OPTR.Push('='); // =是表达式结束标志
// 初始化运算数栈
c=getchar();
x=OPTR.Peek();
while(c!='='||x!='=')
{
if(In(c)) // 是运算符之一
switch(Precede(x,c))
{
case'<':OPTR.Push(c); // 栈顶元素优先权低
c=getchar();
break;
case'=':x=OPTR.Pop(); // 脱括号并接收下一字符
c=getchar();
break;
case'>':op=OPTR.Pop(); // 退栈并将运算结果入栈
if(op=='+'||op=='-'||op=='*'||op=='/')
{
Operate(opnd1,op,opnd2);
}
else
{
Operate(op,opnd1);
}
}
else if(c>='0'&&c<='9'||c=='.') // c是操作数
{
i=0;
do
{
z[i]=c;
i++;
c=getchar();
}while(c>='0'&&c<='9'||c=='.');
z[i]=0;
d=strtod(z,(char**)endp); // 将字符串数组转为浮点数存于d
OPND.Push(d);
}
else // c是非法字符
{
printf("输出数超出范围或输入非法字符!!!\n");
exit(1);
}
x=OPTR.Peek();
}
m=OPND.Peek();
return m;
}
void Calculator::Run(void)
{
char t;
do{
printf("请输入算术表达式,负数要用(0-正数)表示,并以=结束\n");
printf("%f\n",Compute());
printf("继续请按y...\n");
getchar();
scanf("%c%*c",&t);
}while(t=='y'||t=='Y');
}
void Calculator::Clear(void)//清空两栈
{
OPND.ClearStack();
OPTR.ClearStack();
}
void main()
{
char t;
Calculator CALC;
CALC.Run();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -