|
一个简单的识别函数的计算器(1)
可以支持简单的函数计算:如(+、-、*、/、^、sin, cos)等等。 用正则表达式写的,核心就如下了: CSdn.net/Emoticons/hitwall.gif">
// compute.h // #ifndef HEADFILE_COMPUTE_H_HXML:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> #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) ); }
|