Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
345bc50
Add stack library header file
NicholayShestakov Oct 14, 2025
4737d32
Add stack library realisation file
NicholayShestakov Oct 14, 2025
405bf4c
Update stack header file commentaries
NicholayShestakov Oct 14, 2025
ce89c99
Update stack realisation file
NicholayShestakov Oct 14, 2025
f4d1e69
Update stack realisation file
NicholayShestakov Oct 20, 2025
d389c7d
Update stack header file
NicholayShestakov Oct 20, 2025
ceeeb02
Update stack header file
NicholayShestakov Oct 21, 2025
f344512
Update stack realisation file
NicholayShestakov Oct 21, 2025
caa1bf9
Update stack header file
NicholayShestakov Oct 21, 2025
0d99e19
Update stack realisation file
NicholayShestakov Oct 21, 2025
8f9bc54
Add sorting station algorithm
NicholayShestakov Oct 22, 2025
851d7c8
Add compile instruction for sorting station
NicholayShestakov Oct 22, 2025
5871294
Update .gitignore with adding ignoring CMake build directory
NicholayShestakov Nov 8, 2025
fd01840
Add CMakeLists.txt for build sorting station
NicholayShestakov Nov 8, 2025
6fe8041
Update instructions how to build
NicholayShestakov Nov 8, 2025
1038190
Update grammary in documentations
NicholayShestakov Dec 11, 2025
74218cf
Update stack realization
NicholayShestakov Dec 11, 2025
60792cf
Update stack header documentation
NicholayShestakov Dec 11, 2025
46eac81
Add build instruction in README
NicholayShestakov Dec 11, 2025
2a35f61
Delete build instruction from stack folder
NicholayShestakov Dec 11, 2025
8646f0d
Update sorting station
NicholayShestakov Dec 11, 2025
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,7 @@ Module.symvers
Mkfile.old
dkms.conf

# CMake
build

# End of https://www.toptal.com/developers/gitignore/api/c
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.25)
project(sorting_station C)

add_library(stack src/stack_and_queue/stack/stack.c)

add_executable(sorting_station src/stack_and_queue/stack/sorting_station.c)
target_link_libraries(sorting_station PRIVATE stack)
target_compile_options(sorting_station PRIVATE -Wall -Wextra -pedantic)
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@
Основная почта: nicholas.shestakov@gmail.com

Телеграм: @Kolya_shesterka

## Инструкции по сборке:
```console
$ cmake . -B build
$ cmake --build build
```
156 changes: 156 additions & 0 deletions src/stack_and_queue/stack/sorting_station.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#include "stack.h"
#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

bool isOperatorFirstPriority(char c)
{
return c == '*' || c == '/';
}

bool isOperatorSecondPriority(char c)
{
return c == '+' || c == '-';
}

// Takes infix form of expression as string and returns pointer to postfix form string. Please, dont forget free memory.
// Can track unbalanced brackets and correctness of order of numbers and operators. Cant track extraneous symbols.
// If the error is tracked, returns pointer to the string with the error description.
char* sortingStation(char* infixForm)
{
char* output = calloc(2 * strlen(infixForm), sizeof(output));
Stack* operators = newStack();

bool isNumberTurn = true; // For check correctness of order.
char* errorMessage = calloc(64, sizeof(*errorMessage)); // For error returns.
int indexOfOutput = 0;
for (int indexOfInfix = 0; infixForm[indexOfInfix] != '\0'; ++indexOfInfix) {
if (isdigit(infixForm[indexOfInfix])) {
if (!isNumberTurn) {
strcat(errorMessage, "Error! Order of numbers and operators is incorrect.");
}
isNumberTurn = !isNumberTurn;

output[indexOfOutput] = infixForm[indexOfInfix];
output[indexOfOutput + 1] = ' ';
indexOfOutput += 2;
}
if (isOperatorFirstPriority(infixForm[indexOfInfix])) {
if (isNumberTurn) {
strcat(errorMessage, "Error! Order of numbers and operators is incorrect.");
}
isNumberTurn = !isNumberTurn;

push(operators, infixForm[indexOfInfix]);
}
if (isOperatorSecondPriority(infixForm[indexOfInfix])) {
if (isNumberTurn) {
strcat(errorMessage, "Error! Order of numbers and operators is incorrect.");
}
isNumberTurn = !isNumberTurn;

while (!isEmpty(operators) && peek(operators) != '(') {
output[indexOfOutput++] = pop(operators);
output[indexOfOutput++] = ' ';
}
push(operators, infixForm[indexOfInfix]);
}
if (infixForm[indexOfInfix] == '(') {
if (!isNumberTurn) {
strcat(errorMessage, "Error! Number before opening bracket.");
}

push(operators, infixForm[indexOfInfix]);
}
// Многоступенчатость в целях предотвращения одновременного добавления сразу нескольких сообщений об ошибке.
if (infixForm[indexOfInfix] == ')') {
if (isEmpty(operators)) {
strcat(errorMessage, "Error! Brackets not opened.");
} else {
if (isNumberTurn) {
strcat(errorMessage, "Error! Operator before closing bracket.");
} else {
while (peek(operators) != '(') {
output[indexOfOutput++] = pop(operators);
output[indexOfOutput++] = ' ';

if (isEmpty(operators)) {
strcat(errorMessage, "Error! Brackets not opened.");
break;
}
}
if (!isEmpty(operators)) {
pop(operators);
}
}
}
}

// Данное условие истинно, когда строки не равны.
if (strcmp(errorMessage, "")) {
free(output);
deleteStack(operators);
return errorMessage;
}
}

while (!isEmpty(operators)) {
output[indexOfOutput++] = pop(operators);
output[indexOfOutput++] = ' ';

if (output[indexOfOutput - 2] == '(') {
free(output);
deleteStack(operators);
strcat(errorMessage, "Error! Brackets not closed.");
return errorMessage;
}
}

deleteStack(operators);
return output;
}

