Major overhaul. Using pointer arithmetic and strtod now
This commit is contained in:
216
ee.c
216
ee.c
@@ -1,27 +1,207 @@
|
|||||||
|
|
||||||
#include "ee.h"
|
#include "ee.h"
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, const char* argv[]){
|
main (int argc, const char* argv[]){
|
||||||
STACK ee_stack = NULL;
|
|
||||||
int iter = 1;
|
STACK expr = NULL;
|
||||||
while (iter < argc){
|
const char** endPtr = argv+argc,
|
||||||
if (isNum(argv[iter])){
|
** arg = argv+1 ;
|
||||||
ee_stack = push(strtod(argv[iter],NULL), ee_stack);
|
|
||||||
}else if (isOperator(argv[iter][0])){
|
while ((arg < endPtr) && (!error)){
|
||||||
ee_stack = push(evaluate(&ee_stack, argv[iter][0]), ee_stack);
|
|
||||||
} else{
|
if (arrity(**arg))
|
||||||
ERR_INVALID_INPUT = 1;
|
expr = push(evaluate(&expr, **arg), expr);
|
||||||
|
|
||||||
|
else if(isNum(*arg))
|
||||||
|
expr = push(strtod(*arg,NULL), expr);
|
||||||
|
|
||||||
|
else
|
||||||
|
error |= ERR_INVALID_INPUT;
|
||||||
|
|
||||||
|
arg++;
|
||||||
}
|
}
|
||||||
iter++;
|
|
||||||
|
if (expr == NULL)
|
||||||
|
error |= ERR_NS_OPERANDS;
|
||||||
|
|
||||||
|
else if (expr->tail!=NULL)
|
||||||
|
error |= ERR_NS_OPERATORS;
|
||||||
|
|
||||||
|
report(expr);
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
if (ee_stack == NULL){
|
|
||||||
ERR_NS_OPERANDS = 1;
|
int // Dependency of main()
|
||||||
} else if (ee_stack->tail!=NULL){
|
isNum(const char* query){
|
||||||
ERR_NS_OPERATORS = 1;
|
|
||||||
|
/*
|
||||||
|
* If query is a string, isNum(query) iff query represents a number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char* alphas;
|
||||||
|
strtod(query, &alphas);
|
||||||
|
return !strcmp(alphas,"");
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!reportErrors()){
|
|
||||||
printf("%f\n", peek(ee_stack));
|
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;
|
||||||
}
|
}
|
||||||
return 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
172
ee.h
@@ -2,165 +2,35 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <ctype.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 isNum(const char*);
|
||||||
int isOperator(const char);
|
int arrity(const char);
|
||||||
|
|
||||||
double evaluate(STACK*, int);
|
double evaluate(STACK*, int);
|
||||||
double* getOperands(STACK*, int);
|
double* operands(STACK*, int);
|
||||||
double fact(int n);
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
39
ee_stack.h
39
ee_stack.h
@@ -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;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user