165 lines
4.5 KiB
C
165 lines
4.5 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <ctype.h>
|
|
#include "ee_stack.h"
|
|
|
|
int ERR_NS_OPERANDS = 0;
|
|
int ERR_NS_OPERATORS = 0;
|
|
int ERR_INVALID_INPUT = 0;
|
|
int ERR_INVALID_FACTORIAL = 0;
|
|
|
|
// Summary
|
|
int isNum(const char*);
|
|
int isOperator(const char);
|
|
|
|
double evaluate(STACK*, int);
|
|
double* getOperands(STACK*, int);
|
|
double fact(int n);
|
|
|
|
int reportErrors();
|
|
|
|
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])))
|
|
{ ERR_INVALID_FACTORIAL = 1; }
|
|
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_NS_OPERANDS){
|
|
printf("Error: insufficient operands.\n"); errors++;
|
|
} else if (ERR_NS_OPERATORS){
|
|
printf("Error: insufficient operators.\n"); errors++;
|
|
} else if (ERR_INVALID_INPUT){
|
|
printf("Error: Unexpected input.\n"); errors++;
|
|
} else if (ERR_INVALID_FACTORIAL){
|
|
printf("Error: only integer factorials are supported.\n"); errors++;
|
|
}
|
|
return errors;
|
|
}
|