用于计算四则混合运算表达式的递归函数(第二版)

豆豆网   技术应用频道   2007年08月29日  【字号: 收藏本文

内容摘要:用于计算四则混合运算表达式的递归函数第二版

#include<math.h>
#pragmawarn-8060//屏蔽编译时的 Possibly incorrect assignment 警告
AnsiString__fastcallCalc(StringsExp)
{
  //计算不带变量的四则混合运算表达式(支持取整int和圆整round函数,支持负操作数)
  //正数不许带正号
  intposL,pos,posR,posM;//pos->当前考虑的运算符的位置
  //posL->当前考虑的运算符之前最近的运算符的位置
  //posR->当前考虑的运算符之后最近的运算符的位置
  //posM->圆整函数中逗号的位置
  StringsTmp,sL,sR;
  //sL->当前考虑的运算符的左操作数字符串,sR->当前考虑的运算符的右操作数字符串
  boolIsMinus;//IsMinus->当前*/序列的符号
  sExp=sExp.LowerCase();
  if(sExp.AnsiPos("error"))
    return(sExp);
  while(pos=sExp.AnsiPos(""))
    sExp=sExp.Delete(pos,1);//去除表达式中的空格
  if(sExp.IsEmpty())
    return("0");
  while((pos=sExp.AnsiPos("["))>0||(pos=sExp.AnsiPos("{"))>0)//统一左括号为(
    sExp=sExp.SubString(1,pos-1)+"("
        +sExp.SubString(pos+1,sExp.Length());
  while((pos=sExp.AnsiPos("]"))>0||(pos=sExp.AnsiPos("}"))>0)//统一右括号为)
    sExp=sExp.SubString(1,pos-1)+")"
        +sExp.SubString(pos+1,sExp.Length());
  //以下处理round圆整函数
  while(pos=sExp.AnsiPos("round("))
  {
    posL=pos+5;
    while(posM=sExp.SubString(posL+1,sExp.Length()).AnsiPos("round("))
      posL=posL+posM+5;//最后一个round之后的位置
    for(posM=posL+2;!sExp.IsDelimiter(",",posM)
        &&posM<=sExp.Length();posM++);//round后第一个,的位置
      if(posM==0)return("error:round没有配对的逗号,公式错!");
    for(posR=posM+2;!sExp.IsDelimiter(")",posR)
        &&posR<=sExp.Length();posR++);//逗号后第一个)的位置
      //posR不从posM+1而从posM+2开始搜索,是为了应对操作数为负的情况
      sExp=sExp.SubString(1,posL-6)
          +floor(Calc(sExp.SubString(posL+1,
          posM-posL-1)).ToDouble()*pow(10,
          sExp.SubString(posM+1,posR-posM-1).ToDouble())
// 本文转自 C++Builder 研究 - http://www.ccrun.com/article.asp?i=636&d=x5fncl
          +0.5)/pow(10,sExp.SubString(posM+1,
          posR-posM-1).ToDouble())
          +sExp.SubString(posR+1,sExp.Length());
  }
  //处理括号:递归计算括号中的表达式,最后消去括号
  while(posL=sExp.LastDelimiter("("))//最里层(
  {
    sTmp=sExp.SubString(posL+1,sExp.Length());
    posR=sTmp.AnsiPos(")");//最里层)
    if(posR==0)
      return("error:没有配对的),公式错!");
    sExp=sExp.SubString(1,posL-1)
        +Calc(sTmp.SubString(1,posR-1))
        +sTmp.SubString(posR+1,sTmp.Length());
  }
  //以下处理int取整函数
  while(pos=sExp.AnsiPos("int"))
  {
    posL=pos+2;
    for(posR=posL+2;!sExp.IsDelimiter("+-*/",posR)
        &&posR<=sExp.Length();posR++);//其后第一个+-*/
      //posR不从posL+1而从posL+2开始搜索,是为了应对操作数为负的情况
      sExp=sExp.SubString(1,pos-1)
          +floor(sExp.SubString(posL+1,posR-posL-1).ToDouble())
          +sExp.SubString(posR,sExp.Length());
  }
  //以下处理不带括号表达式中的*/序列
  IsMinus=false;//IsMinus->当前*/序列的符号
  while(sExp.LastDelimiter("*/"))//存在*或/
  {
    for(pos=1;!sExp.IsDelimiter("*/",pos)
        &&pos<=sExp.Length();pos++);//第一个*或/
      if(pos==1||pos==sExp.Length())
        return("error:首或尾字符是*/运算符,公式错!");
    //posL->第一个*/之前的第一个+-
    posL=sExp.SubString(1,pos-1).LastDelimiter("+-");
Minus0:
    for(posR=pos+1;!sExp.IsDelimiter("+-*/",posR)
        &&posR<=sExp.Length();posR++);
      //posR->第一个*/之后的第一个+-*/运算符
      if(posR==(pos+1)&&sExp.IsDelimiter("*/",posR))
        return("error:*/运算符相邻,公式错!");
      if(posR==sExp.Length())
        return("error:尾字符是+ -*/运算符,公式错!");
      if(sExp.SubString(pos,2)=="*-"
          ||sExp.SubString(pos,2)=="/-")//乘数或除数为负
      {
        sExp.Delete(pos+1,1);
        IsMinus=!IsMinus;
        gotoMinus0;
      }
      sL=sExp.SubString(posL+1,pos-posL-1);
      sR=sExp.SubString(pos+1,posR-pos-1);
      if(sExp.IsDelimiter("/",pos)&&sR=="0")
        return("error:除数为零,无意义!");
      sExp=(posL==0?String(""):
          sExp.SubString(1,posL))+(sExp.IsDelimiter("*",pos)?
          (sL.ToDouble()*sR.ToDouble()):
          (sL.ToDouble()/sR.ToDouble()))
          +sExp.SubString(posR,sExp.Length());
  }
  if(IsMinus)
    sExp=String("-")+sExp;
  //经过上面的系列处理,sExp中的运算符号只剩下+和-了
  //以下处理不带括号表达式中的+-序列
  IsMinus=false;//加数或减数的符号
  while(sExp.LastDelimiter("+-"))//存在+或-
  {
    for(pos=2;!sExp.IsDelimiter("+-",pos)
        &&pos<=sExp.Length();pos++);//第一个+或-
    //pos不从1而从2开始搜索,是为了应对首操作数为负的情况
    if(pos==sExp.Length())
      return("error:尾字符是+-运算符,公式错!");
    if(pos>sExp.Length())
      return(sExp);//sExp是一个简单的负数,不必计算
Minus1:
    for(posR=pos+1;!sExp.IsDelimiter("+-",posR)
        &&posR<=sExp.Length();posR++);
      if(posR==sExp.Length())
        return("error:尾字符是+-运算符,公式错!");
    if(sExp.SubString(pos,2)=="+-"
        ||sExp.SubString(pos,2)=="--")//加数或减数为负
    {
      sExp.Delete(pos+1,1);
      IsMinus=!IsMinus;
      gotoMinus1;
    }
    //此处跳转在正常情况下最多只会执行一次
    sL=sExp.SubString(1,pos-1);
    sR=sExp.SubString(pos+1,posR-pos-1);
    sExp=String(sExp.IsDelimiter("+",pos)?
        (sL.ToDouble()+sR.ToDouble()*(IsMinus?-1:1)):
        (sL.ToDouble()-sR.ToDouble()*(IsMinus?-1:1)))
        +sExp.SubString(posR,sExp.Length());
  }
  return(sExp);
}

  本文出处:http://www.ccrun.com/article.asp?i=636&d=x5fncl

来源:ccrun    作者:billow3    责编:豆豆技术应用

正在加载评论...