Stackfunktionen1

This commit is contained in:
Bannach 2025-11-28 13:31:27 +01:00
parent 30ec4efd57
commit c62a282234
2 changed files with 240 additions and 1 deletions

45
stack.c
View File

@ -11,13 +11,56 @@
StackNode *push(StackNode *stack, void *data)
{
// 1. Einen neuen StackNode erstellen
StackNode *newNode = (StackNode *)malloc(sizeof(StackNode));
// Überprüfen, ob die Speicherreservierung erfolgreich war
if (newNode == NULL)
{
// Wenn malloc fehlschlägt, geben wir NULL zurück, um einen Fehler anzuzeigen.
return NULL;
}
// 2. Die Daten in den neuen Knoten legen
newNode->data = data;
// 3. Den 'next'-Zeiger des neuen Knotens auf den aktuellen Stack-Top setzen
// Der neue Knoten zeigt nun auf das Element, das zuvor ganz oben war.
newNode->next = stack;
// 4. Den neuen Knoten als neuen Stack-Top zurückgeben
// Er ist jetzt das oberste Element.
return newNode;
}
// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be
// freed by caller.)
StackNode *pop(StackNode *stack)
{
// 1. Überprüfen, ob der Stack leer ist
if (stack == NULL)
{
// Wenn der Stack leer ist, gibt es nichts zu entfernen.
// Wir geben NULL zurück, da der Stack immer noch leer ist.
return NULL;
}
// 2. Einen Zeiger auf das aktuelle oberste Element speichern
// Dieses Element wollen wir entfernen und dessen Speicher freigeben.
StackNode *oldTop = stack;
// 3. Den Stack-Zeiger auf das nächste Element im Stack setzen
// Das Element, das unter dem alten Top lag, wird jetzt zum neuen Top.
StackNode *newTop = stack->next;
// 4. Den Speicher des alten obersten Elements freigeben
// Wichtig: Die Daten, auf die oldTop->data zeigt, werden hier NICHT freigegeben.
// Das muss, wie in der .h-Datei beschrieben, vom Aufrufer erledigt werden,
// falls die Daten dynamisch alloziert wurden.
free(oldTop);
// 5. Den neuen Stack-Top zurückgeben
return newTop;
}
// Returns the data of the top element.
@ -30,4 +73,4 @@ void *top(StackNode *stack)
void clearStack(StackNode *stack)
{
}
}

196
test_stack.c Normal file
View File

