⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 calcformule.cpp

📁 我的简易编译器终于在花了近20个工作日后完成了。按照设计是做成一个FormulaEx.dll
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 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 + -