From 92eda19bdd5a1bf5b25e37ebbae5ea155e4f2d00 Mon Sep 17 00:00:00 2001 From: Vera Lewis Date: Wed, 27 Mar 2024 04:30:17 -0500 Subject: [PATCH] Fixed negative number issue --- Makefile | 22 +++++ src/ee.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ee.h | 36 +++++++++ 3 files changed, 298 insertions(+) create mode 100644 Makefile create mode 100644 src/ee.c create mode 100644 src/ee.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..834baaa --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +LFLAGS = -lm +CFLAGS = -Wall +CC = gcc + +BUILD_ROOT=. +SDIR=$(BUILD_ROOT)/src +BDIR=$(BUILD_ROOT)/build + +$(BDIR)/ee: $(BDIR) $(SDIR)/$(wildcard *.c) + $(CC) $(CFLAGS) $(LFLAGS) -o $@ src/ee.c + +$(BDIR): + mkdir $(BDIR) + +ee: $(BDIR)/ee + +clean: + $(MAKE) --no-print-directory -C $(SRC_DIR) clean + rm -rf $(BUILD_DIR)/* + +install: +run: test diff --git a/src/ee.c b/src/ee.c new file mode 100644 index 0000000..6220442 --- /dev/null +++ b/src/ee.c @@ -0,0 +1,240 @@ + #include "ee.h" +int error = 0; +void printStack(STACK); + +int +main (const int argc, const char* argv[]) +{ + + STACK expr = NULL; + + const char** endPtr = argv+argc, + ** arg = argv+1 ; + + char* fmt = (argc > 1)? (strcmp(argv[1],"-f")==0)? "%f\n" : "%g\n" : "%g\n"; + + while ((arg < endPtr) && (!error)){ + + if(isNum(*arg)) + push(strtod(*arg, NULL), &expr); + + else if (arrity(**arg)) + push(evaluate(&expr, **arg), &expr); + + else + error |= ERR_INVALID_INPUT; + + arg += 1; + + } + + if (expr == NULL) + error |= ERR_NS_OPERANDS; + + else if ((*expr).tail != NULL) + error |= ERR_NS_OPERATORS; + + report(&expr, fmt); + + return error; +} + +int +isNum(const char* query) +{ + + /* + * If query is a string, isNum(query) iff query represents a number. + */ + + char *extra_char; + strtod(query, &extra_char); + return strcmp(extra_char, "") == 0; + +} + +int +arrity(const char query) +{ + /* + * If query is a string corresponding to an operator in {+,x,-,/,^,!,%}, then + * arrity(query) is the number of operands required by the operator. + * If query is any other string, arrity(query) is zero. + */ + return (query == '+')? 2: + (query == 'x')? 2: + (query == '-')? 2: + (query == '/')? 2: + (query == '^')? 2: + (query == '%')? 2: + (query == '!')? 1: + 0; +} + + +double +evaluate(STACK* target_stack, char operator) +{ + /* + * If target_stack is a pointer to a STACK and operator is + * a char corresponding to 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; + + case '%' : + value = ((int)_operands[1] % (int)_operands[0]); + break; + + default : + break; + } + return value; +} +double* +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, + * operands(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)); + pop(target_stack); + + tPtr += 1; + } + return _operands; +} + +double +fact(int n) +{ + /* + * if n is an integer, fact(n) is 'n factorial'. + */ + return (n==0)? 1 : n*fact(n-1); +} + +void +report(STACK* expr, char* fmt) +{ + /* + * reportErrors() prints error strings according to the value of global + * bitvector error if it is nonzero, or the result of evaluation if error + * is zero. + */ + + //printStack(expr); + 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(fmt, peek(expr)); +} + +void +printStack(STACK s) +{ + /* Given a stack, print "datum tail"*/ + + while (s != NULL) { + printf("%g\t%p\n", s->datum, s->tail); + s = s->tail; + } + printf("%s\n", "-----"); +} + +void +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; + (*tail) = new_node; +} + +void +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); + } + (*target_stack) = 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; +} diff --git a/src/ee.h b/src/ee.h new file mode 100644 index 0000000..cd4c4d0 --- /dev/null +++ b/src/ee.h @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include + + +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; + +void push(double,STACK*); +void pop(STACK*); +double peek(STACK*); + +int isNum(const char*); +int arrity(const char); + +double evaluate(STACK*, char); +double* operands(STACK*, int); +double fact(int n); + +void report(STACK*,char*); + + + +