@ -0,0 +1,196 @@
#include <stdio.h> // Für printf
#include <stdlib.h> // Für malloc, free
#include "stack.h" // Für die Stack-Funktionen und -Strukturen
// Globale Zähler für die Testergebnisse
int test_count = 0;
int test_failed = 0;
// Hilfsfunktion für Assertionen
void assert_equals_int(int expected, int actual, const char *test_name) {
test_count++;
if (expected == actual) {
printf(" [PASS] %s\n", test_name);
} else {
printf(" [FAIL] %s - Erwartet: %d, Tatsächlich: %d\n", test_name, expected, actual);
test_failed++;
}
}
void assert_equals_ptr(void *expected, void *actual, const char *test_name) {
test_count++;
if (expected == actual) {
printf(" [PASS] %s\n", test_name);
} else {
printf(" [FAIL] %s - Erwartet: %p, Tatsächlich: %p\n", test_name, expected, actual);
test_failed++;
}
}
// Hilfsfunktion zum Freigeben der Daten im Stack, bevor der Stack selbst geleert wird
void free_stack_data(StackNode *stack) {
StackNode *current = stack;
while (current != NULL) {
if (current->data != NULL) {
free(current->data); // Freigabe der Integer-Daten
current->data = NULL; // Optional: Pointer auf NULL setzen
}
current = current->next;
}
}
// --- Testfälle ---
void test_push_single_element() {
printf("--- Test: push_single_element ---\n");
StackNode *stack = NULL;
int *data1 = (int *)malloc(sizeof(int)); *data1 = 10;
stack = push(stack, data1);
assert_equals_ptr(data1, top(stack), "Top should be 10");
assert_equals_ptr(NULL, stack->next, "Next element should be NULL");
// Aufräumen
free_stack_data(stack); // Daten freigeben
clearStack(stack); // StackNodes freigeben
}
void test_push_multiple_elements() {
printf("--- Test: push_multiple_elements ---\n");
StackNode *stack = NULL;
int *data1 = (int *)malloc(sizeof(int)); *data1 = 10;
int *data2 = (int *)malloc(sizeof(int)); *data2 = 20;
int *data3 = (int *)malloc(sizeof(int)); *data3 = 30;
stack = push(stack, data1); // Stack: [10]
stack = push(stack, data2); // Stack: [20, 10]
stack = push(stack, data3); // Stack: [30, 20, 10]
assert_equals_int(30, *(int*)top(stack), "Top should be 30");
assert_equals_int(20, *(int*)stack->next->data, "Second element should be 20");
assert_equals_int(10, *(int*)stack->next->next->data, "Third element should be 10");
assert_equals_ptr(NULL, stack->next->next->next, "Fourth element should be NULL");
// Aufräumen
free_stack_data(stack);
clearStack(stack);
}
void test_pop_from_empty_stack() {
printf("--- Test: pop_from_empty_stack ---\n");
StackNode *stack = NULL;
StackNode *result = pop(stack);
assert_equals_ptr(NULL, result, "Pop from empty stack should return NULL");
assert_equals_ptr(NULL, stack, "Stack should remain NULL"); // stack pointer passed by value, so it's still NULL
}
void test_pop_single_element() {
printf("--- Test: pop_single_element ---\n");
StackNode *stack = NULL;
int *data1 = (int *)malloc(sizeof(int)); *data1 = 10;
stack = push(stack, data1); // Stack: [10]
assert_equals_int(10, *(int*)top(stack), "Top should be 10 before pop");
// Daten freigeben, bevor der Knoten freigegeben wird
free(top(stack)); // Freigabe von data1
stack = pop(stack); // Stack: []
assert_equals_ptr(NULL, stack, "Stack should be empty after popping last element");
assert_equals_ptr(NULL, top(stack), "Top should be NULL after popping last element");
}
void test_pop_multiple_elements() {
printf("--- Test: pop_multiple_elements ---\n");
StackNode *stack = NULL;
int *data1 = (int *)malloc(sizeof(int)); *data1 = 10;
int *data2 = (int *)malloc(sizeof(int)); *data2 = 20;
int *data3 = (int *)malloc(sizeof(int)); *data3 = 30;
stack = push(stack, data1);
stack = push(stack, data2);
stack = push(stack, data3); // Stack: [30, 20, 10]
// Pop 1 (30)
free(top(stack)); // Freigabe von data3
stack = pop(stack); // Stack: [20, 10]
assert_equals_int(20, *(int*)top(stack), "Top should be 20 after first pop");
// Pop 2 (20)
free(top(stack)); // Freigabe von data2
stack = pop(stack); // Stack: [10]
assert_equals_int(10, *(int*)top(stack), "Top should be 10 after second pop");
// Pop 3 (10)
free(top(stack)); // Freigabe von data1
stack = pop(stack); // Stack: []
assert_equals_ptr(NULL, stack, "Stack should be empty after third pop");
assert_equals_ptr(NULL, top(stack), "Top should be NULL after third pop");
}
void test_top_function() {
printf("--- Test: top_function ---\n");
StackNode *stack = NULL;
int *data1 = (int *)malloc(sizeof(int)); *data1 = 100;
int *data2 = (int *)malloc(sizeof(int)); *data2 = 200;
assert_equals_ptr(NULL, top(stack), "Top of empty stack should be NULL");
stack = push(stack, data1);
assert_equals_int(100, *(int*)top(stack), "Top should be 100");
stack = push(stack, data2);
assert_equals_int(200, *(int*)top(stack), "Top should be 200");
// Aufräumen
free_stack_data(stack);
clearStack(stack);
}
void test_clear_stack_function() {
printf("--- Test: clear_stack_function ---\n");
StackNode *stack = NULL;
int *data1 = (int *)malloc(sizeof(int)); *data1 = 1;
int *data2 = (int *)malloc(sizeof(int)); *data2 = 2;
int *data3 = (int *)malloc(sizeof(int)); *data3 = 3;
stack = push(stack, data1);
stack = push(stack, data2);
stack = push(stack, data3); // Stack: [3, 2, 1]
// Zuerst die Daten freigeben
free_stack_data(stack);
// Dann die StackNodes freigeben
clearStack(stack);
// WICHTIG: Der lokale 'stack'-Zeiger muss manuell auf NULL gesetzt werden,
// da clearStack ihn nicht ändern kann (pass-by-value).
stack = NULL;
assert_equals_ptr(NULL, stack, "Stack should be NULL after clearStack");
assert_equals_ptr(NULL, top(stack), "Top of cleared stack should be NULL");
}
int main() {
printf("Starte Stack Unit-Tests...\n");
test_push_single_element();
test_push_multiple_elements();
test_pop_from_empty_stack();
test_pop_single_element();
test_pop_multiple_elements();
test_top_function();
test_clear_stack_function();
printf("\n--- Testergebnisse ---\n");
printf("Gesamtzahl der Tests: %d\n", test_count);
printf("Fehlgeschlagene Tests: %d\n", test_failed);
if (test_failed == 0) {
printf("Alle Tests erfolgreich bestanden! 🎉\n");
return EXIT_SUCCESS;
} else {
printf("Einige Tests sind fehlgeschlagen. 😟\n");
return EXIT_FAILURE;
}
}