diff --git a/src/homework5.1_16.10_sortStation/instruction.md b/src/homework5.1_16.10_sortStation/instruction.md new file mode 100644 index 0000000..90840c2 --- /dev/null +++ b/src/homework5.1_16.10_sortStation/instruction.md @@ -0,0 +1,5 @@ +# инструкция по сборке + +gcc -c stack.c -o stack.o + +gcc sortStation.c stack.o -o sortStation diff --git a/src/homework5.1_16.10_sortStation/sortStation.c b/src/homework5.1_16.10_sortStation/sortStation.c new file mode 100644 index 0000000..a9a9e77 --- /dev/null +++ b/src/homework5.1_16.10_sortStation/sortStation.c @@ -0,0 +1,160 @@ +/** + * @file SortStation.c + * @brief Реализация алгоритма Дейкстры для преобразования инфиксной записи в постфиксную + * + * Программа преобразует математические выражения из инфиксной формы в постфиксную + * используя алгоритм "сортировочной станции" Эдсгера Дейкстры. + */ + +#include "stack.h" +#include +#include +#include +#include + +/** + * @brief Определение приоритета оператора + * @param operatorChar Символ оператора + * @return Числовой приоритет (чем выше число, тем выше приоритет) + */ +int GetOperatorPriority(char operatorChar) +{ + switch (operatorChar) { + case '+': + case '-': + return 1; + case '*': + case '/': + return 2; + default: + return 0; + } +} + +/** + * @brief Проверка, является ли символ оператором + * @param character Проверяемый символ + * @return 1 если оператор, 0 если нет + */ +int IsOperator(char character) +{ + return character == '+' || character == '-' || character == '*' || character == '/'; +} + +/** + * @brief Преобразование инфиксного выражения в постфиксное + * @param infixExpression Входная строка в инфиксной записи + * @param postfixExpression Выходной буфер для постфиксной записи + * @return 1 если преобразование успешно, 0 если ошибка + */ +int ConvertInfixToPostfix(const char* infixExpression, char* postfixExpression) +{ + CharStack operatorStack; + CharStackInit(&operatorStack); + int outputIndex = 0; + + for (int inputIndex = 0; infixExpression[inputIndex] != '\0'; inputIndex++) { + char currentChar = infixExpression[inputIndex]; + + // Пропускаем пробелы + if (currentChar == ' ') { + continue; + } + + // Если цифра - добавляем в выход + if (isdigit(currentChar)) { + // Обрабатываем многозначные числа + while (isdigit(infixExpression[inputIndex]) || infixExpression[inputIndex] == '.') { + postfixExpression[outputIndex++] = infixExpression[inputIndex++]; + } + postfixExpression[outputIndex++] = ' '; + inputIndex--; // Компенсируем инкремент цикла + } + // Если открывающая скобка - в стек + else if (currentChar == '(') { + if (!CharStackPush(&operatorStack, currentChar)) { + return 0; // Переполнение стека + } + } + // Если закрывающая скобка + else if (currentChar == ')') { + // Выталкиваем операторы до открывающей скобки + while (!CharStackIsEmpty(&operatorStack) && CharStackPeek(&operatorStack) != '(') { + postfixExpression[outputIndex++] = CharStackPop(&operatorStack); + postfixExpression[outputIndex++] = ' '; + } + // Удаляем открывающую скобку + if (!CharStackIsEmpty(&operatorStack) && CharStackPeek(&operatorStack) == '(') { + CharStackPop(&operatorStack); + } else { + return 0; // Несбалансированные скобки + } + } + // Если оператор + else if (IsOperator(currentChar)) { + // Выталкиваем операторы с высшим или равным приоритетом + while (!CharStackIsEmpty(&operatorStack) && IsOperator(CharStackPeek(&operatorStack)) && GetOperatorPriority(CharStackPeek(&operatorStack)) >= GetOperatorPriority(currentChar)) { + postfixExpression[outputIndex++] = CharStackPop(&operatorStack); + postfixExpression[outputIndex++] = ' '; + } + // Помещаем текущий оператор в стек + if (!CharStackPush(&operatorStack, currentChar)) { + return 0; // Переполнение стека + } + } + } + + // Выталкиваем оставшиеся операторы из стека + while (!CharStackIsEmpty(&operatorStack)) { + char operatorChar = CharStackPop(&operatorStack); + if (operatorChar == '(') { + return 0; // Несбалансированные скобки + } + postfixExpression[outputIndex++] = operatorChar; + postfixExpression[outputIndex++] = ' '; + } + + postfixExpression[outputIndex] = '\0'; + return 1; +} + +/** + * @brief Главная функция программы + */ +int main() +{ + char infixInput[STACK_SIZE]; + char postfixOutput[STACK_SIZE * 2]; // Постфиксная запись может быть длиннее + + printf("АЛГОРИТМ ДЕЙКСТРЫ: ПРЕОБРАЗОВАНИЕ ИЗ ИНФИКСНОЙ ФОРМЫ В ПОСТФИКСНУЮ\n"); + printf("Поддерживаются: числа, операторы + - * /, скобки ( )\n"); + printf("Для выхода введите 'exit'\n\n"); + + while (1) { + printf("Введите инфиксное выражение: "); + + if (fgets(infixInput, sizeof(infixInput), stdin) == NULL) { + break; + } + + infixInput[strcspn(infixInput, "\n")] = 0; + + if (strcmp(infixInput, "exit") == 0) { + break; + } + + if (strlen(infixInput) == 0) { + continue; + } + + if (ConvertInfixToPostfix(infixInput, postfixOutput)) { + printf("Инфикс: %s\n", infixInput); + printf("Постфикс: %s\n\n", postfixOutput); + } else { + printf("Ошибка: некорректное выражение\n\n"); + } + } + + printf("Выход из программы.\n"); + return 0; +} diff --git a/src/stackMod/stack.c b/src/stackMod/stack.c new file mode 100644 index 0000000..6ce044d --- /dev/null +++ b/src/stackMod/stack.c @@ -0,0 +1,74 @@ +/** + *@file stack.c + * @brief Реализация функций стека + */ + +#include "stack.h" + +void CharStackInit(CharStack* stack) { + stack->top = -1; +} + +void IntStackInit(IntStack* stack) { + stack->top = -1; +} + +int CharStackIsEmpty(const CharStack* stack) { + return stack->top == -1; +} + +int IntStackIsEmpty(const IntStack* stack) { + return stack->top == -1; +} + +int CharStackIsFull(const CharStack* stack) { + return stack->top == STACK_SIZE - 1; +} + +int IntStackIsFull(const IntStack* stack) { + return stack->top == STACK_SIZE - 1; +} + +int CharStackPush(CharStack* stack, char value) { + if (CharStackIsFull(stack)) { + return 0; + } + stack->data[++(stack->top)] = value; + return 1; +} + +int IntStackPush(IntStack* stack, int value) { + if (IntStackIsFull(stack)) { + return 0; + } + stack->data[++(stack->top)] = value; + return 1; +} + +char CharStackPop(CharStack* stack) { + if (CharStackIsEmpty(stack)) { + return '\0'; + } + return stack->data[(stack->top)--]; +} + +int IntStackPop(IntStack* stack) { + if (IntStackIsEmpty(stack)) { + return 0; + } + return stack->data[(stack->top)--]; +} + +char CharStackPeek(const CharStack* stack) { + if (CharStackIsEmpty(stack)) { + return '\0'; + } + return stack->data[stack->top]; +} + +int IntStackPeek(const IntStack* stack) { + if (IntStackIsEmpty(stack)) { + return 0; + } + return stack->data[stack->top]; +} diff --git a/src/stackMod/stack.h b/src/stackMod/stack.h new file mode 100644 index 0000000..c203431 --- /dev/null +++ b/src/stackMod/stack.h @@ -0,0 +1,114 @@ +/** + * @file stack.h + * @brief Реализация стека для символов и целых чисел + * + * Модуль предоставляет универсальную реализацию стека, которая может + * использоваться для различных задач, требующих LIFO-структуры данных. + */ + +#ifndef STACK_H +#define STACK_H + +#define STACK_SIZE 100 + +/** + * @brief Структура стека для символов + */ +typedef struct { + char data[STACK_SIZE]; // Массив для хранения элементов стека + int top; // Индекс вершины стека (-1 если пуст) +} CharStack; + +/** + * @brief Структура стека для целых чисел + */ +typedef struct { + int data[STACK_SIZE]; // Массив для хранения элементов стека + int top; // Индекс вершины стека (-1 если пуст) +} IntStack; + +/** + * @brief Инициализация стека символов + * @param stack Указатель на стек для инициализации + */ +void CharStackInit(CharStack* stack); + +/** + * @brief Инициализация стека целых чисел + * @param stack Указатель на стек для инициализации + */ +void IntStackInit(IntStack* stack); + +/** + * @brief Проверка стека символов на пустоту + * @param stack Указатель на стек + * @return 1 если стек пуст, 0 если нет + */ +int CharStackIsEmpty(const CharStack* stack); + +/** + * @brief Проверка стека целых чисел на пустоту + * @param stack Указатель на стек + * @return 1 если стек пуст, 0 если нет + */ +int IntStackIsEmpty(const IntStack* stack); + +/** + * @brief Проверка стека символов на переполнение + * @param stack Указатель на стек + * @return 1 если стек полон, 0 если нет + */ +int CharStackIsFull(const CharStack* stack); + +/** + * @brief Проверка стека целых чисел на переполнение + * @param stack Указатель на стек + * @return 1 если стек полон, 0 если нет + */ +int IntStackIsFull(const IntStack* stack); + +/** + * @brief Добавление элемента в стек символов + * @param stack Указатель на стек + * @param value Символ для добавления + * @return 1 если успешно, 0 если стек полон + */ +int CharStackPush(CharStack* stack, char value); + +/** + * @brief Добавление элемента в стек целых чисел + * @param stack Указатель на стек + * @param value Число для добавления + * @return 1 если успешно, 0 если стек полон + */ +int IntStackPush(IntStack* stack, int value); + +/** + * @brief Извлечение элемента из стека символов + * @param stack Указатель на стек + * @return Извлеченный символ или '\0' если стек пуст + */ +char CharStackPop(CharStack* stack); + +/** + * @brief Извлечение элемента из стека целых чисел + * @param stack Указатель на стек + * @return Извлеченное число или 0 если стек пуст + */ +int IntStackPop(IntStack* stack); + +/** + * @brief Просмотр верхнего элемента стека символов без извлечения + * @param stack Указатель на стек + * @return Верхний символ или '\0' если стек пуст + */ +char CharStackPeek(const CharStack* stack); + +/** + * @brief Просмотр верхнего элемента стека целых чисел без извлечения + * @param stack Указатель на стек + * @return Верхнее число или 0 если стек пуст + */ +int IntStackPeek(const IntStack* stack); + +#endif // STACK_H