C++bulid中表达式求值

//***************************************************************************
//
// +-*/()运算表达式,函数
// 调用ExpCalc(AnsiString pexpr,bool &pt)
// 输入pexpr,bool型 pt;
// 如果表达式子无误,pt为true,并返回计算结果
/*
   设计思想按"算符优先法",参考严蔚敏和吴伟民的数据结构45页算法;

*/
//


#ifndef ExpcalacH
#define ExpcalacH
//---------------------------------------------------------------------------
#include <vcl.h>
#include <stack>  //使用了stl的栈
using namespace std;
bool  findnumber(AnsiString pexpr,int pos,AnsiString &pnumber,int &i)
{
  /****************************************
   功能:将一个表达式中的数字串取出,
   pexpr是表达式,pos是起始位置,pnumber是取得数字串;
   成功了是返回true,没有数字串返回false;

   总体办法:是设定数值串-+0123456789后,将pexpr的每个字符和数值串进行判断子串;
   如果在pexpr中就放入pnumber中;注意+-.(表示正负符号)只能出现一次;

  *****************************************/
   AnsiString numset="-+.0123456789";    //设定数值串的具体值
   AnsiString tems=pexpr;
   i=pos;
   int pad=1;                           //统计加减出现次数;
   int ppos;
   int pdepo=1;                        //统计小数点出现次数;
   int padnum=1;
   int pdeponum=2;
   pnumber="";                        //将pnumber初始;
   int first=numset.Pos(tems[i]);
   if (first==1||first==2)
       padnum=2;
   if (first==3)
      pdeponum=2;
   while((ppos=numset.Pos(tems[i]))>0 && i<=tems.Length()&&pad<=padnum &&pdepo<=pdeponum) //当找到并+-符号出现小于2次
      {


       if(ppos<3)                      //是+ - 符号 位置1,2
         {
         pad++;
         if (pad>padnum)
         break;
         }
       if(ppos==3)                      //.符号3
         {
          pdepo++;
          if (pdepo>pdeponum)
             break;
         }
       pnumber=pnumber+tems[i];    //+ - .符号出现二次了
       i++;


      }
    //

   if (i==pos)                          //当启示位置和结束位置相等表示没有数值被取到
      return false;
   if (pnumber.Length()==1&&numset.Pos(pnumber[1])<4)  //"+" or "-" or "."
      return false;
   if (pnumber.Length()==2&&numset.Pos(pnumber[1])<3&&numset.Pos(pnumber[2])==3 )//"+." or "-."
      return false;
   return true;


}

 

 

int  Readsubstr(AnsiString pexpr,int pos, AnsiString &psubstr,int &i,bool&cg,int state)

{
  /* ***************************************************************
  *返回0--表示是数值,1--是运算符,2--表示无法识别取得的类型
  * state表示+-在数字前是否看作正负号;
  * i无楞成功与否是i=到下一个单词第一位置;
  *****************************************************************/
  AnsiString opertset ="()+-*/#";
  AnsiString opad="+-";
  AnsiString tems=pexpr;
  i=pos;
  psubstr="";
  cg=false;

  if (state==0)
   {
   if(findnumber(tems,pos,psubstr,i))
      {
        cg=true;
        return 0;
      }
      psubstr="";
      i=pos;
   if(opertset.Pos(tems[i])>0)
      {
       psubstr+=tems[i];
       i++;
       cg=true;
       return 1;
      }
   }
  else
   {
     i=pos;
   if(opertset.Pos(tems[i])>0)
     {
       psubstr+=tems[i];
       i++;
       cg=true;
       return 1;
     }
      psubstr="";
      i=pos+1;
   if(findnumber(tems,pos,psubstr,i))
     {
        cg=true;
        return 0;
     }

   }
  i=pos+1;
  return 2;


}