int main()
{
char* testSimple = sortingStation("(1 + (4 + 5 / 2) - 3) + (6 + 8)");
char* testNoSpaces = sortingStation("4/2+6");
char* testManyBrackets = sortingStation("((((1))))");
char* testOnlyNumber = sortingStation("1");
char* testEmpty = sortingStation("");
char* testIncorrectOrder = sortingStation("1 + + 1");
char* testIncorrectOrder2 = sortingStation("+ 1");
char* testNumberBeforeBracket = sortingStation("1 (+ 3)");
char* testOperatorBeforeBracket = sortingStation("1 + (2 + ) 3");
char* testBracketsNotOpened = sortingStation("1 + 2)");
char* testBracketsNotClosed = sortingStation("1 + (2 + 3");

assert(!strcmp(testSimple, "1 4 5 2 / + + 3 - 6 8 + + ") && "testSimple incorrect.");
assert(!strcmp(testNoSpaces, "4 2 / 6 + ") && "testNoSpaces incorrect.");
assert(!strcmp(testManyBrackets, "1 ") && "testManyBrackets incorrect.");
assert(!strcmp(testOnlyNumber, "1 ") && "testOnlyNumber incorrect.");
assert(!strcmp(testEmpty, "") && "testEmpty incorrect.");
assert(!strcmp(testIncorrectOrder, "Error! Order of numbers and operators is incorrect.") && "testIncorrectOrder incorrect.");
assert(!strcmp(testIncorrectOrder2, "Error! Order of numbers and operators is incorrect.") && "testIncorrectOrder2 incorrect.");
assert(!strcmp(testNumberBeforeBracket, "Error! Number before opening bracket.") && "testNumberBeforeBracket incorrect.");
assert(!strcmp(testOperatorBeforeBracket, "Error! Operator before closing bracket.") && "testOperatorBeforeBracket incorrect.");
assert(!strcmp(testBracketsNotOpened, "Error! Brackets not opened.") && "testBracketsNotOpened incorrect.");
assert(!strcmp(testBracketsNotClosed, "Error! Brackets not closed.") && "testBracketsNotClosed incorrect.");

printf("All tests passed successfully.\n");

free(testSimple);
free(testNoSpaces);
free(testManyBrackets);
free(testOnlyNumber);
free(testEmpty);
free(testIncorrectOrder);
free(testIncorrectOrder2);
free(testNumberBeforeBracket);
free(testOperatorBeforeBracket);
free(testBracketsNotOpened);
free(testBracketsNotClosed);
return 0;
}
60 changes: 60 additions & 0 deletions src/stack_and_queue/stack/stack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "stack.h"

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct StackNode {
int value;
struct StackNode* next;
} StackNode;

struct Stack {
StackNode* head;
};

Stack* newStack()
{
Stack* stack = calloc(1, sizeof(*stack));
assert(stack != NULL && "Error! Memory allocated incorrect.");
return stack;
}

void deleteStack(Stack* stack)
{
while (!isEmpty(stack)) {
pop(stack);
}
free(stack);
}

void push(Stack* stack, int value)
{
StackNode* newNode = malloc(sizeof(*newNode));
assert(newNode != NULL && "Error! Memory allocated incorrect.");
newNode->value = value;
newNode->next = stack->head;
stack->head = newNode;
}

int pop(Stack* stack)
{
assert(!isEmpty(stack) && "Error! Stack is empty. Can`t pop value.");
StackNode* poppedNode = stack->head;
int value = poppedNode->value;
stack->head = poppedNode->next;
free(poppedNode);
return value;
}

int peek(Stack* stack)
{
assert(!isEmpty(stack) && "Error! Stack is empty. Can`t peek value.");
return stack->head->value;
}

bool isEmpty(Stack* stack)
{
return stack->head == NULL;
}
33 changes: 33 additions & 0 deletions src/stack_and_queue/stack/stack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <stdbool.h>

typedef struct Stack Stack;

// Creates new stack.
// Returns pointer to the created stack.
Stack* newStack();

// Deletes stack. Frees all memory used in it.
// Takes pointer to the stack.
void deleteStack(Stack* stack);

// Pushes new value on the top of the stack.
// Takes pointer to the stack and value for push.
void push(Stack* stack, int value);

// Deletes the top value of the stack and returns it. Frees memory used for top node.
// Takes pointer to the stack.
// Don`t use if the stack is empty. It causes the error.
// Check this with isEmpty before use this function.
int pop(Stack* stack);

// Returns the top value of the stack.
// Takes pointer to the stack.
// Don`t use if the stack is empty. It causes the error.
// Check this with isEmpty before use this function.
int peek(Stack* stack);

// Returns true if the stack is empty and false if not.
// Takes pointer to the stack.
bool isEmpty(Stack* stack);