Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/homework5.1_16.10_sortStation/instruction.md
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
160 changes: 160 additions & 0 deletions src/homework5.1_16.10_sortStation/sortStation.c
Copy link
Collaborator

@p-senichenkov p-senichenkov Dec 8, 2025

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 балла за эту задачу.

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 если нет
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если использовать bool, то не придётся везде писать "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--; // Компенсируем инкремент цикла
Comment on lines +66 to +71
Copy link
Collaborator

Choose a reason for hiding this comment

The 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]; // Постфиксная запись может быть длиннее
Copy link
Collaborator

Choose a reason for hiding this comment

The 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;
}
74 changes: 74 additions & 0 deletions src/stackMod/stack.c
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];
}
114 changes: 114 additions & 0 deletions src/stackMod/stack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* @file stack.h
* @brief Реализация стека для символов и целых чисел
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем нужны две реализации? Используется же только одна (и в другой задаче со стеком, -- в балансе скобок, -- тем более).

*
* Модуль предоставляет универсальную реализацию стека, которая может
* использоваться для различных задач, требующих LIFO-структуры данных.
*/

#ifndef STACK_H
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

По стайлгайду, мы не используем include guards. Используйте pragma once.

#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