CExpression类

来源:互联网 发布:神泣sa数据库密码 编辑:程序博客网 时间:2024/05/22 02:02
表达式求值类CExpression头文件

 

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_)

 

 

  

表达式求值类CExpression源文件代码1

// 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;
}

 

 

查看文章
  

表达式求值类CExpression源文件代码2
2008-10-21 08:32

// 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();
}

原创粉丝点击