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
28 changes: 28 additions & 0 deletions .github/workflows/c-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: C/C++ CI

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install GCC and tooling
run: |
sudo apt-get update
sudo apt-get install -y gcc build-essential

- name: Build tests with address sanitizer
run: |
gcc -fsanitize=address -g 05_hw/stack.c 05_hw/tests.c -o tests.exe

- name: Run tests
run: |
./tests.exe
62 changes: 62 additions & 0 deletions 05_hw/benchmark.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <stdio.h>
#include <time.h>
#include "stack.h"

#define N 1000000

void benchmark_push() {
Stack s;
initStack(&s);

clock_t start = clock();

for (int i = 0; i < N; i++) {
push(&s, i);
}

clock_t end = clock();

double elapsed_ms = ((double)(end - start) / CLOCKS_PER_SEC) * 1000.0;

printf("Push benchmark:\n");
printf(" Total pushes: %d\n", N);
printf(" Total time: %.3f ms\n", elapsed_ms);
printf(" Avg per push: %.6f microseconds\n\n", (elapsed_ms * 1000.0) / N);

destroyStack(&s);
}

// Функция для измерения pop()
void benchmark_pop() {
Stack s;
initStack(&s);

// Заполняем стек заранее
for (int i = 0; i < N; i++) {
push(&s, i);
}

clock_t start = clock();

for (int i = 0; i < N; i++) {
pop(&s);
}

clock_t end = clock();

double elapsed_ms = ((double)(end - start) / CLOCKS_PER_SEC) * 1000.0;

printf("Pop benchmark:\n");
printf(" Total pops: %d\n", N);
printf(" Total time: %.3f ms\n", elapsed_ms);
printf(" Avg per pop: %.6f microseconds\n\n", (elapsed_ms * 1000.0) / N);
}

int main() {
printf("=== Stack benchmark ===\n\n");

benchmark_push();
benchmark_pop();

return 0;
}
17 changes: 17 additions & 0 deletions 05_hw/report.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Running: cppcheck --enable=all --template={"file":"{file}","line":{line},"column":{column},"severity":"{severity}","message":"{message}","id":"{id}"} c:\Users\User\Desktop\works\lecture-testing-task-main\05_hw\

