Here's a C program that evaluates Reverse Polish Notation (RPN) expressions, supporting standard arithmetic operators (+, -, *, /, %) and additional mathematical functions (SQR, SIN, COS, TAN, ASIN, ACOS, ATAN, EXP, LN, LOG10).
RPN Evaluator in C
Code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STACK 100
#define MAX_TOKEN_LEN 20
// Stack structure to hold the operands
typedef struct {
double data[MAX_STACK];
int top;
} Stack;
void push(Stack *s, double value) {
if (s->top == MAX_STACK - 1) {
printf("Stack overflow\n");
exit(EXIT_FAILURE);
}
s->data[++(s->top)] = value;
}
double pop(Stack *s) {
if (s->top == -1) {
printf("Stack underflow\n");
exit(EXIT_FAILURE);
}
return s->data[(s->top)--];
}
int isOperator(const char *token) {
return strlen(token) == 1 && strchr("+-*/%", token[0]) != NULL;
}
int isFunction(const char *token) {
return strcmp(token, "SQR") == 0 || strcmp(token, "SIN") == 0 ||
strcmp(token, "COS") == 0 || strcmp(token, "TAN") == 0 ||
strcmp(token, "ASIN") == 0 || strcmp(token, "ACOS") == 0 ||
strcmp(token, "ATAN") == 0 || strcmp(token, "EXP") == 0 ||
strcmp(token, "LN") == 0 || strcmp(token, "LOG10") == 0;
}
double evaluateOperator(double a, double b, char op) {
switch (op) {
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
case '%':
return fmod(a, b);
default:
printf("Unknown operator: %c\n", op);
exit(EXIT_FAILURE);
}
}
double evaluateFunction(const char *func, double x) {
if (strcmp(func, "SQR") == 0)
return x * x;
else if (strcmp(func, "SIN") == 0)
return sin(x);
else if (strcmp(func, "COS") == 0)
return cos(x);
else if (strcmp(func, "TAN") == 0)
return tan(x);
else if (strcmp(func, "ASIN") == 0)
return asin(x);
else if (strcmp(func, "ACOS") == 0)
return acos(x);
else if (strcmp(func, "ATAN") == 0)
return atan(x);
else if (strcmp(func, "EXP") == 0)
return exp(x);
else if (strcmp(func, "LN") == 0)
return log(x);
else if (strcmp(func, "LOG10") == 0)
return log10(x);
else {
printf("Unknown function: %s\n", func);
exit(EXIT_FAILURE);
}
}
void evaluateRPN(const char *expression) {
Stack stack = {.top = -1};
char token[MAX_TOKEN_LEN];
const char *delimiter = " ";
char *expCopy = strdup(expression); // Duplicate the expression string for tokenizing
char *ptr = strtok(expCopy, delimiter);
while (ptr != NULL) {
if (isOperator(ptr)) {
double b = pop(&stack);
double a = pop(&stack);
push(&stack, evaluateOperator(a, b, ptr[0]));
} else if (isFunction(ptr)) {
double x = pop(&stack);
push(&stack, evaluateFunction(ptr, x));
} else { // Operand
push(&stack, atof(ptr));
}
ptr = strtok(NULL, delimiter);
}
printf("Result: %.10g\n", pop(&stack));
free(expCopy);
}
int main() {
const char *expression = "3 4 + 2 * 7 /"; // Example expression
evaluateRPN(expression);
const char *complexExpression = "9 2 / SIN 2 SQR + 1 + LOG10"; // More complex expression
evaluateRPN(complexExpression);
return 0;
}
Explanation:
1. Stack Operations:
- push: Adds a value to the stack.
- pop: Removes and returns the top value from the stack.
2. Token Identification:
- isOperator: Checks if the token is a standard arithmetic operator.
- isFunction: Checks if the token is one of the supported mathematical functions.
3. Evaluation Functions:
- evaluateOperator: Evaluates binary operations (+, -, *, /, %).
- evaluateFunction: Evaluates mathematical functions (SQR, SIN, COS, TAN, etc.).
4. RPN Evaluation:
- The evaluateRPN function processes the RPN expression token by token.
- For operators and functions, it pops the necessary operands, applies the operation or function, and pushes the result back onto the stack.
- Finally, the result of the expression is printed.
5. Main Function:
- Demonstrates how to evaluate simple and complex RPN expressions.
Example Expressions:
- "3 4 + 2 * 7 /": This evaluates to (3 + 4) * 2 / 7 = 2.
- "9 2 / SIN 2 SQR + 1 + LOG10": This evaluates the sine of 9 / 2, squares 2, adds the results, adds 1, and then computes the log base 10 of the result.
This program should cover most common operations and mathematical functions that you would need in an RPN evaluator.