Created
December 8, 2011 07:47
-
-
Save garyburd/1446409 to your computer and use it in GitHub Desktop.
My first C program
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* rpn.c -- reverse polish notation calculator. G.S.BURD 25-Mar-1984 */ | |
#include <math.h> | |
#include <stdio.h> | |
#include <ctype.h> | |
extern char *fgets(); | |
extern double push(), pop(); | |
/* function codes */ | |
#define TRUE 1 | |
#define FALSE 0 | |
#define EXITPROGRAM 1 | |
#define GIVEHELP 2 | |
#define CLEAR 3 | |
#define CHANGESIGN 4 | |
#define ADD 5 | |
#define SUBTRACT 6 | |
#define MULTIPLY 7 | |
#define DIVIDE 8 | |
#define RECIPROCAL 9 | |
#define SQUARE 10 | |
#define SQUAREROOT 11 | |
#define SINE 12 | |
#define COSINE 13 | |
#define TANGENT 14 | |
#define ARCSINE 15 | |
#define ARCOSINE 16 | |
#define ARCTANGENT 17 | |
#define RADIAN 18 | |
#define DEGREE 19 | |
#define PI 20 | |
#define NATURALLOG 21 | |
#define BASE10LOG 22 | |
#define ETOTHEX 23 | |
#define POWER 24 | |
#define NUMFUNCTIONS 24 | |
#define UNKNOWN -1 | |
#define NUMBER 0 | |
/* function table; must be in lexical order */ | |
struct function { | |
char *text; | |
int code; | |
} funtable[] = { | |
"*", MULTIPLY, | |
"+", ADD, | |
"-", SUBTRACT, | |
"/", DIVIDE, | |
"?", GIVEHELP, | |
"acos", ARCOSINE, | |
"asin", ARCSINE, | |
"atan", ARCTANGENT, | |
"chs", CHANGESIGN, | |
"clr", CLEAR, | |
"cos", COSINE, | |
"deg", DEGREE, | |
"exp", ETOTHEX, | |
"ln", NATURALLOG, | |
"log", BASE10LOG, | |
"pi", PI, | |
"pow", POWER, | |
"rad", RADIAN, | |
"rec", RECIPROCAL, | |
"sin", SINE, | |
"sqr", SQUARE, | |
"sqrt", SQUAREROOT, | |
"tan", TANGENT, | |
"\0", 0, | |
}; | |
#define MAXOP 40 /* max size of operand, operator */ | |
#define MAXLINE 132 /* max size of a line */ | |
#define RADPERDEG (3.1415926535897 / 180.0) | |
main(argc, argv) | |
int argc; | |
char *argv[]; | |
{ | |
char line[MAXLINE]; | |
if (argc <= 1) { | |
printf("\t\t\t> "); | |
while ( fgets( line, MAXLINE, stdin) != NULL ) { | |
process( line ); | |
print_top(); | |
printf( "\t> "); | |
} | |
} | |
else { | |
while (--argc > 0) | |
process( *++argv ); | |
print_top(); | |
} | |
} | |
/* process -- process a string */ | |
process( str ) | |
char str[]; | |
{ | |
char s[MAXOP]; | |
int i; | |
i = 0; | |
while ( i = getword( str, i, s ) ) | |
dofun( getfun( s ), s ); | |
} | |
/* getword -- get next word from str at i */ | |
getword( str, i, out ) | |
char str[], out[]; | |
int i; | |
{ | |
int j; | |
while ( isspace( str[i] ) ) | |
i++; | |
if( str[ i ] == '\0' ) return( 0 ); | |
j = 0; | |
while ( ( ! isspace( str[i] ) ) && ( str[i] != '\0' ) ) | |
out[ j++ ] = tolower( str[ i++ ] ); | |
out[ j ] = '\0'; | |
return( i ); | |
} | |
/* getfun -- get function code from s */ | |
getfun( s ) | |
char s[]; | |
{ | |
int high, low, mid, cond; | |
if ( isanumber(s) ) | |
return( NUMBER ); | |
else { | |
low = 0; | |
high = NUMFUNCTIONS - 1; | |
while ( low <= high ) { | |
mid = ( low + high ) / 2; | |
if (( cond = strcmp( s, funtable[mid].text )) < 0 ) | |
high = mid - 1; | |
else if ( cond > 0 ) | |
low = mid + 1; | |
else | |
return( funtable[mid].code ); | |
} | |
return( UNKNOWN ); | |
} | |
} | |
/* isanumber -- determine if s contains a digit */ | |
isanumber( s ) | |
char s[]; | |
{ | |
int i; | |
for( i = 0; s[i] != '\0'; i++ ) | |
if ( isdigit( s[i] ) ) return( TRUE ); | |
return( FALSE ); | |
} | |
/* dofun -- do a function */ | |
dofun( i, s ) | |
int i; | |
char s[]; | |
{ | |
static double degrad = 1.0; | |
double op, op2; | |
double atof(), pop(), push(); | |
switch ( i ) { | |
case NUMBER: | |
push( atof(s) ); | |
break; | |
case ADD: | |
push( pop() + pop() ); | |
break; | |
case SUBTRACT: | |
op2 = pop(); | |
push( pop() - op2 ); | |
break; | |
case MULTIPLY: | |
push( pop() * pop() ); | |
break; | |
case DIVIDE: | |
op2 = pop(); | |
if ( op2 != 0.0 ) | |
push( pop() / op2 ); | |
else { | |
push( op2 ); | |
printf("? zero divisor\n"); | |
} | |
break; | |
case RECIPROCAL: | |
op = pop(); | |
if ( op != 0.0 ) | |
push( 1.0 / op ); | |
else { | |
push( op ); | |
printf("? zero divisor\n"); | |
} | |
break; | |
case CHANGESIGN: | |
push( pop() * -1.0 ); | |
break; | |
case DEGREE: | |
degrad = RADPERDEG; | |
break; | |
case RADIAN: | |
degrad = 1.0; | |
break; | |
case PI: | |
push( 3.1415926535897 ); | |
break; | |
case ARCOSINE: | |
op = pop(); | |
if ( fabs(op) <= 1.0 ) | |
push( acos(op) / degrad ); | |
else { | |
push( op ); | |
printf("? |x| > 1 for acos\n"); | |
} | |
break; | |
case ARCSINE: | |
op = pop(); | |
if ( fabs(op) <= 1.0 ) | |
push( asin( op ) / degrad ); | |
else { | |
push( op ); | |
printf("? |x| > 1 for asin\n"); | |
} | |
break; | |
case ARCTANGENT: | |
push( atan( pop() ) / degrad ); | |
break; | |
case COSINE: | |
push( cos( pop() * degrad ) ); | |
break; | |
case ETOTHEX: | |
push( exp( pop() ) ); | |
break; | |
case NATURALLOG: | |
op = pop(); | |
if ( op > 0.0 ) | |
push( log( op ) ); | |
else { | |
push( op ); | |
printf("? x <= 0 for ln\n"); | |
} | |
break; | |
case BASE10LOG: | |
op = pop(); | |
if ( op > 0.0 ) | |
push( log10( op ) ); | |
else { | |
push( op ); | |
printf("? x <= 0 for ln\n"); | |
} | |
break; | |
case POWER: | |
op2 = pop(); | |
push( pow( pop(), op2 ) ); | |
break; | |
case SINE: | |
push( sin( pop() * degrad ) ); | |
break; | |
case SQUAREROOT: | |
op = pop(); | |
if( op < 0.0 ) { | |
push( op ); | |
printf("? x < 0 for sqrt\n"); | |
} | |
else | |
push( sqrt( op ) ); | |
break; | |
case SQUARE: | |
op = pop(); | |
push( op * op ); | |
break; | |
case TANGENT: | |
push( tan( pop() * degrad ) ); | |
break; | |
case CLEAR: | |
clear(); | |
break; | |
case GIVEHELP: | |
help(); | |
break; | |
case UNKNOWN: | |
printf("? unknown function \"%s\",\n type \"?\" for help\n",s); | |
break; | |
}; | |
error_clear(); | |
} | |
/* help -- print out help information */ | |
help() | |
{ | |
int i; | |
printf("\n\nthe available functions are:\n"); | |
for(i=0; i < NUMFUNCTIONS; i++) | |
printf((i % 7) ? " %-5s" : "\n%-5s", funtable[i].text ); | |
printf("\n"); | |
} | |
/* s t a c k r o u t i n e s */ | |
#define MAXVAL 127 | |
int stack_ptr = 0; /* index of top value on stack */ | |
double stack_val[MAXVAL]; /* the value stack */ | |
int stack_err = 0; /* non zero on stack error */ | |
/* push -- pushes f on value stack */ | |
double push( f ) | |
double f; | |
{ | |
if ( stack_err ) return( 0 ); | |
if ( stack_ptr < MAXVAL ) | |
return( stack_val[ ++stack_ptr ] = f ); | |
else { | |
printf("? stack is full\n"); | |
++stack_err; | |
return( 0 ); | |
} | |
} | |
/* pop -- pops top value from stack */ | |
double pop() | |
{ | |
if ( stack_err ) return( 0 ); | |
if ( stack_ptr > 0 ) | |
return( stack_val[ stack_ptr-- ] ); | |
else { | |
printf("? stack is empty\n"); | |
++stack_err; | |
return( 0 ); | |
} | |
} | |
/* clear -- clear the stack */ | |
clear() | |
{ | |
stack_ptr = 0; | |
} | |
/* print_top -- print the top of the stack */ | |
print_top() | |
{ | |
if ( stack_ptr <= 0 ) | |
printf(" "); /* print blanks if it is empty */ | |
else | |
printf( "%16g" ,stack_val[ stack_ptr ] ); | |
} | |
/* error_clear -- clear errors on stack access */ | |
error_clear() | |
{ | |
stack_err = 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment