复杂四则运算之C++实现方案

时间:2022-04-23 20:39:40

转载:http://blog.sina.com.cn/s/blog_786ce14d01014ixq.html

复杂四则运算之C++实现方案 

 #include<iostream>
 #include<cmath>
 using namespace std;
 const int MAX=1000;
 
 
 class Entry
 {
 public:
        static void welcome()
        {
             cout<<"欢迎来到本程序运算界面,该程序功能为根据表达式进行计算。\n"
                 <<"可以实现的计算为加减乘除四则运算,"
                 <<"支持小数运算,也支持负数的读入,但是要用括号将负数括起。\n"
                 <<"在下方输入处输入表达式,以回车结束。\n"
                 <<"=========================Felix============================\n\n"
                 <<"请输入表达式,回车结束:";
        }
 };
 
 
 class Input
 {
 public:
     Input()
     {
         for( int i = 0;i < MAX;i++ )
             Str_input[i] = '\0';
     }   
     char Str_input[MAX];
     void inStr()
     {
         cin>>Str_input;
     }
 };
 
 
 class Output
 {
 public:
     Output()
     {
         result = 0;
     }   
     void getRes( double res )
     {
         result = res;
     }
     void printRes()
     {
         cout<<"这个表达式的结果为:"<<result<<endl;
     }
 private:
     double result;
 };
 
 
 template <class Type>       
 class STACK{                 //定义栈类
    private:
        Type base[MAX];
        int Size;
    public:
        STACK(){Size=0;};
        void push(Type a)     //入栈
        {
            base[Size]=a;
            Size++;
        }
        Type pop()            //出栈
        {
            return base[--Size];
        }
        int size()
        {return Size;}
 };
 
 
 
 class Calculate_Cla
 {
 public:
     bool IsData(char);
     bool IsSym(char);
     int IsPar(char);
     bool Check(char *);
     int setPri(char);                 //判断符号的优先极别
     double ToData(char*);               //把字符串转化为数值
     double Call(double,double,char);    //具体按符号计算
     int GetMatch(char* buffer,int pos); //利用栈找到匹配的括号
     void Opr( STACK<char>&, STACK<double>&, int& ); //利用栈计算
     double Calculate(char*, double& );   //字符串的读入及调配
 
 };
 bool Calculate_Cla::IsData(char ch)      //判断输入计算的数字是否为0-9
 {
     return ((ch>='0'&&ch<='9')||ch=='.')?true:false;
 }
 bool Calculate_Cla::IsSym(char ch)      //判断是否输入非法运算符
 {
     return (ch=='+'||ch=='-'||ch=='*'||ch=='/')?true:false;
 }
 int Calculate_Cla::IsPar(char ch)
 {
     if(ch=='(')
        return 1;
     if(ch==')')
        return -1;
     return 0;
 }
 bool Calculate_Cla::Check(char *ch)
 {
     int a=0;
     for(int i=0;i<strlen(ch);i++)
         if(ch[i]=='.')
             a++;
         if(a>1)
             return false;
         return true;
 }
 int Calculate_Cla::setPri(char ch)          //符号的优先极别
 {
     switch(ch)
     {
     case '+':
         return 0;
     case '-':
         return 0;
     case '*':
         return 1;
     case '/':
         return 1;             
     default:
         return -1;
     }
 }         
 double Calculate_Cla::ToData(char* ch)   //将数字转化为数值
 {
     int i,j,sumn=0;
     double sum=0.0;
     if(!Check(ch)) return 0.0;
     for(i=0;i<strlen(ch);i++)             //读入整数部分
     {
         if(ch[i]!='.')
             sumn=sumn*10+(ch[i]-'0');
         else break;
     }
     if(i<strlen(ch))
         for(j=i+1;j<strlen(ch);j++)        //小数部分
             sum=sum*10+(ch[j]-'0');
     sum /= pow(10.0,(double)(strlen(ch)-1-i));
     return (sum+sumn);                      //返回值
 }
 double Calculate_Cla::Call(double sum,double data,char ch)
 {
     double ans=0.0;
     switch(ch)
     {
     case '+':
         ans=sum+data;        
         break;
     case '-':
         ans=sum-data;
         break;
     case '*':
         ans=sum*data;
         break;
     case '/':
         if( data != 0.0 )
             ans=sum/data;
         else
         {
             cout<<"程序出现除0错误,终止!\n";
             system("pause");
             exit(1);
         }
         break;              
     default:ans=0.0;
         break;    
     }
     return ans;
 }
 int Calculate_Cla::GetMatch(char* buffer,int pos)     //利用栈找到匹配的括号
 {
     STACK<char> Temp;
     int i;
     for(i=pos;i<strlen(buffer);i++)
     {
         if(IsPar(buffer[i])==1)
             Temp.push('0');
         if(IsPar(buffer[i])==-1)
         {
             Temp.pop();
             if(Temp.size()==0) return i;
         }
     }
     return -1;
 }
 void Calculate_Cla::Opr(STACK<char>& symbol,STACK<double>& data,int& mark)
 {
     double sum;
     while(symbol.size()!=0)
     {
         char tem=symbol.pop();
         int temp=setPri(tem);
         symbol.push(tem);
         if(temp<mark)
             break;
         else{
             sum=Call(data.pop(),data.pop(),symbol.pop());
             data.push(sum);
         }
     }
 }
 double Calculate_Cla::Calculate(char* buffer,double& sum)   //字符串读入和各个函数调配
 {
     STACK<double> data;
     STACK<char> symbol;
     double ans;
     char temp[MAX];
     int ct=0,mark=0,tp=0;
     data.push(sum);
     while(ct<=strlen(buffer))
     {
         if(IsData(buffer[ct]))            //如果是数字或小数点
         {
             while( ct < strlen(buffer) && IsData(buffer[ct]) )
                 temp[tp++]=buffer[ct++];
             temp[tp]='\0';
             tp=0;                         //读到非数字也非小数为止
             ans=ToData(temp);             //把读到的字符串转化为数
             data.push(ans);     
            
             if(ct==strlen(buffer))        //已经独到字符串末尾
             {
                 mark=0;
                 Opr(symbol,data,mark);    //计算
                 sum=data.pop();           //此时data栈中还剩一个数据,即是结果
                 return sum;               //返回结果
             }
             else{
                 int mark=setPri(buffer[ct]);
                 Opr(symbol,data,mark);     //计算
             }
         }
         else if(IsSym(buffer[ct]))         //如果是运算符
             symbol.push(buffer[ct++]);     //运算符入symbol栈
         else
         {
             char BF[100];int k=0;          //如果都不是,则只能是括号
             while( IsPar( buffer[ct] ) != 1 && ct <= strlen(buffer) )
                 BF[k++] = buffer[ct++];
             BF[k]='\0';     
             if(IsPar(buffer[ct])==1)       //一旦读到左括号,寻找它匹配的右括号
             {
                 int i,j;
                 char Temp[100];
                 for(i=ct+1,j=0;i<GetMatch(buffer,ct);i++,j++)
                     Temp[j]=buffer[i];     //把这对括号中的字符串存入Temp
                 Temp[j]='\0';
                 data.push(Calculate(Temp,sum)); //递归调用Calculate直到没有括号
                            //然后开始计算,值层层返回最后将最终结果放入data栈
                 ct+=(strlen(Temp)+1);       //跳过已经处理完的字符
                 if(ct+1==strlen(buffer))    //这里考虑字符串以括号结尾的情况
                 {
                     mark=0;
                     Opr(symbol,data,mark);
                     sum=data.pop();
                     return sum;
                 }
                 else
                 {
                     mark=setPri(buffer[ct+1]); //不是的话继续计算
                     Opr(symbol,data,mark);
                 }
                 ct++;                           //读入下一个字符
             }
         }
     }
     return 0.;
 }
 
 
 
 class CheckStr
 {
 public:
     static int check( char *str )
     {
         int i;
         STACK<char> Temp;
         for( i = 0;i < strlen(str);i++ )
         {
             char t = str[i];
             if( !(  (int(str[i]) <= 57 && int(str[i]) >= 48) || str[i]=='(' || str[i]==')' || str[i]=='*'
                 || str[i]=='+' || str[i]=='-' || str[i]=='/' || str[i]=='.')   )       //检测是否含有非法字符
                 return 2;
             else if( str[i]=='(' )  
                 Temp.push('0');
             else if( str[i]==')' )
             {
                 if( Temp.size()<=0 )                                      //检测括号是否匹配,右括号是否过多
                     return 1;
                 else
                     Temp.pop();
             }
         }
         if( Temp.size()!=0 )                                                //检测括号是否匹配,左括号是否过多
             return 1;
         return 0;
     }
 };
 
 int main()
 {
     Entry::welcome();                           //欢迎模块
     double sum=0.0;
     cout.precision(12);
    
     Input in;
     Calculate_Cla cl;
     Output out;
 
     while(1)
     {
         in.inStr();                              //输入模块
         int res = CheckStr::check(in.Str_input); //判断模块
         if( res == 0 )
             break;
         else if( res == 1 )
             cout<<"输入字符串括号不匹配,请重新输入:\n";
         else if( res == 2 )
             cout<<"输入字符串有非法字符,请重新输入:\n";
         else
         {}
     }
     out.getRes( cl.Calculate(in.Str_input,sum) ); //计算模块
     out.printRes();                               //输出模块
     system("pause");
     return 0;
 }