Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5851423
Homework 5 - Added stack
ilya-krivtsov Oct 18, 2024
7d6d6c3
Homework 5 task 1
ilya-krivtsov Oct 18, 2024
8147ea2
Added stdlib include
ilya-krivtsov Oct 18, 2024
86cb5fd
Removed trailing space
ilya-krivtsov Oct 21, 2024
7b9951f
Merge branch 'hw-5' into hw-5-task-1
ilya-krivtsov Oct 21, 2024
5d2768f
Removed another trailing space
ilya-krivtsov Oct 21, 2024
c256a46
Merge branch 'hw-5' into hw-5-task-1
ilya-krivtsov Oct 21, 2024
ada080b
Dispose stack properly
ilya-krivtsov Oct 22, 2024
b3c3e96
Merge branch 'hw-5' into hw-5-task-1
ilya-krivtsov Oct 22, 2024
1cb961c
Merge branch 'build-system' into hw-5-task-1
ilya-krivtsov Nov 7, 2024
4e28ac4
Merge branch 'build-system' into hw-5-task-1
ilya-krivtsov Nov 7, 2024
16a9027
Merge branch 'main' into hw-5-task-1
ilya-krivtsov Nov 20, 2024
f6e5b74
Merge branch 'main' into hw-5-task-1
ilya-krivtsov Nov 25, 2024
e17b3fb
Merge branch 'main' into hw-5
ilya-krivtsov Nov 29, 2024
14c776d
Merge branch 'main' into hw-5
ilya-krivtsov Nov 29, 2024
9953182
Merge branch 'hw-5' into hw-5-task-1
ilya-krivtsov Nov 29, 2024
6a8ac65
Pass buffer as parameter to scanf (hw5 task 1)
ilya-krivtsov Nov 29, 2024
ee01c84
Removed 'PRIVATE' dependency modifier (hw5 - stack)
ilya-krivtsov Dec 10, 2024
826dbdc
Merge branch 'hw-5' into hw-5-task-1
ilya-krivtsov Dec 10, 2024
703b7f2
Added stdbool.h include (hw5 task 1)
ilya-krivtsov Dec 10, 2024
ae2d49b
Added README (hw 5)
ilya-krivtsov Dec 22, 2024
c1fba04
Merge branch 'hw-5' into hw-5-task-1
ilya-krivtsov Dec 22, 2024
cf073ec
Added task name to README (hw5 task 1)
ilya-krivtsov Dec 22, 2024
b44cac8
Merge branch 'main' into hw-5-task-1
ilya-krivtsov Dec 22, 2024
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ add_compile_options(-Wall -Wextra)
add_subdirectory(homework_2)
add_subdirectory(homework_3)
add_subdirectory(homework_4)
add_subdirectory(homework_5)
7 changes: 7 additions & 0 deletions homework_5/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
project(homework_5)

set(homeworkName "${PROJECT_NAME}")

add_subdirectory(stack)

add_subdirectory(task_1)
3 changes: 3 additions & 0 deletions homework_5/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Homework 5

[Task 1. Advanced brackets balance](/homework_5/task_1)
6 changes: 6 additions & 0 deletions homework_5/stack/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
project("${homeworkName}_stack")

add_library(stack stack.c)

add_executable(${PROJECT_NAME}_test test.c)
target_link_libraries(${PROJECT_NAME}_test stack)
84 changes: 84 additions & 0 deletions homework_5/stack/stack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "stack.h"

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct Node {
uint64_t value;
struct Node *previous;
} Node;

typedef struct Stack {
Node *head;
} Stack;

static void removeLastNode(Stack *stack) {
Node *prev = stack->head;
stack->head = stack->head->previous;
free(prev);
}

bool stackCreate(Stack **stack) {
*stack = malloc(sizeof(Stack));
if (*stack == NULL) {
return false;
}

(*stack)->head = NULL;

return true;
}

bool stackPush(Stack *stack, uint64_t value) {
Node *node = malloc(sizeof(Node));
if (node == NULL) {
return false;
}

if (stackIsEmpty(stack)) {
node->previous = NULL;
} else {
node->previous = stack->head;
}

node->value = value;
stack->head = node;

return true;
}


bool stackTryPop(Stack *stack, uint64_t *value) {
if (stackIsEmpty(stack)) {
return false;
}

*value = stack->head->value;

removeLastNode(stack);

return true;
}

