//////////////////////////////////////////////////////////////////////////////// // // calc.C : rpn calculator on the command line // // use: // calc 2 3.14 mul 5 div // // F. Gygi, 1994. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include using namespace std; #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 // Elements of the stack class StackElement { public: double value; StackElement *next; }; // the stack is global StackElement *stack = NULL; int precision = 6; void st_under(); void range(); void fix(); void add(); void sub(); void mul(); void div(); void power(); void deg(); void rad(); void si(); void cs(); void tn(); void asi(); void acs(); void atn(); void ex(); void lg(); void ln(); void sq(); void sqr(); void inv(); void ab(); void chs(); void exc(); int main(int argc, char **argv ) { if ( argc == 1 ) { cout << " calc: RPN calculator on the command line" << endl; cout << " use: calc arg1 arg2 op1 ... argn opn" << endl; cout << " where op's are : " << endl; cout << " + - add sub mul div ^ sin cos tan asin acos atan" << endl << " exp log ln sqr sqrt abs inv dup pop exc pi fix" << endl; exit ( EXIT_SUCCESS ); } while (*++argv) { if ( !strcmp( *argv, "+" ) ) add(); else if ( !strcmp( *argv, "fix" ) ) fix(); else if ( !strcmp( *argv, "add" ) ) add(); else if ( !strcmp( *argv, "-" ) ) sub(); else if ( !strcmp( *argv, "sub" ) ) sub(); else if ( !strcmp( *argv, "mul" ) ) mul(); else if ( !strcmp( *argv, "div" ) ) div(); else if ( !strcmp( *argv, "^" ) ) power(); else if ( !strcmp( *argv, "deg" ) ) deg(); else if ( !strcmp( *argv, "rad" ) ) rad(); else if ( !strcmp( *argv, "sin" ) ) si(); else if ( !strcmp( *argv, "cos" ) ) cs(); else if ( !strcmp( *argv, "tan" ) ) tn(); else if ( !strcmp( *argv, "asin" ) ) asi(); else if ( !strcmp( *argv, "acos" ) ) acs(); else if ( !strcmp( *argv, "atan" ) ) atn(); else if ( !strcmp( *argv, "exp" ) ) ex(); else if ( !strcmp( *argv, "log" ) ) lg(); else if ( !strcmp( *argv, "ln" ) ) ln(); else if ( !strcmp( *argv, "sqr" ) ) sqr(); else if ( !strcmp( *argv, "sqrt" ) ) sq(); else if ( !strcmp( *argv, "abs" ) ) ab(); else if ( !strcmp( *argv, "chs" ) ) chs(); else if ( !strcmp( *argv, "inv" ) ) inv(); else if ( !strcmp( *argv, "exc" ) ) exc(); else if ( !strcmp( *argv, "pi" ) ) { StackElement *tmpstack = new StackElement; tmpstack->value = M_PI; tmpstack->next = stack; stack = tmpstack; } else if ( !strcmp( *argv, "dup" ) ) { if ( !stack ) st_under(); StackElement *tmpstack = new StackElement; tmpstack->value = stack->value; tmpstack->next = stack; stack = tmpstack; } else if ( !strcmp( *argv, "pop" ) ) { if ( !stack ) st_under(); if ( !(stack->next) ) st_under(); stack = stack->next; } else { StackElement *tmpstack = new StackElement; tmpstack->value = atof(*argv); tmpstack->next = stack; stack = tmpstack; } } while ( stack ) { cout << setprecision(precision) << stack->value << endl; stack = stack->next; } } void fix() { if ( !stack ) st_under(); precision = (int) stack->value; stack = stack->next; } void add() { if ( !stack ) st_under(); if ( !(stack->next) ) st_under(); stack->next->value += stack->value; stack = stack->next; } void sub() { if ( !stack ) st_under(); if ( !(stack->next) ) st_under(); stack->next->value -= stack->value; stack = stack->next; } void mul() { if ( !stack ) st_under(); if ( !(stack->next) ) st_under(); stack->next->value *= stack->value; stack = stack->next; } void div() { if ( !stack ) st_under(); if ( !(stack->next) ) st_under(); if ( stack->value == 0.0 ) range(); stack->next->value /= stack->value; stack = stack->next; } void power() { if ( !stack ) st_under(); if ( !(stack->next) ) st_under(); if ( stack->next->value <= 0.0 ) range(); stack->next->value = pow ( stack->next->value, stack->value ); stack = stack->next; } void deg() { if ( !stack ) st_under(); stack->value = ( M_PI / 180 ) * stack->value; } void rad() { if ( !stack ) st_under(); stack->value = ( 180 / M_PI ) * stack->value; } void si() { if ( !stack ) st_under(); stack->value = sin( stack->value ); } void cs() { if ( !stack ) st_under(); stack->value = cos( stack->value ); } void tn() { if ( !stack ) st_under(); stack->value = tan( stack->value ); } void asi() { if ( !stack ) st_under(); stack->value = asin( stack->value ); } void acs() { if ( !stack ) st_under(); stack->value = acos( stack->value ); } void atn() { if ( !stack ) st_under(); stack->value = atan( stack->value ); } void ex() { if ( !stack ) st_under(); stack->value = exp( stack->value ); } void lg() { if ( !stack ) st_under(); if ( stack->value < 0.0 ) range(); stack->value = log10( stack->value ); } void ln() { if ( !stack ) st_under(); if ( stack->value < 0.0 ) range(); stack->value = log( stack->value ); } void sq() { if ( !stack ) st_under(); if ( stack->value < 0.0 ) range(); stack->value = sqrt( stack->value ); } void sqr() { if ( !stack ) st_under(); stack->value = stack->value*stack->value ; } void exc() { if ( !stack ) st_under(); if ( !(stack->next) ) st_under(); double tmp = stack->value; stack->value = stack->next->value; stack->next->value = tmp; } void inv() { if ( !stack ) st_under(); if ( stack->value == 0.0 ) range(); stack->value = 1.0 / stack->value; } void ab() { if ( !stack ) st_under(); stack->value = fabs( stack->value ); } void chs() { if ( !stack ) st_under(); stack->value = - stack->value; } void st_under() { cerr << " Stack underflow " << endl; exit ( EXIT_FAILURE ); } void range() { cerr << " range error" << endl; exit ( EXIT_FAILURE ); }