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

// compute.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)

);

}

0 0