bool stackTryPeek(Stack *stack, uint64_t *value) {
if (stackIsEmpty(stack)) {
return false;
}

*value = stack->head->value;

return true;
}

bool stackIsEmpty(Stack *stack) {
return stack->head == NULL;
}

void stackDispose(Stack *stack) {
while (!stackIsEmpty(stack)) {
removeLastNode(stack);
}

free(stack);
}
38 changes: 38 additions & 0 deletions homework_5/stack/stack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include <stdbool.h>
#include <stdint.h>

/// @brief Stack that stores all of its elements as `uint64_t`
typedef struct Stack Stack;

/// @brief Creates `Stack`
/// @param stack Pointer to store created `Stack` to
/// @return `true` if successful, `false` otherwise (allocation failed)
bool stackCreate(Stack **stack);

/// @brief Pushes value on top of the stack
/// @param stack Pointer to `Stack` instance
/// @return `true` if successful, `false` otherwise (allocation failed)
bool stackPush(Stack *stack, uint64_t value);

/// @brief Pops value from the top of the stack
/// @param stack Pointer to `Stack` instance
/// @param value Pointer to write value to
/// @return `true` if stack was non-empty, `false` otherwise
bool stackTryPop(Stack *stack, uint64_t *value);

/// @brief Returns value from the top of the stack without removing it
/// @param stack Pointer to `Stack` instance
/// @param value Pointer to write value to
/// @return `true` if stack was non-empty, `false` otherwise
bool stackTryPeek(Stack *stack, uint64_t *value);

/// @brief Checks if stack is empty
/// @param stack Pointer to `Stack` instance
/// @return `true` if stack is empty, `false` otherwise
bool stackIsEmpty(Stack *stack);

/// @brief Disposes stack and all of its elements
/// @param stack `Stack` to dispose
void stackDispose(Stack *stack);
147 changes: 147 additions & 0 deletions homework_5/stack/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#define CTEST_MAIN
#define CTEST_SEGFAULT
#include "../../ctest/ctest.h"

#include <stdint.h>

#include "stack.h"

int main(int argc, const char *argv[]) {
return ctest_main(argc, argv);
}

#pragma region Helpers

Stack *createStack(void) {
Stack *stack;
ASSERT_TRUE(stackCreate(&stack));
ASSERT_NOT_NULL(stack);

return stack;
}

void assertPop(Stack *stack, uint64_t value) {
uint64_t top = 0;
ASSERT_TRUE(stackTryPop(stack, &top));
ASSERT_EQUAL_U(value, top);
}

void assertPeek(Stack *stack, uint64_t value) {
uint64_t top = 0;
ASSERT_TRUE(stackTryPeek(stack, &top));
ASSERT_EQUAL_U(value, top);
}

#pragma endregion

CTEST(stackTests, createTest) {
Stack *stack = createStack();
ASSERT_TRUE(stackIsEmpty(stack));
stackDispose(stack);
}

#pragma region Push & Pop

CTEST(stackTests, pushPopTestA) {
Stack *stack = createStack();

ASSERT_TRUE(stackPush(stack, 0));
assertPop(stack, 0);

ASSERT_TRUE(stackIsEmpty(stack));

stackDispose(stack);
}

CTEST(stackTests, pushPopTestB) {
Stack *stack = createStack();

ASSERT_TRUE(stackPush(stack, 0));
assertPop(stack, 0);
ASSERT_TRUE(stackIsEmpty(stack));

ASSERT_TRUE(stackPush(stack, 47));
assertPop(stack, 47);
ASSERT_TRUE(stackIsEmpty(stack));

ASSERT_TRUE(stackPush(stack, 1245));
ASSERT_TRUE(stackPush(stack, 44362));
assertPop(stack, 44362);
assertPop(stack, 1245);
ASSERT_TRUE(stackIsEmpty(stack));

stackDispose(stack);
}

CTEST(stackTests, pushPopTestC) {
Stack *stack = createStack();

ASSERT_TRUE(stackPush(stack, 2352));
ASSERT_TRUE(stackPush(stack, 43634));
assertPop(stack, 43634);
ASSERT_FALSE(stackIsEmpty(stack));

ASSERT_TRUE(stackPush(stack, 9999));
ASSERT_TRUE(stackPush(stack, 7777777));
assertPop(stack, 7777777);
assertPop(stack, 9999);
assertPop(stack, 2352);
ASSERT_TRUE(stackIsEmpty(stack));

stackDispose(stack);
}

