Stackfunktionen1
This commit is contained in:
parent
30ec4efd57
commit
c62a282234
45
stack.c
45
stack.c
@ -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
196
test_stack.c
Normal 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;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user