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

📄 expression.cpp

📁 PC网络游戏的编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            // 错误
            return 0;
        }
    }
    _CallParmCntStack.pop();

    // 把结果压入参数堆栈
    _ParmStack.push(var);

    // 取得表达式下一个位置的指针
    return GetNextChar(str+1);
}

// 计算逗号表达式
// 如果出现错误,返回0
// 否则返回剩余表达式的指针
char* CExpression::_DoComma(char *szExpr)
{
    char*   str=szExpr;
    int     cnt=0;
    while (1)
    {
        // 计算逗号表达式中的子表达式
        str=this->_DoExpr(str);

        // 如果出现错误
        if (str==0)
            return 0;

        // 如果逗号表达式计算结束
        if (str==(char*)-1)
            break;

        // 参数个数加1
        cnt ++;

        if (*str==',')
        {
            // 如果是下一个符号逗号,就说明逗号表达式还有其他的元素
            str ++;
        }else if((*str==')' && _CallStack.size()!=0) || (*str=='\0' && _CallStack.size()==0))
        {
            break;
        }else
        {
            // 表达式错误,左右括号不匹配
            this->SetError("syntax error : ')'");
            return 0;
        }
    }
    if (cnt==0 && _CallStack.size()==0)
    {
        // 空表达式错误
        this->SetError("expression is NULL");
        return 0;
    }else
    {
        _CallParmCntStack.push(cnt);
        return str;
    }
}

// 计算一个表达式
//    szExpr 是表达式的字符串
// 如果出现错误,返回0
// 否则返回剩余表达式的指针
char* CExpression::_DoExpr(char *szExpr)
{
    char*   str;
    double  n1, n2;
    int     opcnt=0;
    char    opr;

    if (szExpr==0)
    {
        // 空表达式错误
        this->SetError("expression is NULL");
        return 0;
    }

    str = szExpr;
    _OprStack.push(0);
    opcnt = 1;
    while(*str!=0 && *str!=',' && *str!=')' || _OprStack.top()!=0)
    {
        if (!this->inOperate(*str)) // 如果不是操作符
        {
            opcnt = 0;
            str = GetSymbol(str, _Symbol);
            if (str==0) return 0;
            if (*str=='(')
            {
                // 这是一个由参数的函数
                str = this->_DoCall(_Symbol, str+1);
                if (str)
                {
                    n1 = _ParmStack.top();
                    _NumStack.push(n1);
                    _ParmStack.pop();
                }else
                {
                    return 0;
                }
            }else
            {
                if (_Symbol[0]>='0' && _Symbol[0]<='9')
                {
                    // 只是一个数字
                    if (this->_GetNumber(_Symbol, &n1))
                    {
                        _NumStack.push(n1);
                    }else
                    {
                        return 0;
                    }
                }else
                {
                    // 这是一个没有参数的函数
                    if (this->DoCall(_Symbol, 0, 0, &n1))
                    {
                        _NumStack.push(n1);
                    }else
                    {
                        return 0;
                    }
                }
            }
        }else
        {
            if (opcnt)
            {
                if (*str=='+' || *str=='-')
                {
                    opr = _OprStack.top();
                    if (opr!=')')
                    {
                        opr = (*str=='+')?'#':'$';
                    }else
                    {
                        opr = *str;
                    }
                }else
                {
                    // 表达式格式错误,比如出现 a**b
                    this->SetError("illegal indirection");
                    return 0;
                }
            }else
            {
                opr = *str;
            }
            opcnt ++;
            switch(this->Precede(_OprStack.top(),opr)) // 取得优先及别
            {
            case EL:    // <
                _OprStack.push(opr);
                str = GetNextChar(str+1);
                break;

            case EE:    // =
                _OprStack.pop();
                str = GetNextChar(str+1);
                break;
            case EG:    // >
                opr = _OprStack.top();
                if (this->_IsSingle(opr))
                {
                    if (_NumStack.size()<1)
                    {
                        this->SetError("operate error");
                        return 0;
                    }
                    n1 = 0;
                }else
                {
                    if (_NumStack.size()<2)
                    {
                        this->SetError("operate error");
                        return 0;
                    }
                    n1 = _NumStack.top();
                    _NumStack.pop();
                }
                n2 = _NumStack.top();
                _NumStack.pop();
                _NumStack.push(this->Operate(n2, n1, opr));
                _OprStack.pop();
                opcnt=0;
                break;

            default:    // 异常
                this->SetError("operate error");
                return 0;
                break;
            }
        }
    }
    while(!_OprStack.empty())   _OprStack.pop();
    if (_NumStack.size())
    {
        _ParmStack.push(_NumStack.top());
        while(!_NumStack.empty())   _NumStack.pop();
        return str;
    }else
    {
        return (char*)-1;
    }
    return 0;
}

