CExpression类
来源:互联网 发布:神泣sa数据库密码 编辑:程序博客网 时间:2024/05/22 02:02
Expression.h
// Expression.h: interface for the CExpression class.
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_EXPRESSION_H__4BA3FCD7_ACB9_473B_8757_31B01A389850__INCLUDED_)
#define AFX_EXPRESSION_H__4BA3FCD7_ACB9_473B_8757_31B01A389850__INCLUDED_
#include <vector>
using namespace std;
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//*/
enum ExpAtomType {
atomVal,atomOpr
};
struct ExpAtom
{
int flag; // 标记是运算符或是操作数
int reserved;
union
{
double value;
char opr[8];
} atom;
__stdcall ExpAtom();
};
class CExpression
{
private:
char *m_szExpr;
const char *m_szOpr;
const char *m_szInvalid;
bool m_IsDeleted;
bool m_IsTranslated;
bool m_IsSuffix;
bool m_IsCalc;
string m_szTranslated;
string m_szSuffix;
double m_dblResult;
vector<ExpAtom> m_arrAtom;
vector<ExpAtom> m_arrSuffix;
bool __stdcall IsOperator(char c);
bool __stdcall IsInvalidChar(char c);
static void __stdcall AtomsToString(vector<ExpAtom> &arrAtom,string& str);
static string ExpAtomToString(const ExpAtom& ea);
int __stdcall CompareOpr(char op1,char op2);
public:
__stdcall CExpression();
__stdcall ~CExpression();
void __stdcall Free(); // 释放重置
void __stdcall SetExpression(const char *Expr);
void __stdcall DeleteInvalidChars();
void __stdcall TranslateToAtom(); // 翻译表达式到Atom
void __stdcall AtomToSuffix(); // Atom到后缀式
const char* __stdcall GetExpression();
const char* __stdcall GetSuffixExpr();
double __stdcall Calculate();
static double __stdcall CalcExpression(const char *Expr);
};
#endif // !defined(AFX_EXPRESSION_H__4BA3FCD7_ACB9_473B_8757_31B01A389850__INCLUDED_)
// Expression.cpp 第一部分
// Expression.cpp: implementation of the CExpression class.
//
//////////////////////////////////////////////////////////////////////
#include <sstream>
#include <string>
#include <stack>
using namespace std;
#include "Expression.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
__stdcall ExpAtom::ExpAtom() {
memset(this,0,sizeof(ExpAtom));
}
__stdcall CExpression::CExpression()
{
m_szExpr=NULL;
m_szOpr="+-*/{}[]()";
m_szInvalid=" /r/n/t";
m_IsDeleted=false;
m_IsTranslated=false;
m_IsSuffix=false;
m_IsCalc=false;
m_szTranslated="";
m_szSuffix="";
}
__stdcall CExpression::~CExpression() { Free(); }
void __stdcall CExpression::Free()
{
if(m_szExpr) delete []m_szExpr;
m_szExpr=NULL;
m_IsDeleted=false;
m_IsTranslated=false;
m_IsSuffix=false;
m_IsCalc=false;
m_szTranslated="";
m_szSuffix="";
}
const char* __stdcall CExpression::GetExpression()
{
if(!m_IsTranslated) TranslateToAtom();
return m_szTranslated.c_str();
}
const char* __stdcall CExpression::GetSuffixExpr()
{
if(!m_IsSuffix) AtomToSuffix();
return m_szSuffix.c_str();
}
void __stdcall CExpression::SetExpression(const char *Expr)
{
Free();
m_szExpr=strdup(Expr);
}
void __stdcall CExpression::TranslateToAtom()
{
if(!m_szExpr) return;
if(m_IsTranslated) return;
const char *exp=m_szExpr;
bool isSaveNum=false; // 是否已经保存了数字
int i=0;
if(!m_IsDeleted) DeleteInvalidChars(); // 删除一些无效的字符
m_arrAtom.clear(); // 先清空Atom数组
while(*exp)
{
ExpAtom ea;
if(IsOperator(*exp))
{
if(*exp=='-') // 解决负数的情况
{
if(i!=0)
{
// 当是'-'号,且不在第一个时,如果前一个是操作符且不是')',后一个是数字
// 则这是个负数.
if(IsOperator(*(exp-1)) && *(exp-1)!=')' && !IsOperator(*(exp+1)))
{
ea.flag=atomVal;
ea.atom.value=atof(exp);
m_arrAtom.push_back(ea);
isSaveNum=true;
goto LBL1;
}
}
else
{
// 当是'-'号,且在第一个时,如果后一个是数字
// 则这是个负数.
if(!IsOperator(*(exp+1)))
{
ea.flag=atomVal;
ea.atom.value=atof(exp);
m_arrAtom.push_back(ea);
isSaveNum=true;
goto LBL1;
}
}
}
isSaveNum=false;
ea.flag=atomOpr;
*ea.atom.opr=*exp;
m_arrAtom.push_back(ea);
LBL1:;
}
else
{
if(!isSaveNum)
{
ea.flag=atomVal;
ea.atom.value=atof(exp);
m_arrAtom.push_back(ea);
isSaveNum=true;
}
}
i++;
exp++;
}
AtomsToString(m_arrAtom,m_szTranslated);
m_IsTranslated=true;
}
void __stdcall CExpression::AtomToSuffix()
{
if(m_IsSuffix) return;
if(!m_IsTranslated) TranslateToAtom();
m_arrSuffix.clear(); // 置空
stack<ExpAtom> skop; // 操作符栈
ExpAtom ea;
ea.flag=atomOpr;
*ea.atom.opr='#';
skop.push(ea); // 向栈压入表达式开始符 #
m_arrAtom.push_back(ea); // 向表达式加结束符 #
vector<ExpAtom>::iterator it=m_arrAtom.begin();
for(;it<m_arrAtom.end();it++)
{
if(it->flag==atomVal)
{
m_arrSuffix.push_back(*it);
}
else
{
char op1=*skop.top().atom.opr; // 栈顶操作符
char op2=*it->atom.opr; // 当前操作符
switch(op2)
{
case ')':
case '#':
{
while(CompareOpr(*skop.top().atom.opr,*it->atom.opr))
{
m_arrSuffix.push_back(skop.top());
skop.pop();
}
skop.pop();
}
break;
default:
{
int cmp=CompareOpr(op1,op2);
if(cmp==1)
{
while(CompareOpr(*skop.top().atom.opr,*it->atom.opr)==1)
{
m_arrSuffix.push_back(skop.top());
skop.pop();
}
skop.push(*it);
}
else if(cmp==-1) // op1<op2
{
skop.push(*it);
}
}
}
}
}
m_arrAtom.pop_back();
AtomsToString(m_arrSuffix,m_szSuffix);
m_IsSuffix=true;
}
void __stdcall CExpression::DeleteInvalidChars()
{
if(m_IsDeleted) return;
string exp(m_szExpr);
string::iterator ithead=exp.begin();
string::iterator ittail=exp.end()-1;
while(ithead<=ittail)
{
if(IsInvalidChar(*ithead))
{
exp.erase(ithead);
}
if(IsInvalidChar(*ittail))
{
exp.erase(ittail);
}
ithead++;
ittail--;
}
if(m_szExpr) delete []m_szExpr;
m_szExpr=strdup(exp.c_str());
m_IsDeleted=true;
}
bool __stdcall CExpression::IsOperator(char c)
{
const char *head=m_szOpr;
const char *tail=m_szOpr+strlen(m_szOpr)-1;
while(head<=tail)
{
if(c==*head) return true;
if(c==*tail) return true;
head++;
tail--;
}
return false;
}
bool __stdcall CExpression::IsInvalidChar(char c)
{
const char *head=m_szInvalid;
const char *tail=m_szInvalid+strlen(m_szInvalid)-1;
while(head<=tail)
{
if(c==*head) return true;
if(c==*tail) return true;
head++;
tail--;
}
return false;
}
// Expression.cpp 第二部分
int __stdcall CExpression::CompareOpr(char op1,char op2)
{
switch(op1)
{
case '+':
{ switch(op2)
{
case '+':
return 1; // >
case '-':
return 1; // >
case '*':
return -1; // >
case '/':
return -1; // >
case '(':
return -1; // >
case ')':
return 1; // >
case '#':
return 1; // >
}
return 2;
}
break;
case '-':
{
switch(op2)
{
case '+':
return 1; // >
case '-':
return 1; // >
case '*':
return -1; // >
case '/':
return -1; // >
case '(':
return -1; // >
case ')':
return 1; // >
case '#':
return 1; // >
}
return 2;
}
break;
case '*':
{
switch(op2)
{
case '+':
return 1; // >
case '-':
return 1; // >
case '*':
return 1; // >
case '/':
return 1; // >
case '(':
return -1; // >
case ')':
return 1; // >
case '#':
return 1; // >
}
return 2;
}
break;
case '/':
{
switch(op2)
{
case '+':
return 1; // >
case '-':
return 1; // >
case '*':
return 1; // >
case '/':
return 1; // >
case '(':
return -1; // >
case ')':
return 1; // >
case '#':
return 1; // >
}
return 2;
}
break;
case '(':
{
switch(op2)
{
case '+':
return -1; // >
case '-':
return -1; // >
case '*':
return -1; // >
case '/':
return -1; // >
case '(':
return -1; // >
case ')':
return 0; // >
case '#':
return 2; // >
}
return 2;
}
break;
case ')':
{
switch(op2)
{
case '+':
return 1; // >
case '-':
return 1; // >
case '*':
return 1; // >
case '/':
return 1; // >
case '(':
return 2; // >
case ')':
return 1; // >
case '#':
return 1; // >
}
return 2;
}
break;
case '#':
{
switch(op2)
{
case '+':
return -1; // >
case '-':
return -1; // >
case '*':
return -1; // >
case '/':
return -1; // >
case '(':
return -1; // >
case ')':
return 2; // >
case '#':
return 0; // >
}
return 2;
}
break;
}
return 2;
}
string CExpression::ExpAtomToString(const ExpAtom& ea)
{
ostringstream sout;
if(ea.flag==atomVal)
{
sout<<ea.atom.value<<' ';
}
else
{
sout<<ea.atom.opr<<' ';
}
return sout.str();
}
void __stdcall CExpression::AtomsToString(vector<ExpAtom> &arrAtom,string& str)
{
vector<ExpAtom>::iterator it=arrAtom.begin();
for(;it<arrAtom.end();it++)
{
str+=ExpAtomToString(*it);
}
if(str[str.length()-1]==' ')
str.erase(str.length()-1,1);
}
double calc(double v1,char op,double v2)
{
switch(op)
{
case '+':
return v1+v2;
case '-':
return v1-v2;
case '*':
return v1*v2;
case '/':
return v1/v2;
}
return 0;
}
double __stdcall CExpression::Calculate()
{
if(m_IsCalc) return m_dblResult;
if(!m_IsTranslated) TranslateToAtom();
if(!m_IsSuffix) AtomToSuffix();
stack<double> result;
vector<ExpAtom>::iterator it=m_arrSuffix.begin();
for(;it<m_arrSuffix.end();it++)
{
if(it->flag==atomVal)
{
result.push(it->atom.value);
}
else
{
double v1,v2;
v2=result.top();
result.pop();
v1=result.top();
result.pop();
result.push(calc(v1,*it->atom.opr,v2));
}
}
m_IsCalc=true;
if(!result.empty()) return m_dblResult=result.top();
return m_dblResult=0;
}
double __stdcall CExpression::CalcExpression(const char *Expr)
{
CExpression exp;
exp.SetExpression(Expr);
return exp.Calculate();
}
- CExpression类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 类
- 产品需求分析--原则一
- ThreadLocal 介绍
- CListCtrl基本用法
- 产品需求分析--原则二
- C++中常用的运算符及微软自定义类型
- CExpression类
- php字符串处理函数大全(学习)
- ADO.NET中的五个主要对象
- JavaMail发送和接收邮件
- ibatis2.3调用oracle function
- How to temporarily suppress infolog messages in Dynamics Ax (deux)
- JAAS
- MFC对话框接受文件拖放的方法
- velocity+spring mvc+spring ioc+ibatis初试感觉(与struts+spring+hibernate比较)