Major overhaul. Using pointer arithmetic and strtod now

This commit is contained in:
Jon Lewis
2018-06-27 15:26:32 -05:00
parent 2968740698
commit 63367550df
3 changed files with 222 additions and 211 deletions

222
ee.c
View File

@@ -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;
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++;
}
iter++;
}
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;
}

172
ee.h
View File

@@ -2,165 +2,35 @@
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include "ee_stack.h"
#include <string.h>
int ERR_NS_OPERANDS = 0;
int ERR_NS_OPERATORS = 0;
int ERR_INVALID_INPUT = 0;
int ERR_INVALID_FACTORIAL = 0;
// Summary
const int ERR_NS_OPERANDS = 1;
const int ERR_NS_OPERATORS = 2;
const int ERR_INVALID_INPUT = 4;
const int ERR_INVALID_FACTORIAL = 8;
struct EE_STACK_NODE {
double datum;
struct EE_STACK_NODE* tail;
};
typedef struct EE_STACK_NODE NODE;
typedef struct EE_STACK_NODE* STACK;
STACK push(double,STACK);
STACK pop(STACK);
double peek(STACK);
int isNum(const char*);
int isOperator(const char);
int arrity(const char);
double evaluate(STACK*, int);
double* getOperands(STACK*, int);
double* operands(STACK*, int);
double fact(int n);
int reportErrors();
void report();
int // Dependency of main()
isNum(const char* query){
/*
* If query is a string, isNum(query) iff query represents a number.
*/
int foundDecimal = 0; int foundSign = 0; int noDigits = 1;
int ch=0; int issues = 0; int i = 0;
while (!issues && ( ( ch = query[i] ) != '\0') ){
ch = query[i];
if (isdigit(ch)){
noDigits = 0;
}else {
if (ch == '-' || ch == '+'){
if (foundSign){ issues = 1; }
else {foundSign = 1;}
}
else if (ch == '.'){
if (foundDecimal) { issues = 1; }
else { foundDecimal = 1; }
}
else { issues = 1; }
}
i++;
}
if (noDigits) { issues = 1; }
return !issues;
}
int // Dependency of main()
isOperator(const char query){
/*
* If query is a string, isOperator iff query is a
* supported operator.
*/
switch (query){
case '+':
return 1; break;
case '-':
return 1; break;
case 'x':
return 1; break;
case '/':
return 1; break;
case '^':
return 1; break;
case '!':
return 1; break;
default:
return 0; break;
}
}
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;
double a,b; a=b=0;
double* operands;
switch (operator){
case '+' :
operands = getOperands(target_stack, 2);
value = operands[1] + operands[0];
break;
case '-' :
operands = getOperands(target_stack, 2);
value = operands[1] - operands[0];
break;
case 'x' :
operands = getOperands(target_stack, 2);
value = operands[1] * operands[0];
break;
case '/' :
operands = getOperands(target_stack, 2);
value = operands[1] / operands[0];
break;
case '^' :
operands = getOperands(target_stack, 2);
value = pow(operands[1],operands[0]);
break;
case '!' :
operands = getOperands(target_stack, 1);
if ( (operands[0] != floor(operands[0])) || (operands[0] < 0))
{ ERR_INVALID_FACTORIAL = 1; }
else{
value = fact((int)operands[0]);
}
break;
default :
break;
}
return value;
}
double* // Dependency of evaluate()
getOperands(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* operands = (double*)malloc(size*sizeof(double));
int i = 0;
for (i=0; i<size; i++){
if ((*target_stack) == NULL) { ERR_NS_OPERANDS = 1; }
operands[i] = peek((*target_stack));
(*target_stack) = pop(*target_stack);
}
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);
}
int // Dependency of main()
reportErrors(){
/*
* 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.
*/
int errors = 0;
if (ERR_INVALID_INPUT){
printf("Error: Unexpected input.\n"); errors++;
} else if (ERR_NS_OPERATORS){
printf("Error: insufficient operators.\n"); errors++;
} else if (ERR_NS_OPERANDS){
printf("Error: insufficient operands.\n"); errors++;
} else if (ERR_INVALID_FACTORIAL){
printf("Error: Factorials are only supported for positive integers.\n"); errors++;
}
return errors;
}

View File

@@ -1,39 +0,0 @@
struct EE_STACK_NODE {
double datum;
struct EE_STACK_NODE* tail;
};
typedef struct EE_STACK_NODE NODE;
typedef struct EE_STACK_NODE* STACK;
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;
*/
if (target_stack == NULL){ return target_stack; }
STACK 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.
*/
if (target_stack == NULL){ return 0; }
return (*target_stack).datum;
}