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
13 changes: 13 additions & 0 deletions src/hw5_stack/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 4.0)
project(hw5_stack C)

set(CMAKE_C_STANDARD 17)

add_executable(sortingStation
sortingStation.c
stack.c
)

if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(hw5_stack PRIVATE -Wall -Wextra -Wpedantic)
endif()
109 changes: 109 additions & 0 deletions src/hw5_stack/sortingStation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "sortingStation.h"

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "stack.h"

// Проверяем является ли данный нам символ знаком операции (умножения/деления/сложения/вычитания)
int isOperator(char currElem) {
return currElem == '+' || currElem == '-' || currElem == '*' || currElem == '/';
}

// Проверяем приоритет данного нам знака (по мат законам у деления/умножения он выше чем у сложения/вычитания)
int priority(char currElem) {
if (currElem == '+' || currElem == '-') {
return 1;
}
if (currElem == '*' || currElem == '/') {
return 2;
}
return 0;
}


// Само преобразованиие Дейкстры
void toPostfix(char infix[], char postfix[]) {
Stack stack;
init_stack(&stack);
int postfix_index = 0;

for (int i = 0; infix[i] != '\0'; i++) {
char currElem = infix[i];

// Пропускаем пробелы
if (currElem == ' ') {
continue;
}

// Если цифра - добавляем в массив postfix, так как числа идут первыми, а потом операции
if (isdigit(currElem)) {
postfix[postfix_index++] = currElem; // Добавляем число в следующий индекс массива
postfix[postfix_index++] = ' '; // Делаем пробелы между символами, чтоб не слипалось
}

// Если открывающая скобка, то в стек
else if (currElem == '(') {
push(&stack, currElem);
}

// Закрывающая скобка завершает выражение в скобках.
// Вынимаем из стека все операции пока не найдем открывающую скобку
else if (currElem == ')') {
while (!StackEmptiness(&stack)) {
char operator = pop(&stack);
if (operator == '(') {
break;
}
postfix[postfix_index++] = operator;
postfix[postfix_index++] = ' ';
}
}
// Если операция
else if (isOperator(currElem)) {
// Вынимаем операторы с более высоким или равным приоритетом, так как надо чтобы в выражениях, где важен порядок, они выполнялись быстрее
while (!StackEmptiness(&stack)) {
char lastOperator = stack.elements[stack.topIndex];
if (lastOperator == '(') { // Останавливаем, если встречаем открывающую скобку
break;
}
if (priority(lastOperator) >= priority(currElem)) { // Сравниваем приоритетность операторов
// Оператор из стека имеет высший или равный приоритет - вынимаем его
pop(&stack);
postfix[postfix_index++] = lastOperator;
postfix[postfix_index++] = ' ';
} else {
// Оператор из стека имеет низший - останаваливаем вынимание
break;
}
}
// Кладем текущий оператор в стек
push(&stack, currElem);
}
}

// Вынимаем все оставшиеся символы операций из стека
while (!StackEmptiness(&stack)) {
char lastOperator = pop(&stack);
postfix[postfix_index++] = lastOperator;
postfix[postfix_index++] = ' ';
}
}

int main() {
char infix[500];
char postfix[500];

printf("Введите выражение со скобками, цифрами и операторами ");
fgets(infix, sizeof(infix), stdin);


infix[strlen(infix) - 1] = '\0';

toPostfix(infix, postfix);

printf("Инфиксная форма: %s\n", infix);
printf("Постфиксная форма: %s\n", postfix);

return 0;
}
36 changes: 36 additions & 0 deletions src/hw5_stack/sortingStation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Description: Этот модуль предоставляет функции для преобразования
// математических выражений из инфиксной формы в постфиксную (обратную польскую запись)
// с использованием алгоритма "сортировочной станции" Э. Дейкстры.
// Поддерживает операции: +, -, *, /, скобки () и цифры.
//

#pragma once

//
// Проверяет является ли символ оператором
// Параметр: currElem - символ для проверки
// Возвращает: 1 если оператор, 0 если нет
//
int isOperator(char currElem);

//
// Определяет приоритет оператора
// Параметр: currElem - оператор
// Возвращает: 2 для * /, 1 для + -, 0 для других символов
//
int priority(char currElem);

//
// Преобразует инфиксное выражение в постфиксное
// Параметры:
// infix - входное инфиксное выражение
// postfix - выходной буфер для постфиксного выражения
//
// Алгоритм:
// 1. Числа сразу добавляются в выходной массив
// 2. Открывающие скобки помещаются в стек
// 3. Закрывающие скобки выталкивают операторы из стека до открывающей скобки
// 4. Операторы выталкивают из стека операторы с высшим или равным приоритетом
// 5. В конце все оставшиеся операторы выталкиваются из стека
//
void toPostfix(char infix[], char postfix[]);
31 changes: 31 additions & 0 deletions src/hw5_stack/stack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "stack.h"

// Создаем стэк, делая значение top равным -1 ("нет элементов")
void init_stack(Stack *stack) {
stack->topIndex = -1;
}

// Добавляем элемент
void push(Stack *stack, char value) {
stack->topIndex++; // Увеличиваем индекс на 1
stack->elements[stack->topIndex] = value; // Добавляем сам элемент в массив
}

// Берем верхний элемент и удаляем его
char pop(Stack *stack) {
if (StackEmptiness(stack)) { // Проверяем не пуст ли стек
return '\0'; // Возвращаем '\0' если пуст (в таком виде, потому что нужно вернуть char)
}
char value = stack->elements[stack->topIndex]; // Сохраняем верхний элемент
stack->topIndex--; // Уменьшаем индекс
return value; // Возвращаем сохраненный элемент
}

// Проверяем пуст ли стек (Чтоб не убрать "пустоту")
int StackEmptiness(Stack *stack) {
if (stack->topIndex == -1) {
return 1; // 1 - стек пуст
} else {
return 0; // 0 - стек не пуст
}
}
41 changes: 41 additions & 0 deletions src/hw5_stack/stack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Description: Этот модуль предоставляет функции для работы со стеком:
// создание стэка (init_stack), добавление (push), извлечение элементов (pop) и проверка на пустоту (is_empty).
// Нужен для двух задач: Продвинутый баланс скобок и Сортировочная станция
//
#pragma once
#define STACK_SIZE 512

//
// Структура для стека
// В ней создаем char массив для хранения элементов длины STACK_SIZE и переменную для хранения индекса верхнего элемента
//
typedef struct {
char elements[STACK_SIZE]; // массив для хранения
int topIndex; // индекс верхнего элемента
} Stack;

//
// Создание стека
// В качестве параметра берем указатель на стек (для изменения самого стека, а не только копии)
//
void init_stack(Stack *stack);

//
// Добавление элемента в стек
// Параметр - Указатель на стек и значение элемента для добавления
//
void push(Stack *stack, char value);

//
// Удаление элемента из стека с проверкой на пустоту
// Параметр - Указатель на стек
// Вернет значение элемента, если есть что удалять, и 0 если нет
//
char pop(Stack *stack);

//
// Проверка стэка на пустоту
// Параметр - Указатель на стек
// Вернет 1 если стек пуст, 0 если нет
//
int is_empty(Stack *stack);