Major overhaul. Using pointer arithmetic and strtod now
This commit is contained in:
222
ee.c
222
ee.c
@@ -1,27 +1,207 @@
|
||||
|
||||
#include "ee.h"
|
||||
int error = 0;
|
||||
|
||||
int
|
||||
main (int argc, const char* argv[]){
|
||||
STACK ee_stack = NULL;
|
||||
int iter = 1;
|
||||
while (iter < argc){
|
||||
if (isNum(argv[iter])){
|
||||
ee_stack = push(strtod(argv[iter],NULL), ee_stack);
|
||||
}else if (isOperator(argv[iter][0])){
|
||||
ee_stack = push(evaluate(&ee_stack, argv[iter][0]), ee_stack);
|
||||
} else{
|
||||
ERR_INVALID_INPUT = 1;
|
||||
}
|
||||
iter++;
|
||||
|
||||
STACK expr = NULL;
|
||||
const char** endPtr = argv+argc,
|
||||
** arg = argv+1 ;
|
||||
|
||||
while ((arg < endPtr) && (!error)){
|
||||
|
||||
if (arrity(**arg))
|
||||
expr = push(evaluate(&expr, **arg), expr);
|
||||
|
||||
else if(isNum(*arg))
|
||||
expr = push(strtod(*arg,NULL), expr);
|
||||
|
||||
else
|
||||
error |= ERR_INVALID_INPUT;
|
||||
|
||||
arg++;
|
||||
}
|
||||
if (ee_stack == NULL){
|
||||
ERR_NS_OPERANDS = 1;
|
||||
} else if (ee_stack->tail!=NULL){
|
||||
ERR_NS_OPERATORS = 1;
|
||||
}
|
||||
if (!reportErrors()){
|
||||
printf("%f\n", peek(ee_stack));
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (expr == NULL)
|
||||
error |= ERR_NS_OPERANDS;
|
||||
|
||||
else if (expr->tail!=NULL)
|
||||
error |= ERR_NS_OPERATORS;
|
||||
|
||||
report(expr);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int // Dependency of main()
|
||||
isNum(const char* query){
|
||||
|
||||
/*
|
||||
* If query is a string, isNum(query) iff query represents a number.
|
||||
*/
|
||||
|
||||
char* alphas;
|
||||
strtod(query, &alphas);
|
||||
return !strcmp(alphas,"");
|
||||
|
||||
}
|
||||
|
||||
int // Dependency of main()
|
||||
arrity(const char query){
|
||||
/*
|
||||
* If query is a string, isOperator iff query is a
|
||||
* supported operator.
|
||||
*/
|
||||
return (query == '+')? 2:
|
||||
(query == 'x')? 2:
|
||||
(query == '/')? 2:
|
||||
(query == '^')? 2:
|
||||
(query == '!')? 1:
|
||||
0;
|
||||
}
|
||||
|
||||
|
||||
double // Dependency of main()
|
||||
evaluate(STACK* target_stack, int operator){
|
||||
/*
|
||||
* if target_stack is a pointer to a STACK and operator is
|
||||
* an integer corresponding to the ascii value of a supported
|
||||
* operator, evaluate(target_stack,operator) is the result of
|
||||
* applying the given operator to the appropriate number of
|
||||
* operands from target_stack.
|
||||
*/
|
||||
double value = 0,
|
||||
a = 0,
|
||||
b = 0;
|
||||
|
||||
double *_operands = operands(target_stack, arrity(operator));
|
||||
|
||||
switch (operator){
|
||||
|
||||
case '+' :
|
||||
value = _operands[1] + _operands[0];
|
||||
break;
|
||||
|
||||
case '-' :
|
||||
value = _operands[1] - _operands[0];
|
||||
break;
|
||||
|
||||
case 'x' :
|
||||
value = _operands[1] * _operands[0];
|
||||
break;
|
||||
|
||||
case '/' :
|
||||
value = _operands[1] / _operands[0];
|
||||
break;
|
||||
|
||||
case '^' :
|
||||
value = pow(_operands[1],_operands[0]);
|
||||
break;
|
||||
|
||||
case '!' :
|
||||
if ( (*_operands != floor(*_operands)) || (*_operands < 0))
|
||||
error |= ERR_INVALID_FACTORIAL;
|
||||
|
||||
else
|
||||
value = fact(*_operands);
|
||||
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
double* // Dependency of evaluate()
|
||||
operands(STACK* target_stack, int size){
|
||||
/*
|
||||
* if target_stack is a pointer to a STACK, and size is an integer
|
||||
* corresponding to the number of operands desired,
|
||||
* getOperands(target_stack,size) returns an array of operands and
|
||||
* pops them off *target_stack.
|
||||
*/
|
||||
double * const _operands = (double*)malloc(size*sizeof(double));
|
||||
|
||||
if ((*target_stack) == NULL)
|
||||
error |= ERR_NS_OPERANDS;
|
||||
|
||||
double * tPtr = _operands;
|
||||
double * endPtr = _operands + size;
|
||||
while ((tPtr < endPtr) && !error)
|
||||
{
|
||||
*tPtr = peek((*target_stack));
|
||||
(*target_stack) = pop(*target_stack);
|
||||
|
||||
tPtr += 1;
|
||||
}
|
||||
return _operands;
|
||||
}
|
||||
|
||||
double // Dependency of evaluate()
|
||||
fact(int n){
|
||||
/*
|
||||
* if n is an integer, fact(n) is 'n factorial'.
|
||||
*/
|
||||
return (n==0)? 1 : n*fact(n-1);
|
||||
}
|
||||
|
||||
void // Dependency of main()
|
||||
report(STACK expr){
|
||||
/*
|
||||
* reportErrors() returns an integer corresponding to
|
||||
* the number of discrete error types noted in global
|
||||
* variables ERR_NS_OPERANDS, ERR_NS_OPERATORS, and
|
||||
* ERR_INVALID_INPUT.
|
||||
*/
|
||||
|
||||
if (error & ERR_INVALID_INPUT)
|
||||
printf("Error: Unexpected input.\n");
|
||||
|
||||
else if (error & ERR_NS_OPERATORS)
|
||||
printf("Error: insufficient operators.\n");
|
||||
|
||||
else if (error & ERR_NS_OPERANDS)
|
||||
printf("Error: insufficient operands.\n");
|
||||
|
||||
else if (error & ERR_INVALID_FACTORIAL)
|
||||
printf("Error: Factorials are only supported for positive integers.\n");
|
||||
|
||||
else
|
||||
printf("%g\n", peek(expr));
|
||||
}
|
||||
|
||||
STACK
|
||||
push(double datum, STACK tail){
|
||||
/* Given a double value (datum), and a STACK (tail),
|
||||
* push(datum,tail) is the STACK resulting from
|
||||
* prepending datum to the STACK tail.
|
||||
*/
|
||||
NODE* new_node = (NODE*)malloc(sizeof(NODE));
|
||||
(*new_node).datum = datum;
|
||||
(*new_node).tail = tail;
|
||||
return new_node;
|
||||
}
|
||||
|
||||
STACK
|
||||
pop(STACK target_stack){
|
||||
/* Given a STACK (target_stack), pop(target_stack)
|
||||
* is the STACK resulting from the removal of the first
|
||||
* item in target_stack;
|
||||
*/
|
||||
|
||||
STACK tail = NULL;
|
||||
|
||||
if (target_stack != NULL){
|
||||
tail = (*target_stack).tail;
|
||||
free(target_stack);
|
||||
}
|
||||
return tail;
|
||||
}
|
||||
|
||||
double
|
||||
peek(STACK target_stack){
|
||||
/* Given a STACK (target_stack), peek(STACK)
|
||||
* is the first element's datum.
|
||||
*/
|
||||
return (target_stack)? (*target_stack).datum : 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user