int precede(AnsiString opt1, AnsiString opt2)
{
   int oopower[7][7]=
   {
     //-------------------------- -
    //  / optr2
    //      算符优先关系表          |
   //opt1/  + - * / ( ) #         |
   //-----------------------------
  /*+*/    {2,2,0,0,0,2,2},

  /*-*/    {2,2,0,0,0,2,2},

  /* * */  {2,2,2,2,0,2,2},

  /*/*/    {2,2,2,2,0,2,2},

  /*(*/    {0,0,0,0,0,1,-1},

  /*)*/    {2,2,2,2,-1,2,2},

  /*#*/    {0,0,0,0,0,-1,1},
   } ;

  AnsiString opertset ="+-*/()#";
  int x=opertset.Pos(opt1);
  int y=opertset.Pos(opt2);
  return  oopower[x-1][y-1];
}

//----------------------------------------------------------------------------

/*
  计算a+b,a-b,a*b,a/b的值


*/
float  Operate(float a, AnsiString oper, float b)
{
   AnsiString opertset ="+-*/";
     switch (opertset.Pos(oper))
       {
         case 1:
          return a+b;

         case 2:
          return a-b;

         case 3:
          return a*b;

         case 4:
          return a/b;

       }
}

//---------------------------------------------------------------------------


/**********************************************
 输入pexpr,bool型 pt;
 如果表达式子无误,pt为true,并返回计算结果
***********************************************/
float ExpCalc(AnsiString pexpr,bool &pt)
{
  pt=true;
  AnsiString opertset="+-*/()#";
  AnsiString tems=pexpr+"#";
 
  stack <AnsiString> optr;
  stack <float> opnd;
  AnsiString theta;
  optr.push("#");
  AnsiString w;
  int pos=1;
  int i;
  bool cg=false;
  int oplx=Readsubstr(tems,pos,w,i,cg,0);
  if(!pt)
  return -10000;
  int power;
  float a,b;
  while (/*!(w.Pos("#")==1 && optr.top().Pos("#")==1)&& */ i<=tems.Length()+1)
    {
       switch (oplx)
        {
         case 0 : //"数值"
           opnd.push(StrToFloat(w));
           pos=i;
           if(i<tems.Length())
             {
               oplx=Readsubstr(tems,pos,w,i,pt,1);
               if(!pt)
                return -10000;
             }
              else
              {
                w="#" ;
                oplx=1;
                i++;
              }


           break;
         case 1: //"运算符"
           {

              power=precede(optr.top(),w);
            

              switch (power)
                  {
                    case -1: //)( ,#),(# 出现
                      return -10000.00;
                    case 0: //"<"
                       optr.push(w);
                       pos=i;
                       if(i<tems.Length())
                         {

                             oplx=Readsubstr(tems,pos,w,i,pt,0);
                             if(!pt)
                             return -10000;
                   
                          }
                       else
                         {
                              w="#" ;
                              oplx=1;
                              i++;
                         }

                       break;
                    case 1: //"="

                       optr.pop();
                       pos=i;
                       if(i<tems.Length())
                         {
                           oplx=Readsubstr(tems,pos,w,i,pt,1);
                           if(!pt)
                           return -10000;
                         }

                       else
                          {
                             w="#" ;
                             oplx=1;
                             i++;
                          }

                       break;
                    case 2: //">"
                       if(optr.empty())
                         {
                          pt=false;
                         return 10000;
                         }
                       theta=optr.top();
                       optr.pop();
                       if(opnd.empty())
                         {
                          pt=false;
                          return 10000;
                         }
                       b=opnd.top();
                       opnd.pop();
                        if(opnd.empty())
                         {
                          pt=false;
                          return 10000;
                         }
                       a=opnd.top();
                       opnd.pop();
                       opnd.push(Operate(a,theta,b));


                     
                       pos=i;
                    

                       break;

                  }

                break;

           }

         case 2: //有不可识别的;
           return -10000;
        }

    }
  pt=true;
  return opnd.top() ;
}

#endif

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值