Checking c:\Users\User\Desktop\works\lecture-testing-task-main\05_hw\stack.h ...
{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.h","line":1,"column":0,"severity":"information","message":"Include file: <stdbool.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.","id":"missingIncludeSystem"},

Checking c:\Users\User\Desktop\works\lecture-testing-task-main\05_hw\stack.c ...
{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":1,"column":0,"severity":"information","message":"Include file: <stdio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.","id":"missingIncludeSystem"},
{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":2,"column":0,"severity":"information","message":"Include file: <stdlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.","id":"missingIncludeSystem"},

{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":31,"column":5,"severity":"warning","message":"Returning 0 from pop() may be misleading: 0 is also valid data value.","id":"inconclusiveReturnValue"},

{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":16,"column":5,"severity":"style","message":"Parameter stack can be null pointer.","id":"nullPointerRedundantCheck"},

{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":67,"column":5,"severity":"style","message":"Found printf without newline. This may cause performance issues.","id":"performancePrintfWithoutNewline"},

Checking c:\Users\User\Desktop\works\lecture-testing-task-main\05_hw\main.c ...
{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\main.c","line":3,"column":0,"severity":"information","message":"Include file: <stdio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.","id":"missingIncludeSystem"},
31 changes: 23 additions & 8 deletions 05_hw/stack.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#include <stdio.h>
#include <stdlib.h>

#include "stack.h"

Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode) return NULL;

newNode->data = data;
newNode->next = NULL;
return newNode;
Expand All @@ -17,21 +18,33 @@ void initStack(Stack* stack) {
void destroyStack(Stack* stack) {
Node* current = stack->top;
while (current != NULL) {
Node *tmp = current;
Node* tmp = current;
current = current->next;
free(tmp);
free(tmp);
}
stack->top = NULL;
}

void push(Stack* stack, int data) {
Node* newNode = createNode(data);
if (!newNode) return;

newNode->next = stack->top;
stack->top = newNode;
}

void pop(Stack* stack) {
int pop(Stack* stack) {
if (stack->top == NULL) {
return 0;
}

Node* temp = stack->top;
stack->top = stack->top->next;
int value = temp->data;

stack->top = temp->next;
free(temp);

return value;
}

Node* searchByValue(Stack* stack, int value) {
Expand All @@ -40,13 +53,15 @@ Node* searchByValue(Stack* stack, int value) {
if (current->data == value) {
return current;
}
current = current->next;
}
return NULL;
}

Node* searchByIndex(Stack* stack, int index) {
Node* current = stack->top;
int count = 0;

while (current != NULL) {
if (count == index) {
return current;
Expand All @@ -64,15 +79,15 @@ Node* getTop(Stack* stack) {
void traverseStack(Stack* stack) {
Node* current = stack->top;
printf("Stack elements: ");

while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}

printf("\n");
}

bool isEmpty(Stack* stack) {
free(stack->top);
return stack->top == NULL;
}

}
4 changes: 2 additions & 2 deletions 05_hw/stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void destroyStack(Stack *stack);

void push(Stack* stack, int data);

void pop(Stack* stack);
int pop(Stack* stack);

Node* searchByValue(Stack* stack, int value);

Expand All @@ -37,4 +37,4 @@ bool isEmpty(Stack* stack);

#ifdef __cplusplus
}
#endif
#endif
117 changes: 117 additions & 0 deletions 05_hw/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include <CUnit/CUnit.h>
#include <CUnit/Basic.h>

#include "stack.h"

void test_initStack(void) {
Stack s;
initStack(&s);
CU_ASSERT_PTR_NULL(s.top);
destroyStack(&s);
}

void test_push_and_getTop(void) {
Stack s;
initStack(&s);

push(&s, 10);
CU_ASSERT_PTR_NOT_NULL(s.top);
CU_ASSERT_EQUAL(getTop(&s)->data, 10);

push(&s, 20);
CU_ASSERT_EQUAL(getTop(&s)->data, 20);

destroyStack(&s);
}

void test_pop(void) {
Stack s;
initStack(&s);

push(&s, 10);
push(&s, 20);

pop(&s);
CU_ASSERT_EQUAL(getTop(&s)->data, 10);

pop(&s);
CU_ASSERT_PTR_NULL(getTop(&s));

destroyStack(&s);
}

void test_searchByValue(void) {
Stack s;
initStack(&s);

push(&s, 5);
push(&s, 10);
push(&s, 15);

CU_ASSERT_PTR_NOT_NULL(searchByValue(&s, 10));
CU_ASSERT_PTR_NULL(searchByValue(&s, 999));

destroyStack(&s);
}

void test_searchByIndex(void) {
Stack s;
initStack(&s);

push(&s, 1);
push(&s, 2);
push(&s, 3);

CU_ASSERT_EQUAL(searchByIndex(&s, 0)->data, 3);
CU_ASSERT_EQUAL(searchByIndex(&s, 1)->data, 2);
CU_ASSERT_EQUAL(searchByIndex(&s, 2)->data, 1);
CU_ASSERT_PTR_NULL(searchByIndex(&s, 10));

destroyStack(&s);
}

void test_isEmpty(void) {
Stack s;
initStack(&s);
CU_ASSERT_TRUE(isEmpty(&s));

push(&s, 123);
CU_ASSERT_FALSE(isEmpty(&s));

destroyStack(&s);
}

void test_destroyStack(void) {
Stack s;
initStack(&s);

push(&s, 1);
push(&s, 2);
push(&s, 3);

destroyStack(&s);

CU_ASSERT_PTR_NULL(s.top);

destroyStack(&s);
}

int main() {
CU_initialize_registry();

CU_pSuite suite = CU_add_suite("Stack tests", 0, 0);

CU_add_test(suite, "initStack", test_initStack);
CU_add_test(suite, "push & getTop", test_push_and_getTop);
CU_add_test(suite, "pop", test_pop);
CU_add_test(suite, "searchByValue", test_searchByValue);
CU_add_test(suite, "searchByIndex", test_searchByIndex);
CU_add_test(suite, "isEmpty", test_isEmpty);
CU_add_test(suite, "destroyStack", test_destroyStack);

CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();

return 0;
}