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

📄 expression.cpp

📁 PC网络游戏的编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 嵌入式表达式代码
// 作者: Janhail Luo
// 最后整理: 2003-03-03
//////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <math.h>
#include <stdarg.h>

#include "Expression.h"

class   CSafeArray
{
public:
    CSafeArray(int num){point = new double[num];}
    ~CSafeArray(){delete[] point;}
    double* GetPoint(){return point;}
private:
    double   *point;
};

#define EG     1  // GREATE
#define EL     2  // LESS
#define EE     3  // EQUALS
#define EU     0  // UNKNOW

// 操作符列表
// '#' 表示单目 '+', '$' 表示单目 '-'
char CExpression::_Operate[EXPR_MAX_OPERATE]={
          '+','-','*','/', '#', '$', '>', '<', '=', '!', '&', '|', '\0'};
// 操作符优先级别的定义
// EG >,  El <,  EE =,  EU Unknow
int CExpression::_Precede[EXPR_MAX_OPERATE][EXPR_MAX_OPERATE]={
          EG,EG,EL,EL,EL,EL,EG,EG,EG,EL,EG,EG,EG,
          EG,EG,EL,EL,EL,EL,EG,EG,EG,EL,EG,EG,EG,
          EG,EG,EG,EG,EL,EL,EG,EG,EG,EL,EG,EG,EG,
          EG,EG,EG,EG,EL,EL,EG,EG,EG,EL,EG,EG,EG,
          EG,EG,EG,EG,EG,EG,EG,EG,EG,EL,EG,EG,EG,
          EG,EG,EG,EG,EG,EG,EG,EG,EG,EL,EG,EG,EG,
          EL,EL,EL,EL,EL,EL,EG,EG,EG,EL,EG,EG,EG,
          EL,EL,EL,EL,EL,EL,EG,EG,EG,EL,EG,EG,EG,
          EL,EL,EL,EL,EL,EL,EL,EL,EG,EL,EG,EG,EG,
          EG,EG,EG,EG,EG,EG,EG,EG,EG,EG,EG,EG,EG,
          EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EG,EG,EG,
          EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EG,EG,EG,
          EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EE};

// 类构造函数
CExpression::CExpression()
{
}

// 类析构函数
CExpression::~CExpression()
{
    // 清除数据
    this->_Clear();
}

// 清除所有数据
void CExpression::_Clear()
{
    while(!_NumStack.empty())           _NumStack.pop();
    while(!_OprStack.empty())           _OprStack.pop();
    while(!_ParmStack.empty())          _ParmStack.pop();
    while(!_CallStack.empty())          _CallStack.pop();
    while(!_CallParmCntStack.empty())   _CallParmCntStack.pop();
    while(!_SceneStack.empty())         _SceneStack.pop();
    while(!_NumTotalStack.empty())      _NumTotalStack.pop();
    while(!_OprTotalStack.empty())      _OprTotalStack.pop();
}

// 计算表达式
// const char *szExpStr: 表达式的字符串
// double *var         : 用于保存表达式的计算结果的值
// 返回:
//      true  表示表达式计算成功,值保存到*var中
//      false 表示表达式计算失败,用GetError可以取得失败的原因
bool CExpression::Computer(const char *szExpStr, double *var)
{
    // 开始计算
    _bError = false;

    // 计算逗号表达式,可以认为一个表达式是由逗号表达式组成
    if (this->_DoComma((char*)szExpStr))
    {
        // 从参数栈中取出栈顶的数值为表达式的计算结果
        *var = _ParmStack.top();
        this->_Clear();
        return true;
    }else
    {
        this->_Clear();
        return false;
    }
}

// 设置错误信息
void CExpression::SetError(const char* errMsg, ...)
{
    _bError = true;
	va_list list;
	va_start( list , errMsg );
	vsprintf(_szErrorLog , errMsg , list);
	va_end( list );
}

// 取得错误信息
const char* CExpression::GetError(void)
{
    if (_bError==false)
    {
        this->SetError("No error");
    }
    return _szErrorLog;
}

// 检查符号 o 是否是操作符
//   如果是操作符就返回操作符的编号
//   否则返回 0
int CExpression::inOperate(char o)
{
    int i;
    if ( o==')' || o==',')
        return EXPR_MAX_OPERATE;

    for (i=0; i<EXPR_MAX_OPERATE; i++)
    {
        if (o==_Operate[i])
        {
            break;
        }
    }

    if (i==EXPR_MAX_OPERATE)
    {
        i = 0;
    }else
    {
        i++;
    }
    return i;
}

// 取得符号o1对符号o2的优先级别
int  CExpression::Precede(char o1, char o2)
{
    int i, j;
    i = this->inOperate(o1);
    j = this->inOperate(o2);
    if (i==0 || j==0)
    {
        return 0;
    }
    return _Precede[i-1][j-1];
}

