usaa23/sk2/calculator.c

182 lines
6.5 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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];
}