公式解析器原碼

来源:互联网 发布:java生成随机数零到一 编辑:程序博客网 时间:2024/05/03 03:23

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Formula.h"
/*  使用方法如下
    TFormula *Fml = new TFormula(EdtFormula->Text);
    int err = 1;
    err = Fml->Run();
    if (err > 0)
    {
        EdtAns->Text = Fml->Answer;
    }
    else
    {
        EdtAns->Text = "問題碼" + AnsiString(err) +" 嘿嘿,出錯了!";
    }
    delete Fml;
*/
//---------------------------------------------------------------------------
__fastcall TFormula::TFormula()
{
    Init();
}
//---------------------------------------------------------------------------
__fastcall TFormula::TFormula(AnsiString Formula)
{
    Init(Formula);
}
//---------------------------------------------------------------------------
__fastcall TFormula::~TFormula()
{
    PartLB->Clear();
    NumberLB->Clear();
    SignLB->Clear();
    delete PartLB;
    delete NumberLB;
    delete SignLB;
}
//---------------------------------------------------------------------------
void TFormula::Init()
{
    Init("");
}
//---------------------------------------------------------------------------
void TFormula::Init(AnsiString Formula)
{
    Oper[0] = '+';
    Oper[1] = '-';
    Oper[2] = '*';
    Oper[3] = '/';
    Oper[4] = '(';
    Oper[5] = ')';

    _InFormula = Formula;
    _OutAns = 0;
    iBracket = 0;

    PartLB = new TStringList;
    NumberLB = new TStringList;
    SignLB = new TStringList;
    PartLB->Clear();
    NumberLB->Clear();
    SignLB->Clear();
}
//---------------------------------------------------------------------------
double TFormula::GetAnswer()
{
    return _OutAns;
}
//---------------------------------------------------------------------------
void TFormula::SetFormula(AnsiString Formula)
{
    _InFormula = Formula;
}
//---------------------------------------------------------------------------
bool TFormula::InOper(AnsiString Oper)
{
    bool tag = false;
    for (int i=0;i<6;i++)
    {
        if (Oper == AnsiString(Oper[i]))
        {
            tag = true;
            break;
        }
    }
    return tag;
}
//---------------------------------------------------------------------------
bool TFormula::InOper(char ch)
{
    bool tag = false;
    for (int i=0;i<6;i++)
    {
        if (ch == Oper[i])
        {
            tag = true;
            break;
        }
    }
    return tag;
}
//---------------------------------------------------------------------------
int TFormula::CheckExp()
{
    int err = 1;
    int bracked=0;
    for (int i=0;i<PartLB->Count;i++)
    {
        AnsiString str = PartLB->Strings[i];
        if (str == "(")
            bracked++;
        if (str == ")")
            bracked--;
        if (bracked < 0)
        {
            err = -2;
            break;
        }
    }
    if (err>0 && bracked!=0)
        err = -1;
    return err;
}
//---------------------------------------------------------------------------
void TFormula::devide(AnsiString Formula)
{
    AnsiString str = Formula;

    AnsiString number="";

    PartLB->Clear();
    NumberLB->Clear();
    SignLB->Clear();

    //2*(1-3)+(2-10)*2=-22
    for (int i=1;i<=str.Length();i++)
    {
        char ch = str[i];
        if (InOper(ch))
        {
            if (!(number.Trim() == "" && ch == '-'))
            {
                PartLB->Add(AnsiString(ch));
                SignLB->Add(AnsiString(ch));
            }
            if (number.Trim() != "")
            {
                PartLB->Add(number);
                NumberLB->Add(number);
                number = "";
            }
            else if (ch == '-')
            {
                number = "-"+number;
            }
        }
        else
        {
            if (ch!=' ')
            {
                number += AnsiString(ch);
            }
        }
    }
    if (number.Trim() != "")
    {
        PartLB->Add(number);
        NumberLB->Add(number);
        number = "";
    }
}
//---------------------------------------------------------------------------
double TFormula::step(char operater,double x1, double x2)
{
    double result = 0;
    switch (operater)
    {
        case '+':
            result = x1 + x2;
            break;
        case '-':
            result = x1 - x2;
            break;
        case '*':
            result = x1 * x2;
            break;
        case '/':
            if (IsZero(x2))
                result = 0;
            else
                result = x1 / x2;
            break;
    }
    return result;
}
//---------------------------------------------------------------------------
double TFormula::Calculate()
{
    double x1, x2;
    AnsiString sign, nextsign;
    if (SignLB->Count > 0)
    {
        sign = SignLB->Strings[0];
        SignLB->Delete(0);
        if (SignLB->Count > 0)
            nextsign = SignLB->Strings[0];
        else
            nextsign = " ";
        switch (sign[1])
        {
            case '+':
            case '-':
                if  (NumberLB->Count>0)
                {
                    x1 = atof(NumberLB->Strings[0].c_str());
                    NumberLB->Delete(0);
                }
                else
                    x1 = 0;

                switch (nextsign[1])
                {
                    case '+':
                    case '-':
                    case ' ':
                    case ')':
                        if  (NumberLB->Count>0)
                        {
                            x2 = atof(NumberLB->Strings[0].c_str());
                            NumberLB->Delete(0);
                        }
                        else
                            x2 = 0;

                        NumberLB->Insert(0, AnsiString(step(sign[1], x1, x2)));
                        _OutAns = Calculate();
                        break;
                    case '*':
                    case '/':
                        _OutAns = step(sign[1], x1, Calculate());
                        break;
                    case '(':
                    // 加減法優先級最低,"("應保留
//                        if (SignLB->Count > 0)
//                            SignLB->Delete(0);
                        x2 = Calculate();
                        NumberLB->Insert(0, AnsiString(step(sign[1], x1, x2)));
                        _OutAns = Calculate();
                        break;
                }
                break;
            case '*':
            case '/':
                if  (NumberLB->Count>0)
                {
                    x1 = atof(NumberLB->Strings[0].c_str());
                    NumberLB->Delete(0);
                }
                else
                    x1 = 0;

                switch (nextsign[1])
                {
                    case '+':
                    case '-':
                    case '*':
                    case '/':
                    case ' ':
                    case ')':
                        if  (NumberLB->Count>0)
                        {
                            x2 = atof(NumberLB->Strings[0].c_str());
                            NumberLB->Delete(0);
                        }
                        else
                            x2 = 0;                               
                        break;
                    case '(':
                        if (SignLB->Count > 0)
                            SignLB->Delete(0);
                        x2 = Calculate();
                        break;
                }
                NumberLB->Insert(0, AnsiString(step(sign[1], x1, x2)));
                _OutAns = Calculate();
                break;
            case '(':
                iBracket++;
                x2 = Calculate();
                NumberLB->Insert(0, AnsiString(x2));
                _OutAns = Calculate();
                break;
            case ')':
                iBracket--;
               
                if  (NumberLB->Count>0)
                {
                    x2 = atof(NumberLB->Strings[0].c_str());
                    NumberLB->Delete(0);
                }
                else
                    x2 = 0;        

                _OutAns = x2;
                break;
        }
    }
    else
    {
        if (NumberLB->Count > 0)
        {
            x1 = atof(NumberLB->Strings[0].c_str());
            NumberLB->Delete(0);
            _OutAns = x1;
        }
    }
    return _OutAns;
}
//---------------------------------------------------------------------------
int TFormula::Run()
{
    int err=1;
    devide(_InFormula);
    err=CheckExp();
    if (err>0)
    {
        _OutAns = Calculate();
        return err;
    }
    else
    {
        return err;
    }
}
//---------------------------------------------------------------------------
#pragma package(smart_init)