182 lines
6.5 KiB
C
182 lines
6.5 KiB
C
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <math.h>
|
||
#include <ctype.h>
|
||
#include "calculator.h"
|
||
|
||
typedef struct {
|
||
double data[100];
|
||
int top;
|
||
} Stack;
|
||
|
||
void stack_init(Stack* stack) {
|
||
stack->top = -1;
|
||
}
|
||
|
||
void push(Stack* stack, double value) {
|
||
stack->data[++stack->top] = value;
|
||
}
|
||
|
||
double delet(Stack* stack) {
|
||
return stack->data[stack->top--];
|
||
}
|
||
|
||
int isOperator(char op) {
|
||
return (op == '+' || op == '-' || op == '*' || op == '/' || op == 's' || op == 'c' || op == 'l' || op == 'r' || op == 'k' || op == '^' || op == 'L');
|
||
}
|
||
|
||
int precedence(char op) {
|
||
switch(op) {
|
||
case '+':
|
||
case '-':
|
||
return 1;
|
||
case '*':
|
||
case '/':
|
||
return 2;
|
||
case '^':
|
||
return 3;
|
||
case 's':
|
||
case 'c':
|
||
case 'l':
|
||
case 'L':
|
||
case 'r':
|
||
case 'k':
|
||
return 4;
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
double applyOperator(double a, double b, char op) {
|
||
switch(op) {
|
||
case '+': return a + b;
|
||
case '-': return a - b;
|
||
case '*': return a * b;
|
||
case '/': return (b != 0) ? (a / b) : 0; // Деление (проверка на деление на ноль)
|
||
case '^': return pow(a, b);
|
||
case 's': return sin(a);
|
||
case 'c': return cos(a);
|
||
case 'l': return (a > 0) ? log(a) : 0; // Проверка на отрицательное число для натурального логарифма
|
||
case 'L': return (a > 0) ? log10(a) : 0; // Десятичный логарифм(проверка на отрицательное число)
|
||
case 'r':
|
||
if (a >= 0) {
|
||
return sqrt(a);
|
||
} else {
|
||
printf("Argument entered incorrectly: %lf\n", a); // Если квадратный корень вводится с "-" то ошибка
|
||
return 0;
|
||
}
|
||
case 'k': return sqrt(a); // Квадратный корень
|
||
default: return 0;
|
||
}
|
||
}
|
||
|
||
double evaluateExpression(char* expression, int configuration) {
|
||
Stack operandStack;
|
||
Stack operatorStack;
|
||
stack_init(&operandStack);
|
||
stack_init(&operatorStack);
|
||
|
||
int i = 0;
|
||
int unary = 1; // Изначально знак операнда - положительный
|
||
|
||
while (expression[i] != '\0') {
|
||
if (expression[i] == ' ' || expression[i] == '\n') {
|
||
i++;
|
||
continue;
|
||
}
|
||
else if (isdigit(expression[i]) || expression[i] == '.') {
|
||
double operand = strtod(&expression[i], NULL) * unary;
|
||
push(&operandStack, operand);
|
||
while (isdigit(expression[i]) || expression[i] == '.') {
|
||
i++;
|
||
}
|
||
unary = 1; // Сброс унарного минуса
|
||
continue;
|
||
}
|
||
else if (expression[i] == '(') {
|
||
if (i > 0 && expression[i - 1] == '-') {
|
||
unary *= -1; // Смена знака
|
||
}
|
||
push(&operatorStack, expression[i]);
|
||
i++;
|
||
}
|
||
else if (expression[i] == ')') {
|
||
while (operatorStack.data[operatorStack.top] != '(') {
|
||
char op = pop(&operatorStack);
|
||
double b = delet(&operandStack);
|
||
double a = delet(&operandStack);
|
||
push(&operandStack, applyOperator(a, b, op));
|
||
}
|
||
delet(&operatorStack); // Pop '('
|
||
i++;
|
||
}
|
||
else if (isOperator(expression[i])) {
|
||
if (expression[i] == '-' && (i == 0 || expression[i-1] == '(')) {
|
||
unary = -1;
|
||
i++;
|
||
continue;
|
||
}
|
||
else if ((configuration == 1 && (expression[i] == '*' || expression[i] == '-' || expression[i] == '+' || expression[i] == '/' || expression[i] == '^')) ||
|
||
(configuration == 2)) {
|
||
while (operatorStack.top != -1 && precedence(operatorStack.data[operatorStack.top]) >= precedence(expression[i])) {
|
||
char op = delet(&operatorStack);
|
||
double b = delet(&operandStack);
|
||
double a = delet(&operandStack);
|
||
push(&operandStack, applyOperator(a, b, op));
|
||
}
|
||
push(&operatorStack, expression[i]);
|
||
}
|
||
|
||
else if (expression[i] == 'k') {
|
||
while (operatorStack.top != -1 && precedence(operatorStack.data[operatorStack.top]) >= precedence(expression[i])) {
|
||
char op = delet(&operatorStack);
|
||
double a = delet(&operandStack);
|
||
push(&operandStack, applyOperator(a, 0, op)); // Так как корень одиночный оператор, второй операнд будет игнорироваться
|
||
}
|
||
push(&operatorStack, expression[i]);
|
||
}
|
||
else {
|
||
printf("Invalid character: %c\n", expression[i]);
|
||
return 0;
|
||
}
|
||
i++;
|
||
}
|
||
else {
|
||
char function[10];
|
||
int j = i; // Запоминаем начальный индекс для функции
|
||
int k = 0;
|
||
while (isalpha(expression[j])) {
|
||
function[k++] = expression[j++];
|
||
}
|
||
function[k] = '\0';
|
||
|
||
if ((configuration == 1) &&
|
||
(strcmp(function, "sin") != 0 && strcmp(function, "cos") != 0 && strcmp(function, "sqrt") != 0 && strcmp(function, "log") != 0 && strcmp(function, "log10") != 0)) {
|
||
printf("Unavailable operation: %s\n", function);
|
||
return 0;
|
||
}
|
||
else if ((configuration == 2)) {
|
||
if (strcmp(function, "sqrt") == 0 || strcmp(function, "sin") == 0 || strcmp(function, "cos") == 0 || strcmp(function, "log") == 0 || strcmp(function, "log10") == 0) {
|
||
push(&operatorStack, expression[i]);
|
||
}
|
||
else {
|
||
printf("Error: %s\n", function);
|
||
return 0;
|
||
}
|
||
i = j; // Перемещаем индекс на символ после функции
|
||
}
|
||
else {
|
||
printf("Invalid character: %c\n", expression[i]);
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
while (operatorStack.top != -1) {
|
||
char op = delet(&operatorStack);
|
||
double b = delet(&operandStack);
|
||
double a = delet(&operandStack);
|
||
push(&operandStack, applyOperator(a, b, op));
|
||
}
|
||
return operandStack.data[operandStack.top];
|
||
} |