jac@yoko.rutgers.edu (Jonathan A. Chandross) (12/02/90)
Submitted-by: NONE Posting-number: Volume 1, Source:11 Archive-name: util/calculator/dc Architecture: ANY_2 Version-number: 1.00 Enclosed is a simple desk calculator in C. Enjoy. =dc.c -/* - * dc.c - * - * Desk calculator. Supports +,-,* and / on integer and floating point. - * - * Usage: - * dc - * - * Commands: - * d duplicate top of stack (TOS) - * p print TOS - * f print all stack entries - * c clear stack - * q quit - * * replace TOS, NOS with NOS * TOS - * / replace TOS, NOS with NOS / TOS - * + replace TOS, NOS with NOS * TOS - * - replace TOS, NOS with NOS - TOS - * <number> push <number> onto stack, where number is: - * [+|-] digit+ - * [+|-] [digit+] . digit+ - * - * Adapted from C Reference Manual - * - * Notes: must be linked to flt.lib - * - * Contributed Anonymously. Written: November 1983 - * - * Version 1.00 - * - */ - -#include "stdio.h" /* contains extra defines for EOF, etc */ - -#define BLANK ' ' -#define TAB '\t' -#define NL '\n' -#define EOS '\0' - -#define MAXOP 20 -#define NUMBER '0' -#define TOOBIG '9' - -main() -{ - int type ; - char s[MAXOP] ; - double op2, atof(), pop(), push() ; - - while( (type = getop(s,MAXOP)) != EOF ) - switch( type ) { - case NUMBER: - push( atof(s) ) ; - break ; - case '+': - push( pop() + pop() ) ; - break ; - case '*': - push( pop() * pop() ) ; - break ; - case '-': - op2 = pop() ; - push( pop() - op2 ) ; - break ; - case '/': - op2 = pop() ; - if( op2 != 0.0 ) - push( pop() / op2 ) ; - else - fprintf(stderr, "dc: divide by zero\n"); - break ; - case 'd': - push( push( pop() ) ) ; - break ; - case 'p': - top() ; - break ; - case 'f': - print() ; - break ; - case 'c': - empty() ; - break ; - case 'q': - printf("\n") ; - exit(0) ; - case TOOBIG: - fprintf(stderr, "dc: %.20s is too long\n", s ) ; - break ; - default: - fprintf(stderr, "dc: unknown commnd %c\n", type ) ; - break ; - } - -} /* end main */ - -/* stack declarations */ - -#define STACKSIZE 100 - -int sp = 0 ; -double stack[STACKSIZE] ; - -/* push - push new value on stack */ - -double push(f) -double f ; -{ - if( sp < STACKSIZE ) - return stack[sp++] = f ; - else { - printf("dc: stack is full\n"); - empty() ; - return 0 ; - } - -} /* end push */ - -/* pop - return top of stack */ - -double pop() -{ - if( sp > 0 ) - return stack[--sp] ; - else { - printf("dc: stack empty\n") ; - empty() ; - return 0 ; - } - -} /* end pop */ - -/* empty - empty the stack */ - -empty() -{ - sp = 0 ; -} - -/* top - print top stack entry */ - -top() -{ - int i ; - double d ; - - if( sp <= 0 ) - return ; - d = stack[ sp-1 ] ; - i = d ; - if( ((double) i) == d ) - printf("%c%d\n", TAB, i ) ; - else - printf("%c%f\n", TAB, d ) ; -} - -/* print - show all stack entries */ - -print() -{ - int i, s ; - double d ; - - for( s=sp-1 ; s >= 0 ; s-- ) { - d = stack[ s ] ; - i = d ; - if( ((double) i) == d ) - printf("%c%d\n", TAB, i ) ; - else - printf("%c%f\n", TAB, d ) ; - } -} - -/* getop - get next operator, operand */ - -getop( s, limit ) -char s[] ; -int limit ; -{ - int i, c, oldc ; - - i = 0 ; - do - c = agetc(stdin) ; - while( c == BLANK || c == TAB || c == NL ) ; - - i = 0 ; - if( c != '.' && c != '-' && c != '+' && (c < '0' || c > '9') ) - return c ; - - if( c == '+' || c == '-' ) { - oldc = c ; - c = agetc(stdin) ; - if( c != '.' && (c < '0' || c > '9') ) { - ungetc( c, stdin ) ; - return oldc ; - } - else - s[i++] = oldc ; - } - s[i++] = c ; - for( ; (c = agetc(stdin)) >= '0' && c <= '9' ; i++ ) - if( i < limit ) - s[i] = c ; - if( c == '.' ) { - if( i < limit ) - s[i] = c ; - for( i++ ; (c = agetc(stdin)) >= '0' && c <= '9' ; i++ ) - if( i < limit ) - s[i] = c ; - } - if( i < limit ) { - ungetc( c, stdin ) ; - s[i] = EOS ; - return NUMBER ; - } - else { - while( c != NL && c != EOF ) - c = agetc(stdin) ; - s[limit-1] = EOS ; - return TOOBIG ; - } - -} /* end getop */ - - + END OF ARCHIVE