// 从字符串中取出一个数字
bool CExpression::_GetNumber(char* szExpr, double *var)
{
    if (szExpr==0)
    {
        // 空表达式错误
        this->SetError("expression is NULL");
        return false;
    }
    for (char *str=(char*)szExpr; *str; str++)
    {
        if ((*str<'0'||*str>'9')&&(*str!='.'))
        {
            // 数字格式错误
            this->SetError("bad suffix on number: '%s'", szExpr);
            return false;
        }
    }
    // 取出数字
    *var = atof(szExpr);
    return true;
}

// 虚函数,用户重定义这个函数来实现对自定义函数的解释
bool CExpression::DoCall(const char *szCallName, const int iParmCnt, const double *pParms, double *var)
{
    return DefDoCall(this, szCallName, iParmCnt, pParms, var);
}

// 定义一些基本的函数给用户使用
//    如果用户需要使用这些函数就要在
//    虚函数 DoCall 中调用这个函数
bool CExpression::DefDoCall(CExpression *pObj, const char *szCallName, const int iParmCnt, const double *pParms, double *var)
{
    int i;

    if (iParmCnt)   *var = pParms[iParmCnt-1];
    else            *var = 0;

    if (strcmp("log", szCallName)==0)
    {
        if (iParmCnt!=1)    goto err_pos_1;
        *var = log(pParms[0]);
    }else if (strcmp("abs", szCallName)==0)
    {
        if (iParmCnt!=1)    goto err_pos_1;
        *var = fabs(pParms[0]);
    }else if (strcmp("sqrt", szCallName)==0)
    {
        if (iParmCnt!=1)    goto err_pos_1;
        *var = sqrt(pParms[0]);
    }else if (strcmp("sin", szCallName)==0)
    {
        if (iParmCnt!=1)    goto err_pos_1;
        *var = sin(pParms[0]);
    }else if (strcmp("cos", szCallName)==0)
    {
        if (iParmCnt!=1)    goto err_pos_1;
        *var = cos(pParms[0]);
    }else if (strcmp("tan", szCallName)==0)
    {
        if (iParmCnt!=1)    goto err_pos_1;
        *var = tan(pParms[0]);
    }else if (strcmp("rand", szCallName)==0)
    {
        if (iParmCnt!=2)    goto err_pos_1;
        *var = (rand()%((int)(pParms[1]-pParms[0]))+pParms[0]);
    }else if (strcmp("min", szCallName)==0)
    {
        *var = pParms[0];
        for (i=1; i<iParmCnt; i++)
        {
            if (pParms[i]<*var)   *var = pParms[i];
        }
    }else if (strcmp("max", szCallName)==0)
    {
        *var = pParms[0];
        for (i=1; i<iParmCnt; i++)
        {
            if (pParms[i]>*var)   *var = pParms[i];
        }
    }else if (strcmp("sum", szCallName)==0)
    {
        *var = 0;
        for (i=0; i<iParmCnt; i++)
        {
            *var += pParms[i];
        }
    }else if (strcmp("ave", szCallName)==0)
    {
        *var = 0;
        for (i=0; i<iParmCnt; i++)
        {
            *var += pParms[i];
        }
        *var /= iParmCnt;
    }else
    {
        goto err_pos_2;
    }

    return true;
err_pos_1:
    if (pObj)
    {
        // 函数参数个数错误
        pObj->SetError("'%s' : function does not take %d parameters", szCallName, iParmCnt);
    }
    return false;
err_pos_2:
    if (pObj)
    {
        // 没有定义的标志符
        pObj->SetError("'%s' : undeclared identifier", szCallName);
    }
    return false;
}

⌨️ 快捷键说明

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