//***************************************************************************
//
// +-*/()运算表达式,函数
// 调用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