📄 calcformule.cpp
字号:
// CalcFormula.cpp: implementation of the CCalcFormula class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CalcFormule.h"
#include "RegularOpt.h"
#include <math.h>
#include "..\..\..\String\StringOpt.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
int COptStack::m_OptPri[]={ 5,5,6,6, 4,4,4, 4, 4, 4, 2,3,9,8,5,5, 4, 7, 4,4,4,4};
//+ - * / == > < <= >= != | & ! ^ >><<like in
//5 is normal
COptStack::COptStack():
m_nLen(0)
{
}
COptStack::~COptStack()
{
}
int COptStack::PushOpt(int optID)
{
if( m_nLen == 0 || m_OptPri[optID-OP_BASE] > m_OptPri[ m_OptStack[m_nLen-1]-OP_BASE]){
m_OptStack[m_nLen] = optID;
m_nLen ++;
return 0;
}else
return PopOpt();
}
int COptStack::PopOpt()
{
if(m_nLen>0)return m_OptStack[--m_nLen];
return 0;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define RETURNEMPTY return CString("")
CSZGetWord::CSZGetWord(LPCTSTR szFormula):
m_nPos(0),
m_bAcceptOpt(false)
{
//if(szFormula!=NULL)
m_sFormula = szFormula;
m_nSl = strlen(m_sFormula);
m_bIsBack = false;
}
CSZGetWord::~CSZGetWord(){}
void CSZGetWord::SetFormula(LPCTSTR szFormula)
{
m_sFormula = szFormula;
m_nPos=0;
m_nSl = strlen(m_sFormula);
m_bIsBack = false;
m_bAcceptOpt = false;
}
CString CSZGetWord::FormatWord(LPCTSTR szWord)
{
int sl = strlen(szWord);
if(sl >= 2 && (( szWord[0]=='\"' && szWord[sl-1]=='\"') || ( szWord[0]=='\'' && szWord[sl-1]=='\'')) )
return CString(szWord);
if(CRegularOpt::IsNumber(szWord) || CRegularOpt::IsTrue(szWord)) return CString(szWord);
return '\''+CString(szWord)+'\'';
}
CString CSZGetWord::getAWord()
{
if(m_bIsBack) {
m_bIsBack = false;
return m_preWord;
}
return CRegularOpt::GetARegularWord(m_sFormula,m_nPos,m_nSl,m_bAcceptOpt);
// if(bFormatWord)
// sCurWord = FormatWord(sCurWord);
// m_preWord = sCurWord;
// return sCurWord;
}
// CSZGetWordWithPrm :public CSZGetWord
CSZGetWordWithPrm::CSZGetWordWithPrm(LPCTSTR szFormula,LPCTSTR szParams):
CSZGetWord(szFormula),
paramList(64),
m_nParamSum(0)
{
// if (szParams!=NULL)
SetParameters(szParams);
}
CSZGetWordWithPrm::~CSZGetWordWithPrm(){}
CString CSZGetWordWithPrm::GetParamValue(int nInd)
{
if(nInd>=0 && nInd<m_nParamSum){
POSITION pos = paramList.FindIndex(nInd);
return paramList.GetAt(pos).sParamValue;
}
return CString("");
}
CString CSZGetWordWithPrm::GetParamValue(LPCTSTR sParamName)
{
POSITION pos = paramList.GetHeadPosition();
while(pos!=NULL){
SParameter & param = paramList.GetNext(pos);
if(param.sParamName.CompareNoCase(sParamName)==0)
return param.sParamValue;
}
return CString("");
}
void CSZGetWordWithPrm::SetParameters(LPCTSTR szParams)
{
if(szParams==NULL) return;
CString strParams(szParams);
int nStart=0,nPos=0,nTmp;
m_nParamSum = 0;
SParameter param;
paramList.RemoveAll();
CString sParamDesc;
nPos = strParams.Find(',',nStart);
while(nPos>=0){
if(nPos>nStart){
sParamDesc = strParams.Mid(nStart,nPos-nStart);
nTmp = sParamDesc.Find(':');
if(nTmp>0){
param.sParamName = sParamDesc.Mid(0,nTmp);
param.sParamValue = sParamDesc.Mid(nTmp+1);
}else{
param.sParamName.Format("Param%d",m_nParamSum);
if(nTmp==0)
param.sParamValue = sParamDesc.Mid(1);
else
param.sParamValue = sParamDesc;
}
}
paramList.AddTail(param);
m_nParamSum++;
nStart = nPos+1;
nPos = strParams.Find(',',nStart);
}
sParamDesc = strParams.Mid(nStart);
nTmp = sParamDesc.Find(':');
if(nTmp>0){
param.sParamName = sParamDesc.Mid(0,nTmp);
param.sParamValue = sParamDesc.Mid(nTmp+1);
}else{
param.sParamName.Format("Param%d",m_nParamSum);
if(nTmp==0)
param.sParamValue = sParamDesc.Mid(1);
else
param.sParamValue = sParamDesc;
}
paramList.AddTail(param);
m_nParamSum++;
//return CString("");
}
void CSZGetWordWithPrm::SetUnnamedParameters (int nParamSum,...)
{
SParameter param;
paramList.RemoveAll();
va_list arg_ptr;
const char * sArg ;
va_start( arg_ptr, nParamSum ); /* Initialize variable arguments. */
for(int i=0; i<nParamSum; i++){
param.sParamName.Format("Param%d",i);
sArg = va_arg( arg_ptr, const char * );
param.sParamValue = sArg;
paramList.AddTail(param);
}
va_end( arg_ptr );
m_nParamSum = nParamSum;
}
void CSZGetWordWithPrm::SetNamedParameters(int nParamSum,...)
{
SParameter param;
paramList.RemoveAll();
va_list arg_ptr;
const char * sArg ;
va_start( arg_ptr, nParamSum ); /* Initialize variable arguments. */
for(int i=0; i<nParamSum; i++){
sArg = va_arg( arg_ptr, const char * );
param.sParamName = sArg;
sArg = va_arg( arg_ptr, const char * );
param.sParamValue = sArg;
paramList.AddTail(param);
}
va_end( arg_ptr );
m_nParamSum = nParamSum;
}
void CSZGetWordWithPrm::AddParameter(LPCTSTR szParamName,LPCTSTR szParamValue)
{
SParameter param;
param.sParamName = szParamName;
param.sParamValue = szParamValue;
paramList.AddTail(param);
m_nParamSum++;
}
void CSZGetWordWithPrm::SetFormula(LPCTSTR szFormula)
{
CSZGetWord::SetFormula(szFormula);
paramList.RemoveAll();
m_nParamSum = 0;
}
CString CSZGetWordWithPrm::getAWord()
{
CString sRes = CSZGetWord::getAWord();
int nSL=sRes.GetLength();
if(nSL>1 && sRes[0]=='@') {
sRes = sRes.Mid(1,nSL-1);
if( CRegularOpt::IsNumber(sRes) ) return GetParamValue(atoi(sRes));
return GetParamValue(sRes);
}
// if(bFormatWord)
// sRes = FormatWord(sRes);
// m_preWord = sCurWord;
return sRes;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
UINT CCalcFormula::m_uiSysStrSum=1;
tagSysString CCalcFormula::m_sSysStrList[]={
{"jzx","金寨县"}
};
UINT CCalcFormula::m_uiFunctionSum = 34;
tagFunctionInfo CCalcFormula::m_sFunctionList[]={
{"ave",-1,FUNC_AVE,TYPE_NUM}, //求均值 ave(1,2,3)=2
{"byte",2,FUNC_BYTE,TYPE_NUM}, //求位值 byte(4321.789,2)=2
// byte(4321.789,-2)=8
// byte("4321.789",2)=3
{"capital",1,FUNC_CAPITAL,TYPE_STR}, // capital(123.45)="一百二十三点四五"
{"if",3,FUNC_IF,TYPE_STR}, // if(1,2,3)= 2 if(0,"2","3")= "3"
{"match",2,FUNC_MATCH,TYPE_NUM}, //匹配*?为通配符 match("abcd","a??d")=1
// match("abcd","a*d")=1
{"max",-1,FUNC_MAX,TYPE_NUM}, // 求最大值 max(1,2,3,5,4) = 5
{"min",-1,FUNC_MIN,TYPE_NUM}, // 求最小值 max(1,2,3,5,4) = 1
{"count",-1,FUNC_COUNT,TYPE_NUM}, // 计数 max(1,"2",3,"5",1,1,4) = 7
{"round",1,FUNC_ROUND,TYPE_NUM}, // 四舍五入
{"strcat",-1,FUNC_STRCAT,TYPE_STR}, // 连接字符串 strcat("12","34","56")="123456"
{"sum",-1,FUNC_SUM,TYPE_NUM}, // 求和 sum(1,2,3,4,5) = 15
{"stddev",-1,FUNC_STDDEV,TYPE_NUM}, // 求标准偏差
{"log",1,FUNC_LOG,TYPE_NUM}, // 求以10为底的对数
{"ln",1,FUNC_LN,TYPE_NUM}, // 求自然对数
{"sin",1,FUNC_SIN,TYPE_NUM}, // 求正弦
{"cos",1,FUNC_COS,TYPE_NUM}, // 求余弦
{"tan",1,FUNC_TAN,TYPE_NUM}, // 求正切
{"ctan",1,FUNC_CTAN,TYPE_NUM}, // 求正切
{"exp",1,FUNC_EXP,TYPE_NUM}, // 求以e为底的指数
{"sqrt",1,FUNC_SQRT,TYPE_NUM}, // 求平方根
{"substr",2,FUNC_SUBSTR,TYPE_STR}, // 求字符串子串 substr("123456",2,3)="345"
{"find",2,FUNC_FIND,TYPE_NUM}, //求子串位置 find("123456","34")=2 find("123456","35")=-1
{"frequence",2,FUNC_FREQUENCE,TYPE_NUM}, // 求子串个数 find("12345236","23")=2
{"integer",1,FUNC_INT,TYPE_NUM}, // 求整数部分 int(12.34)=12 int(-12.34)=-12
{"frac",1,FUNC_FRAC,TYPE_NUM}, // 求小数部分 frac(12.34)=0.34 frac(-12.34)=-0.34
{"today",-1,FUNC_TODAY,TYPE_NUM},//当前日期
{"day",-1,FUNC_DAY,TYPE_NUM},//日期函数
{"month",-1,FUNC_MONTH,TYPE_NUM},//日期函数
{"year",-1,FUNC_YEAR,TYPE_NUM},//日期函数
{"dayspan",1,FUNC_DAY_SPAN,TYPE_NUM},//日期函数 求两日期之间的天数
{"monthspan",1,FUNC_MONTH_SPAN,TYPE_NUM},//日期函数 求两日期之间的月数
{"getsysstr",1,FUNC_GET_STR,TYPE_STR},//取系统字符串
{"getpy",1,FUNC_GET_PY,TYPE_STR},//取汉字拼音
{"yearspan",1,FUNC_YEAR_SPAN,TYPE_NUM}//日期函数 求两日期之间的年数
};
// +-*/ ()
CCalcFormula::CCalcFormula():
m_lpGetWord(NULL)
{
}
CCalcFormula::~CCalcFormula()
{
}
int CCalcFormula::GetFuncNo(LPCTSTR sFuncName)
{
for(UINT i=0; i<m_uiFunctionSum; i++)
if(strcmp(sFuncName,m_sFunctionList[i].sName) == 0) return i;
return -1;
}
int CCalcFormula::GetOptID(LPCTSTR sOptName)
{
int sl = strlen(sOptName);
if(sl == 0) return -1;
char sp = sOptName[0], sp2= '\0';
if(sl>1) sp2 = sOptName[1];
switch(sp){
case '=':
if(sp2 == '=') {
return(OP_EQ);//m_iPreIsn = OP_EQ ;return OP_EQ;
}
return(OP_EVALUATE);// m_iPreIsn = OP_EVALUATE;return OP_EVALUATE;
case '+': return(OP_ADD); //{ m_iPreIsn = OP_ADD ; return OP_ADD ;}
case '-': return(OP_SUB);//{ m_iPreIsn = OP_SUB ; return OP_SUB;}
case '*': return(OP_MUL);//m_iPreIsn = OP_MUL; return OP_MUL;
case '/': return(OP_DIV);//m_iPreIsn = OP_DIV; return OP_DIV;
case '^': return(OP_POWER);//m_iPreIsn = OP_POWER; return OP_POWER;
case '>':
if(sp2 == '=') {
return(OP_EB);// return OP_EB; m_iPreIsn = OP_EB ;
}
if(sp2 == '>')
return (OP_LMOV);
return(OP_BG);//m_iPreIsn = OP_BG ; return OP_BG ;
case '<':
if(sp2 == '=') {
return(OP_EL);//return OP_EL; m_iPreIsn = OP_EL;
}
if(sp2 == '>') {
return(OP_NE);// return OP_NE; m_iPreIsn = OP_NE ;
}
if(sp2 == '<') {
return(OP_RMOV);// return OP_NE; m_iPreIsn = OP_NE ;
}
return(OP_LT);//m_iPreIsn = OP_LT ;return OP_LT ;
case '&':
if(sp2 == '&') {
return(OP_AND);//return OP_EL; m_iPreIsn = OP_EL;
}
return(OP_BITAND);//m_iPreIsn = OP_AND ; return OP_AND;
case '|':
if(sp2 == '|') {
return(OP_OR);//return OP_EL; m_iPreIsn = OP_EL;
}
return(OP_BITOR);//m_iPreIsn = OP_OR; return OP_OR;
case '!':
if(sp2 == '=') {
return(OP_NE);//return OP_NE; m_iPreIsn = OP_NE;
}
return(OP_NOT);//m_iPreIsn = OP_NOT; return OP_NOT;
}
if(CString("LIKE").CompareNoCase(sOptName) == 0)
return(OP_LIKE);
if(CString("AND").CompareNoCase(sOptName) == 0)
return(OP_AND);
if(CString("OR").CompareNoCase(sOptName) == 0)
return(OP_OR);
if(CString("NOT").CompareNoCase(sOptName) == 0)
return(OP_NOT);
if(CString("IN").CompareNoCase(sOptName) == 0)
return(OP_IN);
if(CString("DIV").CompareNoCase(sOptName) == 0)
return(OP_DIV);
return -1;
}
CString CCalcFormula::Item()
{
CString str = m_lpGetWord->getAWord();
if( str.IsEmpty()) RETURNEMPTY;
if(str[0] == ')' || str[0] == ',' ){
m_lpGetWord->SetPreword(str);
RETURNEMPTY;
}
if(str[0] == '('){
CString resstr = Formula();
str = m_lpGetWord->getAWord();
if( str.IsEmpty() || str[0] != ')') RETURNEMPTY;
return resstr;
}else if( (str[0] == '!') || (str.CompareNoCase("NOT")==0)) {
str = Item();
if(CRegularOpt::IsTrue(str))
return CString("0");
else
return CString("1");
}
CString optstr = str;
optstr.MakeLower();
// Specail opt for IN
int funcNo = GetFuncNo(LPCTSTR(optstr));
if( funcNo != -1)
str = Func(funcNo);
return str;
}
void CCalcFormula::SkipAOperand()
{
int nBracket(0);
CString str;
while(true){
str = m_lpGetWord->getAWord();
if( str.IsEmpty() ) return;
if(str[0] == '(') nBracket++;
if(str[0] == ')'){
nBracket--;
if(nBracket<0) {
m_lpGetWord->SetPreword(")");
return;
}
}
if(str[0] == ','){
if(nBracket==0) {
m_lpGetWord->SetPreword(",");
return;
}
}
}
}
CString CCalcFormula::Func(int nFuncNo)
{
CString str = m_lpGetWord->getAWord();
if( str.IsEmpty() || str[0] != '(') RETURNEMPTY;
int prmNo = 0;
CString sRes("");
if(m_sFunctionList[nFuncNo].nFuncID == FUNC_IF){
CString sCondition = Formula();
if(( sCondition.CompareNoCase("true")==0) ||
( CRegularOpt::IsNumber(sCondition) && (atoi(sCondition) != 0)) ){
str = m_lpGetWord->getAWord();
if( str.IsEmpty() || ( str[0] != ',') ) RETURNEMPTY;
sRes = Formula();
str = m_lpGetWord->getAWord();
if( str.IsEmpty() || ( str[0] != ',' && str[0] != ')') ) RETURNEMPTY;
if( str[0] == ')' ) return sRes;
SkipAOperand();
str = m_lpGetWord->getAWord();
if( str.IsEmpty() || (str[0] != ')') ) RETURNEMPTY;
return sRes;
}else {
str = m_lpGetWord->getAWord();
if( str.IsEmpty() || ( str[0] != ',') ) RETURNEMPTY;
SkipAOperand();
str = m_lpGetWord->getAWord();
if( str.IsEmpty() || ( str[0] != ',' ) ) RETURNEMPTY;
sRes = Formula();
str = m_lpGetWord->getAWord();
if( str.IsEmpty() || (str[0] != ')') ) RETURNEMPTY;
return sRes;
}
return sRes;
}
CStringList slOperand;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -