diff --git a/05_hw/CMakeLists.txt b/05_hw/CMakeLists.txt index 6f5e398..0ca6685 100644 --- a/05_hw/CMakeLists.txt +++ b/05_hw/CMakeLists.txt @@ -1,7 +1,26 @@ cmake_minimum_required(VERSION 3.10) project(stack) +# Устанавливаем флаги для покрытия кода +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../) +set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../) + +# Добавляем библиотеку для реализации стека add_library(stack stack.c) +# Добавляем исполняемый файл main add_executable(main main.c) target_link_libraries(main stack) + +# Добавляем исполняемый файл для тестов +add_executable(test test.c stack.c) +target_link_libraries(test stack) + +# Добавляем исполняемый файл для бенчмарков +add_executable(benchmark benchmark.c stack.c) +target_link_libraries(benchmark stack) + + diff --git a/05_hw/benchmark.c b/05_hw/benchmark.c new file mode 100644 index 0000000..8ed346b --- /dev/null +++ b/05_hw/benchmark.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include "stack.h" + +#define NUM_OPERATIONS 10000000 // Количество операций push/pop + +void benchmarkPush(Stack* stack) { + clock_t start = clock(); // Записываем начальное время + for (int i = 0; i < NUM_OPERATIONS; i++) { + push(stack, i); // Выполняем операцию push + } + clock_t end = clock(); // Записываем конечное время + double elapsed_time = ((double)(end - start)) / CLOCKS_PER_SEC; // Считаем время + printf("Benchmark PUSH: %d operations took %.6f seconds\n", NUM_OPERATIONS, elapsed_time); +} + +void benchmarkPop(Stack* stack) { + clock_t start = clock(); // Записываем начальное время + for (int i = 0; i < NUM_OPERATIONS; i++) { + pop(stack); // Выполняем операцию pop + } + clock_t end = clock(); // Записываем конечное время + double elapsed_time = ((double)(end - start)) / CLOCKS_PER_SEC; // Считаем время + printf("Benchmark POP: %d operations took %.6f seconds\n", NUM_OPERATIONS, elapsed_time); +} + +int main() { + Stack stack; + initStack(&stack); + + printf("Starting benchmark for PUSH...\n"); + benchmarkPush(&stack); + + printf("Starting benchmark for POP...\n"); + benchmarkPop(&stack); + + destroyStack(&stack); // Чистим стек + + return 0; +} diff --git a/05_hw/cppcheck_report.txt b/05_hw/cppcheck_report.txt new file mode 100644 index 0000000..229ec76 --- /dev/null +++ b/05_hw/cppcheck_report.txt @@ -0,0 +1,60 @@ +Checking main.c ... +1/8 files checked 0% done +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c ... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: INT_178B;__INTEGRITY... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: MPRAS;_MPRAS... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: SCO_SV;_SCO_SV;sco_sv... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: SDCC;__SDCC_VERSION_MAJOR... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: SDCC;__SDCC_VERSION_MAJOR;__SDCC_VERSION_MAJOR... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: SIMULATE_VERSION_TWEAK... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: WIN32;_WIN32;__WIN32__... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: XENIX;_XENIX;__XENIX__... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: _ADI_COMPILER... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: _ADI_COMPILER;__VERSIONNUM__... +Checking out\build\CMakeFiles\3.31.2\CompilerIdC\CMakeCCompilerId.c: _AIX;__AIX;__AIX__;__aix;__aix__... +2/8 files checked 22% done +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp ... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: INT_178B;__INTEGRITY... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: MPRAS;_MPRAS... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: SCO_SV;_SCO_SV;sco_sv... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: SIMULATE_VERSION_TWEAK... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: WIN32;_WIN32;__WIN32__... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: XENIX;_XENIX;__XENIX__... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: _ADI_COMPILER... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: _ADI_COMPILER;__VERSIONNUM__... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: _AIX;__AIX;__AIX__;__aix;__aix__... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: _BEOS;__BEOS__;__BeOS... +Checking out\build\CMakeFiles\3.31.2\CompilerIdCXX\CMakeCXXCompilerId.cpp: _CRAYC... +3/8 files checked 45% done +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c ... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: INT_178B;__INTEGRITY... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: MPRAS;_MPRAS... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: SCO_SV;_SCO_SV;sco_sv... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: SDCC;__SDCC_VERSION_MAJOR... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: SDCC;__SDCC_VERSION_MAJOR;__SDCC_VERSION_MAJOR... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: SIMULATE_VERSION_TWEAK... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: WIN32;_WIN32;__WIN32__... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: XENIX;_XENIX;__XENIX__... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: _ADI_COMPILER... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: _ADI_COMPILER;__VERSIONNUM__... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdC\CMakeCCompilerId.c: _AIX;__AIX;__AIX__;__aix;__aix__... +4/8 files checked 67% done +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp ... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: INT_178B;__INTEGRITY... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: MPRAS;_MPRAS... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: SCO_SV;_SCO_SV;sco_sv... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: SIMULATE_VERSION_TWEAK... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: WIN32;_WIN32;__WIN32__... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: XENIX;_XENIX;__XENIX__... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: _ADI_COMPILER... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: _ADI_COMPILER;__VERSIONNUM__... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: _AIX;__AIX;__AIX__;__aix;__aix__... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: _BEOS;__BEOS__;__BeOS... +Checking out\build\x64-Debug\CMakeFiles\3.28.3-msvc11\CompilerIdCXX\CMakeCXXCompilerId.cpp: _CRAYC... +5/8 files checked 88% done +Checking out\build\x64-Debug\CMakeFiles\ShowIncludes\main.c ... +6/8 files checked 88% done +Checking stack.c ... +7/8 files checked 93% done +Checking test.c ... +8/8 files checked 100% done diff --git a/05_hw/stack.c b/05_hw/stack.c index 0964440..04300f8 100644 --- a/05_hw/stack.c +++ b/05_hw/stack.c @@ -1,69 +1,95 @@ +#include "stack.h" #include #include -#include "stack.h" - +// Создание нового узла Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); + if (newNode == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(EXIT_FAILURE); + } newNode->data = data; newNode->next = NULL; return newNode; } +// Инициализация стека void initStack(Stack* stack) { + if (stack == NULL) { + fprintf(stderr, "Cannot initialize a NULL stack\n"); + return; + } stack->top = NULL; } -void destroyStack(Stack* stack) { - Node* current = stack->top; - while (current != NULL) { - Node *tmp = current; - current = current->next; - free(tmp); +// Проверка, пуст ли стек +bool isEmpty(Stack* stack) { + if (stack == NULL) { + fprintf(stderr, "Cannot check isEmpty on a NULL stack\n"); + return true; } + return stack->top == NULL; } +// Добавление элемента в стек void push(Stack* stack, int data) { + if (stack == NULL) { + fprintf(stderr, "Cannot push to a NULL stack\n"); + return; + } Node* newNode = createNode(data); newNode->next = stack->top; stack->top = newNode; } +// Удаление элемента из стека void pop(Stack* stack) { + if (stack == NULL) { + fprintf(stderr, "Cannot pop from a NULL stack\n"); + return; + } + if (isEmpty(stack)) { + fprintf(stderr, "Stack underflow\n"); + return; + } Node* temp = stack->top; stack->top = stack->top->next; + free(temp); } -Node* searchByValue(Stack* stack, int value) { - Node* current = stack->top; - while (current != NULL) { - if (current->data == value) { - return current; - } +// Очистка стека +void destroyStack(Stack* stack) { + if (stack == NULL) { + fprintf(stderr, "Cannot destroy a NULL stack\n"); + return; } - return NULL; -} - -Node* searchByIndex(Stack* stack, int index) { Node* current = stack->top; - int count = 0; while (current != NULL) { - if (count == index) { - return current; - } - count++; + Node* temp = current; current = current->next; + free(temp); } - return NULL; + stack->top = NULL; } +// Получение верхнего элемента стека Node* getTop(Stack* stack) { + if (stack == NULL) { + fprintf(stderr, "Cannot get top of a NULL stack\n"); + return NULL; + } return stack->top; } +// Перебор элементов стека void traverseStack(Stack* stack) { - Node* current = stack->top; + if (stack == NULL) { + fprintf(stderr, "Cannot traverse a NULL stack\n"); + return; + } printf("Stack elements: "); + Node* current = stack->top; while (current != NULL) { printf("%d ", current->data); current = current->next; @@ -71,8 +97,36 @@ void traverseStack(Stack* stack) { printf("\n"); } -bool isEmpty(Stack* stack) { - free(stack->top); - return stack->top == NULL; +// Поиск элемента по значению +Node* searchByValue(Stack* stack, int value) { + if (stack == NULL) { + fprintf(stderr, "Cannot search in a NULL stack\n"); + return NULL; + } + Node* current = stack->top; + while (current != NULL) { + if (current->data == value) { + return current; + } + current = current->next; + } + return NULL; } +// Поиск элемента по индексу +Node* searchByIndex(Stack* stack, int index) { + if (stack == NULL) { + fprintf(stderr, "Cannot search by index in a NULL stack\n"); + return NULL; + } + Node* current = stack->top; + int i = 0; + while (current != NULL) { + if (i == index) { + return current; + } + current = current->next; + i++; + } + return NULL; +} diff --git a/05_hw/stack.h b/05_hw/stack.h index ef0734e..d07aa0f 100644 --- a/05_hw/stack.h +++ b/05_hw/stack.h @@ -15,25 +15,25 @@ typedef struct Stack { extern "C" { #endif -Node* createNode(int data); + Node* createNode(int data); -void initStack(Stack* stack); + void initStack(Stack* stack); -void destroyStack(Stack *stack); + void destroyStack(Stack* stack); -void push(Stack* stack, int data); + void push(Stack* stack, int data); -void pop(Stack* stack); + void pop(Stack* stack); -Node* searchByValue(Stack* stack, int value); + Node* searchByValue(Stack* stack, int value); -Node* searchByIndex(Stack* stack, int index); + Node* searchByIndex(Stack* stack, int index); -Node* getTop(Stack* stack); + Node* getTop(Stack* stack); -void traverseStack(Stack* stack); + void traverseStack(Stack* stack); -bool isEmpty(Stack* stack); + bool isEmpty(Stack* stack); #ifdef __cplusplus } diff --git a/05_hw/test.c b/05_hw/test.c new file mode 100644 index 0000000..49315a2 --- /dev/null +++ b/05_hw/test.c @@ -0,0 +1,218 @@ +#include "stack.h" +#include +#include + +void test_push_null_stack() { + push(NULL, 10); + printf("Test: push with NULL stack - PASSED\n"); +} + +void test_pop_null_stack() { + pop(NULL); + printf("Test: pop with NULL stack - PASSED\n"); +} + +void test_destroyStack_null_stack() { + destroyStack(NULL); + printf("Test: destroyStack with NULL stack - PASSED\n"); +} + +void test_initStack_null() { + initStack(NULL); + printf("Test: initStack with NULL - PASSED\n"); +} + +void test_destroyStack_non_empty() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + destroyStack(&stack); + assert(stack.top == NULL); + + printf("Test: destroyStack on non-empty stack - PASSED\n"); +} + +void test_getTop_non_empty_stack() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + + Node* top = getTop(&stack); + assert(top != NULL && top->data == 20); + + printf("Test: getTop on non-empty stack - PASSED\n"); +} + +void test_getTop_empty_stack() { + Stack stack; + initStack(&stack); + + Node* top = getTop(&stack); + assert(top == NULL); + + printf("Test: getTop on empty stack - PASSED\n"); +} + +void test_traverseStack_empty() { + Stack stack; + initStack(&stack); + + printf("Expected output: (nothing)\n"); + printf("Actual output: "); + traverseStack(&stack); + + printf("Test: traverseStack on empty stack - PASSED\n"); +} + +void test_traverseStack_non_empty() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + printf("Expected output: Stack elements: 30 20 10\n"); + printf("Actual output: "); + traverseStack(&stack); + + printf("Test: traverseStack on non-empty stack - PASSED\n"); +} + +void test_searchByIndex() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + Node* result = searchByIndex(&stack, 1); + assert(result != NULL && result->data == 20); + + result = searchByIndex(&stack, 5); + assert(result == NULL); + + printf("Test: searchByIndex - PASSED\n"); +} + +void test_isEmpty() { + Stack stack; + initStack(&stack); + + assert(isEmpty(&stack) == true); + + push(&stack, 10); + assert(isEmpty(&stack) == false); + + pop(&stack); + assert(isEmpty(&stack) == true); + + printf("Test: isEmpty - PASSED\n"); +} + +void test_searchByValue_null_stack() { + Node* result = searchByValue(NULL, 10); + assert(result == NULL); + printf("Test: searchByValue with NULL stack - PASSED\n"); +} + +void test_searchByValue_empty_stack() { + Stack stack; + initStack(&stack); + + Node* result = searchByValue(&stack, 10); + assert(result == NULL); + printf("Test: searchByValue on empty stack - PASSED\n"); +} + +void test_searchByValue_existing_value() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + Node* result = searchByValue(&stack, 20); + assert(result != NULL && result->data == 20); + printf("Test: searchByValue with existing value - PASSED\n"); +} + +void test_searchByValue_non_existing_value() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + Node* result = searchByValue(&stack, 40); + assert(result == NULL); + printf("Test: searchByValue with non-existing value - PASSED\n"); +} + + +void test_createNode_null() { + Node* node = createNode(10); + assert(node != NULL); + printf("Test: createNode handles memory allocation successfully - PASSED\n"); +} + +void test_push_memory_failure() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + assert(stack.top != NULL); + printf("Test: push handles memory allocation successfully - PASSED\n"); +} + + +void test_searchByIndex_null_stack() { + Node* result = searchByIndex(NULL, 0); + assert(result == NULL); + printf("Test: searchByIndex with NULL stack - PASSED\n"); +} + + +void test_traverseStack_null_stack() { + traverseStack(NULL); + printf("Test: traverseStack with NULL stack - PASSED\n"); +} + +int main() { + + test_push_null_stack(); + test_pop_null_stack(); + test_destroyStack_null_stack(); + test_initStack_null(); + + test_destroyStack_non_empty(); + test_getTop_non_empty_stack(); + test_getTop_empty_stack(); + test_traverseStack_empty(); + test_traverseStack_non_empty(); + test_searchByIndex(); + test_isEmpty(); + + test_searchByValue_null_stack(); + test_searchByValue_empty_stack(); + test_searchByValue_existing_value(); + test_searchByValue_non_existing_value(); + + test_createNode_null(); + test_push_memory_failure(); + + test_searchByIndex_null_stack(); + test_traverseStack_null_stack(); + + printf("All tests passed successfully!\n"); + return 0; +} \ No newline at end of file