Fixed negative number issue
This commit is contained in:
22
Makefile
Normal file
22
Makefile
Normal file
@@ -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
|
||||||
240
src/ee.c
Normal file
240
src/ee.c
Normal file
@@ -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;
|
||||||
|
}
|
||||||
36
src/ee.h
Normal file
36
src/ee.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
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*);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user