From 85be4bac8e8c533d10c4ef17cc3f62241eb67da1 Mon Sep 17 00:00:00 2001 From: Anzhelika Nikolaieva Date: Mon, 5 Feb 2024 23:17:54 +0000 Subject: [PATCH] Add 'sk2/calculator.c' --- sk2/calculator.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 sk2/calculator.c diff --git a/sk2/calculator.c b/sk2/calculator.c new file mode 100644 index 0000000..dd1416e --- /dev/null +++ b/sk2/calculator.c @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#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]; +} \ No newline at end of file