⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 calculator.cpp

📁 编译原理课程设计
💻 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 + -