-
Notifications
You must be signed in to change notification settings - Fork 0
Hm5.1 Сортировочная станция #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # инструкция по сборке | ||
|
|
||
| gcc -c stack.c -o stack.o | ||
|
|
||
| gcc sortStation.c stack.o -o sortStation |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| /** | ||
| * @file SortStation.c | ||
| * @brief Реализация алгоритма Дейкстры для преобразования инфиксной записи в постфиксную | ||
| * | ||
| * Программа преобразует математические выражения из инфиксной формы в постфиксную | ||
| * используя алгоритм "сортировочной станции" Эдсгера Дейкстры. | ||
| */ | ||
|
|
||
| #include "stack.h" | ||
| #include <ctype.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| /** | ||
| * @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 если нет | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Если использовать |
||
| */ | ||
| 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--; // Компенсируем инкремент цикла | ||
|
Comment on lines
+66
to
+71
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не понимаю, зачем отдельно обрабатывать многозначные числа. Кажется, что можно просто добавлять по одной цифре на каждой итерации внешнего цикла. |
||
| } | ||
| // Если открывающая скобка - в стек | ||
| 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]; // Постфиксная запись может быть длиннее | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Как постфиксная запись может быть длиннее, если в инфиксной используются скобки, а в постфиксной -- нет? |
||
|
|
||
| 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; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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]; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| /** | ||
| * @file stack.h | ||
| * @brief Реализация стека для символов и целых чисел | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Зачем нужны две реализации? Используется же только одна (и в другой задаче со стеком, -- в балансе скобок, -- тем более). |
||
| * | ||
| * Модуль предоставляет универсальную реализацию стека, которая может | ||
| * использоваться для различных задач, требующих LIFO-структуры данных. | ||
| */ | ||
|
|
||
| #ifndef STACK_H | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. По стайлгайду, мы не используем include guards. Используйте |
||
| #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 | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ваше решение абсолютно идентично с решением Александры Долженко. И я не преувеличиваю -- отличаются только имена переменных. Посмотрите сами: https://github.com/DolzhenkoAlexa/c_spbu/pull/4/files.
И тут Вам не повезло: Александра до этого ни разу не была замечена за списыванием, а к Вам с Адой всегда были вопросы. Кстати, у Ады решение тоже подозрительно похоже: https://github.com/ada1ra/homework-c/pull/3/files.
И не надо говорить, что это из-за того, что алгоритм один на всех: у остальных решения другие.
Так что Вам с Адой -2 балла за эту задачу.