#include #include #include #include #include #include #include "Calculator.h" #ifdef __AFX_H__ #define new DEBUG_NEW #endif #pragma warning( disable: 4996 ) const int calc::m_max_num_oper=2; calc::calc() { m_oper = new double[m_max_num_oper]; m_current_oper=0; m_precision = 2; m_operator=undefined_oper; m_prev_state=undefined_state; m_state=init; } calc::~calc() { delete [] m_oper; } void calc::set_precision(unsigned int precision) { m_precision = precision; } unsigned int calc::get_precision() { return m_precision; } void calc::change_state(TCHAR newChar, LPCTSTR oldString, LPTSTR newString) { if ( (m_prev_state==undefined_state && m_state==init) || m_state == error ) _tcscpy(newString, CALC_STR_0); else _tcscpy(newString, oldString); m_prev_state=m_state; switch(m_prev_state) { case error: case init: switch(newChar) { case CALC_1: case CALC_2: case CALC_3: case CALC_4: case CALC_5: case CALC_6: case CALC_7: case CALC_8: case CALC_9: m_state=first_oper; addChar(newString,newChar); break; case CALC_P: m_state=first_oper; addChar(newString,newChar); break; case CALC_0: m_state=first_oper; break; case CALC_000: m_state=first_oper; break; case CALC_RESET: m_state=init; m_current_oper=0; _tcscpy(newString, CALC_STR_0); break; } break; case first_oper: switch(newChar) { case CALC_1: case CALC_2: case CALC_3: case CALC_4: case CALC_5: case CALC_6: case CALC_7: case CALC_8: case CALC_9: case CALC_0: case CALC_P: m_state=first_oper; addChar(newString,newChar); break; case CALC_000: m_state=first_oper; addString(newString,CALC_STR_000); break; case CALC_ADD: m_state=operation; m_operator=add; addOper(newString); break; case CALC_SUB: m_state=operation; m_operator=sub; addOper(newString); break; case CALC_MUL: m_state=operation; m_operator=mul; addOper(newString); break; case CALC_DIV: m_state=operation; m_operator=div; addOper(newString); break; case CALC_SQRT: m_state=result; m_operator=calc_sqrt; addOper(newString); calcResult(newString); break; case CALC_I: m_state=result; m_operator=inverse; addOper(newString); calcResult(newString); break; case CALC_RESET: m_state=init; m_current_oper=0; _tcscpy(newString,CALC_STR_0); break; case CALC_NEG: changeToNegative(newString); break; } break; case operation: switch(newChar) { case CALC_1: case CALC_2: case CALC_3: case CALC_4: case CALC_5: case CALC_6: case CALC_7: case CALC_8: case CALC_9: case CALC_0: case CALC_P: m_state=second_oper; _tcscpy(newString,CALC_STR_0); addChar(newString,newChar); break; case CALC_RESET: m_state=init; m_current_oper=0; _tcscpy(newString,CALC_STR_0); break; } break; case second_oper: switch(newChar) { case CALC_1: case CALC_2: case CALC_3: case CALC_4: case CALC_5: case CALC_6: case CALC_7: case CALC_8: case CALC_9: case CALC_0: case CALC_P: m_state=second_oper; addChar(newString,newChar); break; case CALC_000: m_state=second_oper; addString(newString,CALC_STR_000); break; case CALC_ADD: addOper(newString); calcResult(newString); m_state=operation; m_operator=add; addOper(newString); break; case CALC_SUB: addOper(newString); calcResult(newString); m_state=operation; m_operator=sub; addOper(newString); break; case CALC_MUL: addOper(newString); calcResult(newString); m_state=operation; m_operator=mul; addOper(newString); break; case CALC_DIV: addOper(newString); calcResult(newString); m_state=operation; m_operator=div; addOper(newString); break; case CALC_SQRT: addOper(newString); calcResult(newString); m_state=operation; m_operator=calc_sqrt; addOper(newString); break; case CALC_I: addOper(newString); calcResult(newString); m_state=operation; m_operator=inverse; addOper(newString); break; case CALC_TOT: m_state=result; addOper(newString); calcResult(newString); break; case CALC_PERC: { opertors oldOpertor = m_operator; double oldFirstOperator = m_oper[0]; m_operator = percent; addOper(newString); calcResult(newString); m_state = second_oper; m_oper[0] = oldFirstOperator; m_current_oper++; m_operator = oldOpertor; addOper(newString); } break; case CALC_RESET: m_state=init; m_current_oper=0; _tcscpy(newString,CALC_STR_0); break; case CALC_NEG: changeToNegative(newString); break; } break; case result: switch(newChar) { case CALC_1: case CALC_2: case CALC_3: case CALC_4: case CALC_5: case CALC_6: case CALC_7: case CALC_8: case CALC_9: case CALC_P: case CALC_0: m_state=first_oper; _tcscpy(newString,CALC_STR_0); addChar(newString,newChar); break; case CALC_ADD: m_state=operation; m_operator=add; addOper(newString); break; case CALC_SUB: m_state=operation; m_operator=sub; addOper(newString); break; case CALC_MUL: m_state=operation; m_operator=mul; addOper(newString); break; case CALC_DIV: m_state=operation; m_operator=div; addOper(newString); break; case CALC_SQRT: m_state=result; m_operator=calc_sqrt; addOper(newString); calcResult(newString); break; case CALC_I: m_state=result; m_operator=inverse; addOper(newString); calcResult(newString); break; case CALC_RESET: m_state=init; m_current_oper=0; _tcscpy(newString,CALC_STR_0); break; case CALC_NEG: changeToNegative(newString); break; } break; } } int calc::addChar(LPTSTR string, TCHAR c) { size_t len=_tcslen(string); if( len+1>MAX_LEN_RESULT ) goto exitOverflow; if( c==CALC_P && _tcschr(string,c)!=NULL ) goto exitSequenceError; if( len==1 && string[0]=='0' && c=='0' ) goto exitSequenceError; if( len==1 && string[0]=='0' && c!='0' && c!=CALC_P ) { len=0; string[0]='\0'; } string[len]=c; string[len+1]='\0'; return 1; exitSequenceError: return 0; exitOverflow: err(overflow, string); return 0; } int calc::addString(LPTSTR string, LPTSTR str2) { size_t len=_tcslen(string); size_t len2=_tcslen(str2); if( len+len2>MAX_LEN_RESULT ) goto exitOverflow; if( _tcscmp(str2,CALC_STR_P)==0 && _tcsstr(string,CALC_STR_P)!=NULL ) goto exitSequenceError; if( len==1 && string[0]=='0' && _tcscmp(str2,CALC_STR_0)==0 ) goto exitSequenceError; if( len==1 && string[0]=='0' && _tcscmp(str2,CALC_STR_000)==0 ) goto exitSequenceError; if( len==1 && string[0]=='0' && _tcscmp(str2,CALC_STR_0)!=0 && _tcscmp(str2,CALC_STR_P)!=0 ) string[0]='\0'; _tcscat(string,str2); return 1; exitSequenceError: return 0; exitOverflow: err(overflow, string); return 0; } int calc::addOper(LPTSTR string) { _ASSERT(m_current_oper<=m_max_num_oper); m_oper[m_current_oper]=_tstof(string); if( _tcscmp(string,CALC_STR_0)!=0 && m_oper[m_current_oper]==0) { err(overflow, string); return 0; } m_current_oper++; return 1; } int calc::calcResult(LPTSTR string) { double result=0; switch(m_operator) { case undefined_oper: goto exitSequenceError; case add: result=m_oper[0]+m_oper[1]; break; case sub: result=m_oper[0]-m_oper[1]; break; case div: if(m_oper[1]!=0) result=m_oper[0]/m_oper[1]; else goto exitDivisionByZero; break; case mul: result=m_oper[0]*m_oper[1]; break; case calc_sqrt: result = sqrt(m_oper[0]); break; case inverse: result = (1/m_oper[0]); break; case percent: result = (m_oper[1]*m_oper[0])/100; } TCHAR tmp_string[100]; _stprintf(tmp_string, L"%.*lf", (int)m_precision, (double)result); trimRigthDecimalZero(tmp_string); if(_tcslen(tmp_string)>MAX_LEN_RESULT) goto exitOverflow; else _tcscpy(string,tmp_string); m_current_oper=0; return 1; exitSequenceError: m_current_oper=0; return 0; exitOverflow: err(overflow, string); m_current_oper=0; return 0; exitDivisionByZero: err(division_by_zero, string); m_current_oper=0; return 0; } int calc::trimRigthDecimalZero(LPTSTR string) { if(_tcschr(string,CALC_P)==NULL) return 1; size_t i = _tcslen(string); i--; while(string[i]!=CALC_P && string[i]==CALC_0) { string[i]='\0'; i--; } if(string[i]==CALC_P) string[i]='\0'; return 1; } void calc::err(int errorCode, LPTSTR string) { switch(errorCode) { case overflow: if( string != NULL ) _tcscpy(string, ERR_STR_OVERFLOW); m_state = error; break; case division_by_zero: if( string != NULL ) _tcscpy(string, ERR_STR_DIVBYZERO); m_state = error; break; } } int calc::changeToNegative(LPTSTR string) { double d = _tstof(string); d = d * -1; _stprintf(string, L"%.*lf", (int)m_precision, (double)d); trimRigthDecimalZero(string); return 1; }