// 检查操作符 opr 是否是单目操作符
//   是返回 true
//   不是返回 false
bool CExpression::_IsSingle(char opr)
{
    if (opr=='#' || opr=='$' || opr=='!')
        return true;
    return false;
}

// 计算一个操作
double CExpression::Operate(double n1, double n2, char o)
{
    double  ret = 0;
    switch(o)
    {
    case '+':   ret = n1+n2;break;
    case '-':   ret = n1-n2;break;
    case '*':   ret = n1*n2;break;
    case '/':   ret = n1/n2;break;
    case '#':   ret = +n1;break;
    case '$':   ret = -n1;break;
    case '>':   ret = (n1>n2)?1:0;break;
    case '<':   ret = (n1<n2)?1:0;break;
    case '=':   ret = ((int)n1==(int)n2)?1:0;break;
    case '!':   ret = ((int)n1)?0:1;break;
    case '&':   ret = ((int)n1 && (int)n2);break;
    case '|':   ret = ((int)n1 || (int)n2);break;
    default:    ret = 0.0f;break;
    }
    return ret;
}

// 检查一个字符是否是字母、数字、下划线或点
//   如果是返回 true
//   否则返回 false
bool CExpression::inRange(char c)
{
    if ((c>='a'&&c<='z')||(c>='A'&&c<='Z')||(c>='0'&&c<='9')||(c=='_')||(c=='.'))
    {
        return true;
    }else
    {
        return false;
    }
}

// 保存现场到堆栈中
void  CExpression::SaveScene()
{
    // 保存操作数堆栈
    _SceneStack.push(_NumStack.size()); // 操作数个数
    // 把当前操作数堆栈内容转移到存盘堆栈中
    while (!_NumStack.empty())
    {
        _NumTotalStack.push(_NumStack.top());
        _NumStack.pop();
    }

    // 保存操作符堆栈
    _SceneStack.push(_OprStack.size()); // 操作符个数
    // 把当前操作符堆栈内容转移到存盘堆栈中
    while (!_OprStack.empty())
    {
        _OprTotalStack.push(_OprStack.top());
        _OprStack.pop();
    }

    // 保存当前的函数名
    _CallStack.push(_Symbol);
}

// 从堆栈中载入现场
void  CExpression::LoadScene()
{
    int i;

    // 把当前堆栈的内容清空
    while(!_NumStack.empty())   _NumStack.pop();
    while(!_OprStack.empty())   _OprStack.pop();

    // 取出操作符堆栈
    i = _SceneStack.top();  // 操作符个数
    while (i)
    {
        // 把操作符转移到当前计算堆栈
        _OprStack.push(_OprTotalStack.top());
        _OprTotalStack.pop();
        i--;
    }
    _SceneStack.pop();

    // 取出操作数堆栈
    i = _SceneStack.top();  // 操作数个数
    while (i)
    {
        // 把操作数转移到当前计算堆栈
        _NumStack.push(_NumTotalStack.top());
        _NumTotalStack.pop();
        i--;
    }
    _SceneStack.pop();

    // 取出函数名
    strcpy(_Symbol, _CallStack.top().c_str());
    _CallStack.pop();
}

// 求函数的值
//   当遇到一个表达式的函数时调用这个函数
//   szCallName 是表达式函数的名字
//   szExpr 是这个表达式函数后面的字符串,是表达式的参数
// 如果出现错误,返回0
// 否则返回剩余表达式的指针
char* CExpression::_DoCall(char *szCallName, char *szExpr)
{
    char*   str=szExpr;
    int     i;
    double  var;

    // 保存现场
    this->SaveScene();

    // 计算逗号表达式
    str=this->_DoComma(szExpr);

    // 如果出现错误,则返回0
    if (str==0)
        return 0;

    // 载入现场
    this->LoadScene();

    if (_Symbol[0]=='\0')  // 逗号表达式
    {
        // 如果参数堆栈有数据
        if (_CallParmCntStack.top())
        {
            // 栈顶数值为返回值
            var = _ParmStack.top();

            // 清除堆栈里面剩余的数据
            for (i=_CallParmCntStack.top(); i>0; i--)
            {
                _ParmStack.pop();
            }
        }else
        {
            // 空表达式错误
            this->SetError("expression is NULL");
            return 0;
        }
    }else   // 函数调用
    {
        // 参数个数
        int iParmCnt = _CallParmCntStack.top();

        // 定义一个用于保存参数的数组
        CSafeArray    array(iParmCnt);
        double *parm = array.GetPoint();

        // 取得所有参数的数值并保存到数组中
        // 同时把参数堆栈的数据清除
        for (i=iParmCnt-1; i>=0; i--)
        {
            parm[i] = _ParmStack.top();
            _ParmStack.pop();
        }

        // 调用虚函数 DoCall 由用户解释函数
        if (this->DoCall(_Symbol, iParmCnt, parm, &var)==false)
        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -