一个简单的识别函数的计算器

类别:编程语言 点击:0 评论:0 推荐:

可以支持简单的函数计算:如(+、-、*、/、^、sin, cos)等等。
用正则表达式写的,核心就如下了:

// compute.h

//

#ifndef HEADFILE_COMPUTE_H_H

#define HEADFILE_COMPUTE_H_H

 

#pragma once

 

class CCompute

{

public:

    CCompute(FILE* fp);

    ~CCompute();

    void Compute();

 

private:

    void match(char expectedToken);

    void error();

    void delSpace();

 

    const double term();

    const double exp();

    const double factor();

    const double power();

    const double KeyWordOperator();

    const double KeyExp();

 

    const CString GetOperatorName();

 

    bool IsAccepted(char);

    bool IsLegal(char) const;

 

public:

    bool m_bError;

    CString m_cResult;

    CString m_strExpress;

 

private:

    FILE* m_fp;

    char m_cToken;

};

 

#endif

 

// compute.h

//

#include "StdAfx.h"

#include "Compute.h"

 

/** 表达式

  * <exp> -> <term> {<addop> <term>}

  * <addop> -> + | -

  * <term> -> <factor> {<mulop> <factor>}

  * <mulop> -> * | /

  * <factor> -> <power> {<powop> <power>}

  * <powop> -> ^

  * <power> -> <KeyExp> | number

  * <KeyExp> -> (exp) | KeyWordOper(exp)

  **/

 

CCompute::CCompute(FILE* fp)

{

    m_fp = fp;

    m_cToken = ' ';

    m_cResult = "";

    m_bError = false;

    m_strExpress = "";

}

 

CCompute::~CCompute()

{

    m_fp = NULL;

}

 

void CCompute::error()

{

    m_bError = true;

}

 

void CCompute::match(char expectedToken)

{

    if(m_cToken == expectedToken)

    {

        m_cToken = getc(m_fp);

        m_strExpress += expectedToken;

    }

    else

        error();

}

 

const double CCompute::exp()

{

    double temp;

    delSpace();

    temp = term();

    delSpace();

    while((m_cToken == '+') || (m_cToken == '-'))

    {

        switch(m_cToken)

        {

        case '+' :

            match('+');

            delSpace();

            temp += term();

            delSpace();

            break;

        case '-':

            match('-');

            delSpace();

            temp -= term();

            delSpace();

            break;

        default:

            break;

        }

    }

    return temp;

}

 

const double CCompute::term()

{

    double t;

    delSpace();

    double temp = factor();

    delSpace();

    while((m_cToken == '*') || (m_cToken == '/'))

    {

        switch(m_cToken)

        {

        case '*':

            match('*');

            delSpace();

            temp *= factor();

            delSpace();

            break;

        case '/':

            match('/');

            delSpace();

            t = factor();

            if(t != 0.0)

                temp /= t;

            else

                error();

 

            delSpace();

            break;

        default:

            delSpace();

            break;

        }

    }

    return temp;

}

 

const double CCompute::factor()

{

    delSpace();

    double temp = power();

    delSpace();

    while(m_cToken == '^')

    {

        match('^');

        delSpace();

        temp = pow(temp, power());

        delSpace();

    }

    return temp;

}

 

void CCompute::delSpace()

{

    if(' ' == m_cToken)

    {

        m_cToken = getc(m_fp);

        delSpace();

    }

}

 

const double CCompute::power()

