Add 'sk2/calculator.c'

This commit is contained in:
Anzhelika Nikolaieva 2024-02-05 23:17:54 +00:00
parent e19faa5eca
commit 85be4bac8e

182
sk2/calculator.c Normal file
View File

@ -0,0 +1,182 @@
#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];
}