123 lines
3.8 KiB
C
123 lines
3.8 KiB
C
#include "calculator.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
|
|
#define MAX 256
|
|
#define DEG_TO_RAD(x) ((x) * M_PI / 180.0)
|
|
|
|
typedef struct {
|
|
double data[MAX];
|
|
int top;
|
|
} DoubleStack;
|
|
|
|
typedef struct {
|
|
char data[MAX][10];
|
|
int top;
|
|
} StringStack;
|
|
|
|
//funckie stacku
|
|
void push_double(DoubleStack *s, double v) { s->data[++s->top] = v; }
|
|
double pop_double(DoubleStack *s) { return s->data[s->top--]; }
|
|
|
|
void push_string(StringStack *s, const char *v) { strcpy(s->data[++s->top], v); }
|
|
char *pop_string(StringStack *s) { return s->data[s->top--]; }
|
|
char *peek_string(StringStack *s) { return s->data[s->top]; }
|
|
|
|
//priority operatorov
|
|
int priority(const char *op) {
|
|
if (!strcmp(op, "+") || !strcmp(op, "-")) return 1;
|
|
if (!strcmp(op, "*") || !strcmp(op, "/")) return 2;
|
|
if (!strcmp(op, "sin") || !strcmp(op, "cos") ||
|
|
!strcmp(op, "sqrt") || !strcmp(op, "log") ||
|
|
!strcmp(op, "pow")) return 3;
|
|
return 0;
|
|
}
|
|
|
|
//infix na postfix
|
|
int infix_to_postfix(const char *infix, char postfix[][10]) {
|
|
StringStack ops = {.top = -1};
|
|
int k = 0;
|
|
|
|
for (int i = 0; infix[i]; ) {
|
|
if (isspace(infix[i])) { i++; continue; }
|
|
|
|
if (isdigit(infix[i]) || infix[i] == '.') {
|
|
char num[10];
|
|
int j = 0;
|
|
while (isdigit(infix[i]) || infix[i] == '.')
|
|
num[j++] = infix[i++];
|
|
num[j] = '\0';
|
|
strcpy(postfix[k++], num);
|
|
}
|
|
else if (isalpha(infix[i])) {
|
|
char func[10];
|
|
int j = 0;
|
|
while (isalpha(infix[i]))
|
|
func[j++] = infix[i++];
|
|
func[j] = '\0';
|
|
push_string(&ops, func);
|
|
}
|
|
else if (infix[i] == '(') {
|
|
char t[2] = "(";
|
|
push_string(&ops, t);
|
|
i++;
|
|
}
|
|
else if (infix[i] == ')') {
|
|
while (ops.top != -1 && strcmp(peek_string(&ops), "("))
|
|
strcpy(postfix[k++], pop_string(&ops));
|
|
pop_string(&ops);
|
|
i++;
|
|
}
|
|
else {
|
|
char op[2] = {infix[i++], '\0'};
|
|
while (ops.top != -1 &&
|
|
priority(peek_string(&ops)) >= priority(op))
|
|
strcpy(postfix[k++], pop_string(&ops));
|
|
push_string(&ops, op);
|
|
}
|
|
}
|
|
|
|
while (ops.top != -1)
|
|
strcpy(postfix[k++], pop_string(&ops));
|
|
|
|
return k;
|
|
}
|
|
|
|
//vypocet postfixu
|
|
double evaluate_postfix(char postfix[][10], int n) {
|
|
DoubleStack s = {.top = -1};
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
if (isdigit(postfix[i][0]) || postfix[i][0] == '.') {
|
|
push_double(&s, atof(postfix[i]));
|
|
}
|
|
else {
|
|
double b = pop_double(&s);
|
|
double a = (!strcmp(postfix[i], "sin") ||
|
|
!strcmp(postfix[i], "cos") ||
|
|
!strcmp(postfix[i], "sqrt") ||
|
|
!strcmp(postfix[i], "log")) ? 0 : pop_double(&s);
|
|
|
|
if (!strcmp(postfix[i], "+")) push_double(&s, a + b);
|
|
else if (!strcmp(postfix[i], "-")) push_double(&s, a - b);
|
|
else if (!strcmp(postfix[i], "*")) push_double(&s, a * b);
|
|
else if (!strcmp(postfix[i], "/")) push_double(&s, a / b);
|
|
else if (!strcmp(postfix[i], "sin")) push_double(&s, sin(DEG_TO_RAD(b)));
|
|
else if (!strcmp(postfix[i], "cos")) push_double(&s, cos(DEG_TO_RAD(b)));
|
|
else if (!strcmp(postfix[i], "sqrt")) push_double(&s, sqrt(b));
|
|
else if (!strcmp(postfix[i], "log")) push_double(&s, log10(b));
|
|
else if (!strcmp(postfix[i], "pow")) push_double(&s, pow(a, b));
|
|
}
|
|
}
|
|
return pop_double(&s);
|
|
}
|
|
|
|
double evaluate_expression(const char *expression) {
|
|
char postfix[MAX][10];
|
|
int n = infix_to_postfix(expression, postfix);
|
|
return evaluate_postfix(postfix, n);
|
|
}
|