{

    double temp = 0.0;

    delSpace();

   

    if(isdigit(m_cToken) || (m_cToken == '.')

        || (m_cToken == '-') || (m_cToken == '+'))

    {

        CString strTemp;

        if('-' == m_cToken)

        {

            fscanf(m_fp, "%lf", &temp);

            strTemp.Format("%0.10lf", temp);

            temp *= -1;

            m_strExpress += m_cToken + CutTail(strTemp);

           

            m_cToken = getc(m_fp);

            if(IsAccepted(m_cToken))

                delSpace();

            else

                error();

        }

        else if('+' == m_cToken)

        {

            fscanf(m_fp, "%lf", &temp);

 

            strTemp.Format("%0.10lf", temp);

            m_strExpress += m_cToken + CutTail(strTemp);

 

            m_cToken = getc(m_fp);

            if(IsAccepted(m_cToken))

                delSpace();

            else

                error();

        }

        else

        {

            ungetc(m_cToken, m_fp);

            fscanf(m_fp, "%lf", &temp);

           

            strTemp.Format("%0.10lf", temp);

            m_strExpress += CutTail(strTemp);

           

            m_cToken = getc(m_fp);

            if(IsAccepted(m_cToken))

                delSpace();

            else

                error();

        }

    }

    else

        temp = KeyExp();

   

    return temp;

}

 

void CCompute::Compute()

{

    m_cToken = getc(m_fp);

    double result = exp();

 

    if(false == m_bError)

    {

        if(m_cToken == '\n' || m_cToken == EOF)

            m_cResult.Format("%0.10lf", result);

    }

    else

        m_cResult = "Error";

    m_cResult = (m_cResult == "" ? "Error" : m_cResult);

}

 

const CString CCompute::GetOperatorName()

{

    CString _strName;

    while(IsLegal(m_cToken))

    {

        _strName += m_cToken;

        m_cToken = getc(m_fp);

    }

    _strName.MakeLower();

    m_strExpress += _strName;

 

    return _strName;

}

 

bool CCompute::IsLegal(char c) const

{

    if ((c > 0X60 && c < 0X7B)

        || (c > 0X40 && c < 0X5B)

        || (c > 0X2F && c < 0X3A)

        || (c == 0X25))

        return true;

    else

        return false;

}

 

const double CCompute::KeyWordOperator()

{

    delSpace();

    CString _strOpName = GetOperatorName();

    delSpace();

    match('(');

    delSpace();

//

    double temp = 0.0;

    double _nExp = exp();

    if(_strOpName)

    {

        if(_strOpName == "sqrt")

            temp = sqrt(_nExp);

 

        else if((_strOpName == "abs")

            || (_strOpName  == "fabs"))

            temp = fabs(_nExp);

 

        else if(_strOpName  == "sin")

            temp = sin(_nExp);

 

        else if(_strOpName  == "cos")

            temp = cos(_nExp);

 

        else if((_strOpName == "tan")

            || (_strOpName  == "tg"))

            temp = tan(_nExp);

 

        else if((_strOpName == "asin")

            || (_strOpName  == "arsin")

            || (_strOpName  == "arcsin"))

            temp = asin(_nExp);

 

        else if((_strOpName == "acos")

            || (_strOpName  == "arcos")

            || (_strOpName  == "arccos"))

            temp = acos(_nExp);

 

        else if((_strOpName == "atan")

            || (_strOpName  == "artan")

            || (_strOpName  == "arctan"))

            temp = atan(_nExp);

 

        else if((_strOpName == "lg")

            || (_strOpName  == "lge"))

            temp = log(_nExp);

 

        else if((_strOpName == "log")

            || (_strOpName  == "log10"))

            temp = log10(_nExp);

 

        else if((_strOpName == "ctan")

            || (_strOpName  == "ctg"))

            temp = 1.0 / tan(_nExp);

 

        else

            error();

    }

//

    match(')');

    delSpace();

    return temp;

}

 

const double CCompute::KeyExp()

{

    double temp = 0.0;

    delSpace();

    if(m_cToken == '(')

    {

        match('(');

        delSpace();

        temp = exp();

        delSpace();

        match(')');

    }

    else if(IsLegal(m_cToken))

        temp = KeyWordOperator();

    else

        error();

 

    return temp;

}

 

 

bool CCompute::IsAccepted(char c)

{

    return

        (

        (' ' == c) || ('+' == c) ||

        ('-' == c) || ('*' == c) ||

        ('/' == c) || ('^' == c) ||

        ('(' == c) || (')' == c) ||

        (EOF == c) || ('\n' == c)

        );

}


 

本文地址:http://com.8s8s.com/it/it26178.htm