#pragma endregion

#pragma region Push & Peek

CTEST(stackTests, pushPeekTestA) {
Stack *stack = createStack();

ASSERT_TRUE(stackPush(stack, 0));
assertPeek(stack, 0);

ASSERT_FALSE(stackIsEmpty(stack));

stackDispose(stack);
}

CTEST(stackTests, pushPeekTestB) {
Stack *stack = createStack();

ASSERT_TRUE(stackPush(stack, 0));
assertPeek(stack, 0);
ASSERT_FALSE(stackIsEmpty(stack));

ASSERT_TRUE(stackPush(stack, 47));
assertPeek(stack, 47);
ASSERT_FALSE(stackIsEmpty(stack));

ASSERT_TRUE(stackPush(stack, 1245));
ASSERT_TRUE(stackPush(stack, 44362));
assertPeek(stack, 44362);
assertPeek(stack, 44362);
ASSERT_FALSE(stackIsEmpty(stack));

stackDispose(stack);
}

CTEST(stackTests, pushPeekTestC) {
Stack *stack = createStack();

ASSERT_TRUE(stackPush(stack, 2352));
ASSERT_TRUE(stackPush(stack, 43634));
assertPeek(stack, 43634);
ASSERT_FALSE(stackIsEmpty(stack));

ASSERT_TRUE(stackPush(stack, 9999));
ASSERT_TRUE(stackPush(stack, 7777777));
assertPeek(stack, 7777777);
assertPeek(stack, 7777777);
assertPeek(stack, 7777777);
ASSERT_FALSE(stackIsEmpty(stack));

stackDispose(stack);
}

#pragma endregion
11 changes: 11 additions & 0 deletions homework_5/task_1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
project("${homeworkName}_task_1")

add_library(bracketsBalance bracketsBalance.c)

add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} bracketsBalance)
target_link_libraries(${PROJECT_NAME} stack)

add_executable(${PROJECT_NAME}_test test.c)
target_link_libraries(${PROJECT_NAME}_test bracketsBalance)
target_link_libraries(${PROJECT_NAME}_test stack)
44 changes: 44 additions & 0 deletions homework_5/task_1/bracketsBalance.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "bracketsBalance.h"

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

#include "../stack/stack.h"

BalanceResult checkIfBracketsBalanced(const char *string) {
Stack *stack = NULL;
if (!stackCreate(&stack)) {
return ALLOCATION_FAILED;
}

bool checkedAll = true;

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

if (chr == '(' || chr == '[' || chr == '{') {
stackPush(stack, chr);
} else if (chr == ')' || chr == ']' || chr == '}') {
uint64_t value = -1;
if (!stackTryPop(stack, &value)) {
checkedAll = false;
break;
}

char popped = (char)value;

if ((popped == '(' && chr != ')') ||
(popped == '[' && chr != ']') ||
(popped == '{' && chr != '}')) {
checkedAll = false;
break;
}
}
}

BalanceResult result = checkedAll && stackIsEmpty(stack) ? BALANCED : UNBALANCED;

stackDispose(stack);

return result;
}
13 changes: 13 additions & 0 deletions homework_5/task_1/bracketsBalance.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

typedef enum {
BALANCED,
UNBALANCED,
ALLOCATION_FAILED
} BalanceResult;

/// @brief Checks if brackets are balanced in given string, all other characters are ignored
/// @param string String to be checked
/// @return `BALANCED` if brackets are balanced, `UNBALANCED` otherwise,
/// `ALLOCATION_FAILED` if allocation failed
BalanceResult checkIfBracketsBalanced(const char *string);
28 changes: 28 additions & 0 deletions homework_5/task_1/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <stdio.h>

#include "bracketsBalance.h"

int main(void) {
printf("input string: ");
char buffer[1024] = { 0 };

if (scanf("%1023s", buffer) != 1) {
printf("reading string failed\n");
return 1;
}

switch (checkIfBracketsBalanced(buffer))
{
case BALANCED:
printf("brackets are balanced\n");
break;

case UNBALANCED:
printf("brackets are unbalanced\n");
break;

case ALLOCATION_FAILED:
printf("allocation failed\n");
return 1;
}
}
Loading