diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9315955 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.associations": { + "*.gcss": "sass", + "*.gohtml": "html", + "stdlib.h": "c", + "opd_stack.h": "c", + "stdio.h": "c" + } +} \ No newline at end of file diff --git a/analyzers/polynomials/stacks/stack/stack.c b/analyzers/polynomials/stacks/stack/stack.c new file mode 100644 index 0000000..2e370b4 --- /dev/null +++ b/analyzers/polynomials/stacks/stack/stack.c @@ -0,0 +1,58 @@ +#include "stack.h" +#include +#include +#include + +void initStack(Stack *s) { + s->top = -1; +} + +bool isEmpty(Stack *s) { + return s->top == -1; +} + +bool isFull(Stack *s) { + return s->top == MAX_STACK_SIZE - 1; +} + +bool push(Stack *s, const char *value, char type) { + if (isFull(s)) { + fprintf(stderr, "Stack overflow!\n"); + return false; + } + char *new_str = malloc(strlen(value) + 1); + if (new_str == NULL) { + fprintf(stderr, "Memory allocation failed!\n"); + return false; + } + strcpy(new_str, value); + s->top++; + s->data[s->top].str_ptr = new_str; + s->data[s->top].type = type; + return true; +} + +bool pop(Stack *s, Element *out) { + if (isEmpty(s)) { + fprintf(stderr, "Stack is empty!\n"); + return false; + } + *out = s->data[s->top--]; + return true; +} + +bool peek(Stack *s, Element *out) { + if (isEmpty(s)) { + fprintf(stderr, "Stack is empty!\n"); + return false; + } + *out = s->data[s->top]; + return true; +} + +void clearStack(Stack *s) { + while (s->top >= 0) { + free(s->data[s->top].str_ptr); + s->top--; + } +} \ No newline at end of file diff --git a/analyzers/polynomials/stacks/stack/stack.h b/analyzers/polynomials/stacks/stack/stack.h new file mode 100644 index 0000000..a500e4c --- /dev/null +++ b/analyzers/polynomials/stacks/stack/stack.h @@ -0,0 +1,43 @@ +#ifndef STACK_H +#define STACK_H + +#include +#include + +#define MAX_STACK_SIZE 100 + +// Структура элемента стека +typedef struct { + char *str_ptr; // Указатель на строку + char type; // Тип операнда +} Element; + +// Структура стека +typedef struct { + Element data[MAX_STACK_SIZE]; // Массив элементов + int top; +} Stack; + +// Инициализация стека +void initStack(Stack *s); + +// Проверка на пустоту +bool isEmpty(Stack *s); + +// Проверка на переполнение +bool isFull(Stack *s); + +// Добавление опаранда в стек (push), +// операндом может быть число или выражение с переменной +bool push(Stack *s, const char *value, char type); + +// Извлечение элемента из стека (pop) +bool pop(Stack *s, Element *out); + +// Просмотр верхнего элемента без извлечения (peek) +bool peek(Stack *s, Element *out); + +// Очистка стека (освобождение памяти) +void clearStack(Stack *s); + +#endif // STACK_H \ No newline at end of file diff --git a/analyzers/polynomials/stacks/stack/stack_test.c b/analyzers/polynomials/stacks/stack/stack_test.c new file mode 100644 index 0000000..fbb70e2 --- /dev/null +++ b/analyzers/polynomials/stacks/stack/stack_test.c @@ -0,0 +1,133 @@ +// калькулятор на основе обратной польской записи + +// gcc stack_test.c stack.c -o stack_test.exe + +#include "stack.h" +#include +#include +#include + +// Тестирование сценария: +// Токен: 2 -> Стек: [2] +// Токен: 2 -> Стек: [2, 2] +// Токен: 10 -> Стек: [2, 2, 10] +// Токен: 3 -> Стек: [2, 2, 10, 3] +// Токен: - -> Берем 3 и 10: 10-3=7 -> Стек: [2, 2, 7] +// Токен: * -> Берем 7 и 2: 2*7=14 -> Стек: [2, 14] +// Токен: x -> Стек: [2, 14, x] +// Токен: 8 -> Стек: [2, 14, x, 8] +// Токен: - -> Берем 8 и x: x-8 -> Стек: [2, 14, (x-8)] +// Токен: * -> Берем (x-8) и 14: 14*(x-8) -> Стек: [2, (14*(x-8))] +// Токен: + -> Берем (14*(x-8)) и 2: 2+(14*(x-8)) -> Стек: [(2+(14*(x-8)))] +// Ответ: (2+(14*(x-8))) + +// P.S. и еще нескольких + +char* calulate(Element* tokens, int tokens_count) { + #define MAX_ELEMENT_STRING_SIZE 100 + Stack s_operands; + initStack(&s_operands); + for (int i = 0; i < tokens_count; ++i) { + Element token = tokens[i]; + if (token.type == 'n' || token.type == 'v') { + // если число или выражение с переменной - добавляю в стек + push(&s_operands, token.str_ptr, token.type); + } else { + // если оператор + char op = token.str_ptr[0]; + + // беру со стека 2 последних операнда + Element second_operand; pop(&s_operands, &second_operand); + Element first_operand; pop(&s_operands, &first_operand); + + char result[MAX_ELEMENT_STRING_SIZE] = { 0 }; + + if (first_operand.type == 'n' && second_operand.type == 'n') { + // оба операнда - числа => вычисляю значение выражения и его закидываю в стек + int first_num = atoi(first_operand.str_ptr); + int second_num = atoi(second_operand.str_ptr); + + switch (op) { + case '+': { + int result_num = first_num + second_num; + //printf("%i + %i = %i\n", first_num, second_num, result_num); + snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num); + push(&s_operands, result, 'n'); + break; + } + case '-': { + int result_num = first_num - second_num; + //printf("%i - %i = %i\n", first_num, second_num, result_num); + snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num); + push(&s_operands, result, 'n'); + break; + } + case '*': { + int result_num = first_num * second_num; + //printf("%i * %i = %i\n", first_num, second_num, result_num); + snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num); + push(&s_operands, result, 'n'); + break; + } + } + } else { + // хотя бы один операнд содержит переменную + + snprintf(result, MAX_ELEMENT_STRING_SIZE, "(%s%c%s)", first_operand.str_ptr, op, second_operand.str_ptr); + //printf("%s %c %s = %s\n", first_operand.str_ptr, op, second_operand.str_ptr, result); + push(&s_operands, result, 'v'); // Помечаю как выражение с переменной + } + + free(first_operand.str_ptr); + free(second_operand.str_ptr); + } + } + + if (!isEmpty(&s_operands)) { + Element result; + pop(&s_operands, &result); + //printf("Result: %s\n", result.str_ptr); + return result.str_ptr; + } + + return NULL; +} + +int main() { + + char* res; + Element tokens[100]; + + tokens[0].str_ptr = "2"; tokens[0].type = 'n'; // number + tokens[1].str_ptr = "2"; tokens[1].type = 'n'; // number + tokens[2].str_ptr = "10"; tokens[2].type = 'n'; // number + tokens[3].str_ptr = "3"; tokens[3].type = 'n'; // number + tokens[4].str_ptr = "-"; tokens[4].type = 'o'; // operator + tokens[5].str_ptr = "*"; tokens[5].type = 'o'; // operator + tokens[6].str_ptr = "x"; tokens[6].type = 'v'; // variable + tokens[7].str_ptr = "8"; tokens[7].type = 'n'; // number + tokens[8].str_ptr = "-"; tokens[8].type = 'o'; // operator + tokens[9].str_ptr = "*"; tokens[9].type = 'o'; // operator + tokens[10].str_ptr = "+"; tokens[10].type = 'o'; // operator + res = calulate(tokens, 11); + printf("Result: %s\n", res); + free(res); + + tokens[0].str_ptr = "2"; tokens[0].type = 'n'; + tokens[1].str_ptr = "2"; tokens[1].type = 'n'; + tokens[2].str_ptr = "+"; tokens[2].type = 'o'; + res = calulate(tokens, 3); + printf("Result: %s\n", res); + free(res); + + tokens[0].str_ptr = "2"; tokens[0].type = 'n'; + tokens[1].str_ptr = "2"; tokens[1].type = 'n'; + tokens[2].str_ptr = "+"; tokens[2].type = 'o'; + tokens[3].str_ptr = "x"; tokens[3].type = 'v'; + tokens[4].str_ptr = "*"; tokens[4].type = 'o'; + res = calulate(tokens, 5); + printf("Result: %s\n", res); + free(res); + + return 0; +} \ No newline at end of file diff --git a/analyzers/polynomials/test.txt b/analyzers/polynomials/test.txt index 23eb0c8..89e26e6 100644 --- a/analyzers/polynomials/test.txt +++ b/analyzers/polynomials/test.txt @@ -1 +1 @@ -2+2*(10-3) \ No newline at end of file +2+2*(10-3)*(x-8) \ No newline at end of file