From f42a997683ef0082b9c5b19f6f5b6bf1e53f5d1b Mon Sep 17 00:00:00 2001 From: Kristin Date: Fri, 5 Dec 2025 11:12:30 +0100 Subject: [PATCH 01/11] clearstack mit ** --- stack.c | 13 +++++-------- stack.h | 3 ++- test_stack.c | 5 +++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/stack.c b/stack.c index 35e7708..1309122 100644 --- a/stack.c +++ b/stack.c @@ -69,14 +69,11 @@ StackNode *pop(StackNode *stack) { void *top(StackNode *stack) { return stack != NULL ? stack->data : NULL; } // Clears stack and releases all memory. -StackNode *clearStack(StackNode *stack) { +void clearStack(StackNode **stack) { - while (stack != NULL) { - - StackNode *next = stack->next; - free(stack); - stack = next; + while (*stack != NULL) { + StackNode *next = (*stack)->next; + free(*stack); + *stack = next; } - - return NULL; } \ No newline at end of file diff --git a/stack.h b/stack.h index f90d217..bbb3fce 100644 --- a/stack.h +++ b/stack.h @@ -13,6 +13,7 @@ typedef struct StackNode { void *data; struct StackNode *next; + struct StackNode *prev; } StackNode; @@ -29,6 +30,6 @@ StackNode *pop(StackNode *stack); void *top(StackNode *stack); // Clears stack and releases all memory. -StackNode *clearStack(StackNode *stack); +void clearStack(StackNode **stack); #endif diff --git a/test_stack.c b/test_stack.c index 52ff263..78b019b 100644 --- a/test_stack.c +++ b/test_stack.c @@ -31,12 +31,13 @@ void test_clearStack(void) { int testInts[] = {1, 2, 3, 4, 5}; StackNode *testStack = NULL; + // Stack füllen for (int i = 0; i < 5; i++) { - testStack = push(testStack, &testInts[i]); } - testStack = clearStack(testStack); + clearStack(&testStack); + TEST_ASSERT_NULL(testStack); } From 5e96ec050c446e548bd537281c2c1122e73bfc87 Mon Sep 17 00:00:00 2001 From: Kristin Date: Fri, 5 Dec 2025 11:24:35 +0100 Subject: [PATCH 02/11] test_stack mit & --- stack.c | 31 +++++++++++++++++-------------- test_stack.c | 15 ++++++--------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/stack.c b/stack.c index 1309122..8f9d54b 100644 --- a/stack.c +++ b/stack.c @@ -20,33 +20,33 @@ StackNode *createNode(void *data) { - StackNode *node = - malloc(sizeof(StackNode)); // Speicher reservieren, Speicherplatz für das - // struct StackNode + StackNode *node = malloc(sizeof(StackNode)); if (node == NULL) - return NULL; // Speicher konnte nicht reserviert werden + return NULL; - node->data = data; // Zeiger auf data neuer node - node->next = NULL; // nächster Zeiger ist NULL, Ende der Liste + node->data = data; + node->next = NULL; + node->prev = NULL; - return node; // pointer auf den neuen Knoten zurückgeben + return node; } // Pushes data as pointer onto the stack. StackNode *push(StackNode *stack, void *data) { - StackNode *newNode = createNode(data); // Speicher für neuen Knoten - // reservieren + StackNode *newNode = createNode(data); - if (newNode == NULL) { // wenn Speicher nicht reserviert werden konnte, wird - // stack unverändert zurückgegeben + if (newNode == NULL) { return stack; } - newNode->next = stack; // pointer verschieben + newNode->next = stack; + if (stack != NULL) { + stack->prev = newNode; + } - return newNode; // Zeiger auf neuen Speicherbereich zurückgeben + return newNode; } // Deletes the top element of the stack (latest added element) and releases its @@ -57,6 +57,9 @@ StackNode *pop(StackNode *stack) { return NULL; StackNode *nextNode = stack->next; + if (nextNode != NULL) { + nextNode->prev = NULL; + } free(stack); @@ -66,7 +69,7 @@ StackNode *pop(StackNode *stack) { } // Returns the data of the top element. -void *top(StackNode *stack) { return stack != NULL ? stack->data : NULL; } +void *top(StackNode *stack) { return stack ? stack->data : NULL; } // Clears stack and releases all memory. void clearStack(StackNode **stack) { diff --git a/test_stack.c b/test_stack.c index 78b019b..abd14c0 100644 --- a/test_stack.c +++ b/test_stack.c @@ -8,14 +8,12 @@ void test_createNode(void) { int testInt = 26; - StackNode *testNode = createNode(&testInt); TEST_ASSERT_NOT_NULL(testNode); - TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data); - TEST_ASSERT_NULL(testNode->next); + TEST_ASSERT_NULL(testNode->prev); free(testNode); } @@ -27,18 +25,16 @@ void test_deleteTopElement(void) {} void test_returnData(void) {} void test_clearStack(void) { - int testInts[] = {1, 2, 3, 4, 5}; - StackNode *testStack = NULL; + StackNode *stack = NULL; - // Stack füllen for (int i = 0; i < 5; i++) { - testStack = push(testStack, &testInts[i]); + stack = push(stack, &testInts[i]); } - clearStack(&testStack); + clearStack(&stack); - TEST_ASSERT_NULL(testStack); + TEST_ASSERT_NULL(stack); } void setUp(void) {} @@ -49,6 +45,7 @@ int main(void) { UNITY_BEGIN(); printf("------------------------stack test------------------------\n"); + RUN_TEST(test_createNode); RUN_TEST(test_pushDataToStack); RUN_TEST(test_deleteTopElement); From d3904ac6e4c303c044cad0c7d69f5258bca231ad Mon Sep 17 00:00:00 2001 From: Kristin Date: Fri, 5 Dec 2025 11:50:51 +0100 Subject: [PATCH 03/11] alle tests --- test_stack.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/test_stack.c b/test_stack.c index abd14c0..9f14a45 100644 --- a/test_stack.c +++ b/test_stack.c @@ -18,11 +18,65 @@ void test_createNode(void) { free(testNode); } -void test_pushDataToStack(void) {} +void test_pushDataToStack(void) { -void test_deleteTopElement(void) {} + int testInt = 27; -void test_returnData(void) {} + StackNode *testNode = push(NULL, &testInt); + + TEST_ASSERT_NOT_NULL(testNode); + TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data); + TEST_ASSERT_NULL(testNode->next); + TEST_ASSERT_NULL(testNode->prev); + + free(testNode); +} + +void test_deleteTopElement(void) { + + int testInts[] = {10, 20, 30}; + StackNode *stack = NULL; + + for (int i = 0; i < 3; i++) { + stack = push(stack, &testInts[i]); + } + + TEST_ASSERT_EQUAL_PTR(&testInts[2], top(stack)); + + stack = pop(stack); + TEST_ASSERT_EQUAL_PTR(&testInts[1], top(stack)); + + stack = pop(stack); + TEST_ASSERT_EQUAL_PTR(&testInts[0], top(stack)); + + stack = pop(stack); + TEST_ASSERT_NULL(stack); +} + +void test_returnData(void) { + + int testInts[] = {10, 20, 30}; + StackNode *stack = NULL; + + for (int i = 0; i < 3; i++) { + stack = push(stack, &testInts[i]); + } + + TEST_ASSERT_EQUAL_PTR(&testInts[2], top(stack)); + + if (stack->next != NULL) { + TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->next->data); + if (stack->next->next != NULL) { + TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->next->next->data); + } + } + + StackNode *last = stack; + while (last->next != NULL) { + last = last->next; + } + TEST_ASSERT_NULL(last->next); +} void test_clearStack(void) { int testInts[] = {1, 2, 3, 4, 5}; @@ -51,7 +105,6 @@ int main(void) { RUN_TEST(test_deleteTopElement); RUN_TEST(test_returnData); RUN_TEST(test_clearStack); - RUN_TEST(test_clearStack); return UNITY_END(); } From 55532cbb421d0b0d821f75b197ea0b78fb151201 Mon Sep 17 00:00:00 2001 From: Kristin Date: Fri, 5 Dec 2025 11:52:08 +0100 Subject: [PATCH 04/11] makefile mit rm --- makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/makefile b/makefile index 514505e..c923a04 100644 --- a/makefile +++ b/makefile @@ -48,8 +48,4 @@ test_stack.o: test_stack.c # Clean # -------------------------- clean: -ifeq ($(OS),Windows_NT) rm -f *.o doble -else - del /f *.o doble -endif \ No newline at end of file From 68563ec2973c1040f1fa1bacd06a614b1a633e71 Mon Sep 17 00:00:00 2001 From: Kristin Date: Sun, 7 Dec 2025 18:35:22 +0100 Subject: [PATCH 05/11] erste version --- bintree.c | 108 ++++++++++++++++++++++++++++++++++++++++--------- highscores.txt | 3 ++ makefile | 31 ++++++++++++-- numbers.c | 103 +++++++++++++++++++++++++++++++++++++--------- test_binary.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++ test_numbers.c | 61 ++++++++++++++++++++++++++++ test_stack.c | 8 ++-- 7 files changed, 373 insertions(+), 46 deletions(-) create mode 100644 test_binary.c create mode 100644 test_numbers.c diff --git a/bintree.c b/bintree.c index 5cf82a9..82d2789 100644 --- a/bintree.c +++ b/bintree.c @@ -1,36 +1,106 @@ -#include -#include "stack.h" #include "bintree.h" +#include "stack.h" +#include -//TODO: binären Suchbaum implementieren +// TODO: binären Suchbaum implementieren /* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv), - * `clearTree`: gibt den gesamten Baum frei (rekursiv), - * `treeSize`: zählt die Knoten im Baum (rekursiv), - * `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */ + * `clearTree`: gibt den gesamten Baum frei (rekursiv), + * `treeSize`: zählt die Knoten im Baum (rekursiv), + * `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */ -// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates -// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). -TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) -{ +// typedef int (*CompareFctType)(const void *arg1, const void *arg2); +// Adds a copy of data's pointer destination to the tree using compareFct for +// ordering. Accepts duplicates if isDuplicate is NULL, otherwise ignores +// duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). +TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, + CompareFctType compareFct, int *isDuplicate) { + if (isDuplicate) { + *isDuplicate = 0; + } + + if (root == NULL) { + TreeNode *node = malloc(sizeof(TreeNode)); + node->data = malloc(dataSize); + memcpy(node->data, data, dataSize); + node->left = NULL; + node->right = NULL; + return node; + } + + int cmp = compareFct(data, root->data); + + if (cmp < 0) { + root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate); + } else if (cmp > 0) { + root->right = + addToTree(root->right, data, dataSize, compareFct, isDuplicate); + } else { + // Duplikat + if (isDuplicate) { + *isDuplicate = 1; + } + } + return root; } -// Iterates over the tree given by root. Follows the usage of strtok. If tree is NULL, the next entry of the last tree given is returned in ordering direction. -// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, -// push the top node and push all its left nodes. -void *nextTreeData(TreeNode *root) -{ +// Iterates over the tree given by root. Follows the usage of strtok. If tree is +// NULL, the next entry of the last tree given is returned in ordering +// direction. Use your implementation of a stack to organize the iterator. Push +// the root node and all left nodes first. On returning the next element, push +// the top node and push all its left nodes. +void *nextTreeData(TreeNode *root) { + static StackNode *stack = NULL; + + // Neue Iteration starten + if (root != NULL) { + clearStack(&stack); + + TreeNode *curr = root; + + // Alle linken Kinder pushen + while (curr != NULL) { + stack = push(stack, curr); + curr = curr->left; + } + } + + // Wenn leer → fertig + if (stack == NULL) + return NULL; + + // Oberstes Element lesen + TreeNode *node = (TreeNode *)stack->data; + stack = pop(stack); + + // Jetzt den rechten Teilbaum verarbeiten + TreeNode *curr = node->right; + while (curr != NULL) { + stack = push(stack, curr); + curr = curr->left; + } + + return node->data; } // Releases all memory resources (including data copies). -void clearTree(TreeNode *root) -{ +void clearTree(TreeNode *root) { + if (root == NULL) + return; + + clearTree(root->left); + clearTree(root->right); + + free(root->data); + free(root); } // Returns the number of entries in the tree given by root. -unsigned int treeSize(const TreeNode *root) -{ +unsigned int treeSize(const TreeNode *root) { + if (root == NULL) + return 0; + return 1 + treeSize(root->left) + treeSize(root->right); } \ No newline at end of file diff --git a/highscores.txt b/highscores.txt index ca5950d..cf3230a 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1,2 +1,5 @@ krisp;4986 +krisp;4985 +Kristin;4972 player1;3999 +krisp;3991 diff --git a/makefile b/makefile index c923a04..bc65fb7 100644 --- a/makefile +++ b/makefile @@ -36,16 +36,39 @@ $(program_obj_files): %.o: %.c # Unit Tests # -------------------------- -TEST_BIN = runTests +STACK_TEST_BIN = runStackTests +NUMBERS_TEST_BIN = runNumbersTests +BINARY_TEST_BIN = runBinaryTests -unitTests: stack.o test_stack.o - $(CC) $(FLAGS) -I$(unityfolder) -o $(TEST_BIN) stack.o test_stack.o $(unityfolder)/unity.c +# --- Stack Tests --- +stackTests: stack.o test_stack.o + $(CC) $(FLAGS) -I$(unityfolder) -o $(STACK_TEST_BIN) \ + stack.o test_stack.o $(unityfolder)/unity.c test_stack.o: test_stack.c $(CC) $(FLAGS) -I$(unityfolder) -c test_stack.c -o test_stack.o + +# --- Numbers Tests --- +numbersTests: numbers.o bintree.o stack.o test_numbers.o + $(CC) $(FLAGS) -I$(unityfolder) -o $(NUMBERS_TEST_BIN) \ + numbers.o bintree.o stack.o test_numbers.o $(unityfolder)/unity.c + +test_numbers.o: test_numbers.c + $(CC) $(FLAGS) -I$(unityfolder) -c test_numbers.c -o test_numbers.o + + +# --- Binary Tree Tests --- +binaryTests: bintree.o stack.o test_binary.o + $(CC) $(FLAGS) -I$(unityfolder) -o $(BINARY_TEST_BIN) \ + bintree.o stack.o test_binary.o $(unityfolder)/unity.c + +test_binary.o: test_binary.c + $(CC) $(FLAGS) -I$(unityfolder) -c test_binary.c -o test_binary.o + + # -------------------------- # Clean # -------------------------- clean: - rm -f *.o doble + rm -f *.o doble $(STACK_TEST_BIN) $(NUMBERS_TEST_BIN) $(BINARY_TEST_BIN) \ No newline at end of file diff --git a/numbers.c b/numbers.c index f59d9a2..414a4a4 100644 --- a/numbers.c +++ b/numbers.c @@ -1,26 +1,91 @@ -#include -#include -#include -#include #include "numbers.h" #include "bintree.h" +#include +#include +#include +#include -//TODO: getDuplicate und createNumbers implementieren -/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. - * Sicherstellen, dass beim Befüllen keine Duplikate entstehen. - * Duplizieren eines zufälligen Eintrags im Array. - * in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ - -// Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries. -// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while -// creating random numbers. -unsigned int *createNumbers(unsigned int len) -{ +int compareUnsignedInt(const void *a, const void *b) { + unsigned int x = *(unsigned int *)a; + unsigned int y = *(unsigned int *)b; + if (x < y) + return -1; + if (x > y) + return 1; + return 0; } -// Returns only the only number in numbers which is present twice. Returns zero on errors. -unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) -{ +// TODO: getDuplicate und createNumbers implementieren +/**Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an + * Zufallszahlen. Sicherstellen, dass beim Befüllen keine Duplikate entstehen. + * Duplizieren eines zufälligen Eintrags im Array. + * in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl + * durch Vergleich benachbarter Elemente. */ -} \ No newline at end of file +// Returns len random numbers between 1 and 2x len in random order which are all +// different, except for two entries. Returns NULL on errors. Use your +// implementation of the binary search tree to check for possible duplicates +// while creating random numbers. +unsigned int *createNumbers(unsigned int len) { + if (len < 2) + return NULL; + + unsigned int *arr = malloc(sizeof(unsigned int) * len); + if (!arr) + return NULL; + + TreeNode *root = NULL; + srand((unsigned int)time(NULL)); + + for (unsigned int i = 0; i < len - 1; i++) { + unsigned int num; + int isDuplicate; + + do { + num = (rand() % (2 * len)) + 1; + isDuplicate = 0; + + root = addToTree(root, &num, sizeof(unsigned int), compareUnsignedInt, + &isDuplicate); + + } while (isDuplicate); // nur akzeptieren, wenn eindeutig + + arr[i] = num; + } + + // Jetzt gezielt EIN Duplikat erzeugen + unsigned int duplicateIndex = rand() % (len - 1); + arr[len - 1] = arr[duplicateIndex]; + + clearTree(root); + return arr; +} + +// Returns only the only number in numbers which is present twice. Returns zero +// on errors. +unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) { + if (!numbers || len < 2) + return 0; + + unsigned int *copy = malloc(sizeof(unsigned int) * len); + if (!copy) + return 0; + + memcpy(copy, numbers, sizeof(unsigned int) * len); + + // Sortierung + qsort(copy, len, sizeof(unsigned int), compareUnsignedInt); + + // Duplikat finden: zwei gleiche nebeneinander + unsigned int duplicate = 0; + for (unsigned int i = 0; i < len - 1; i++) { + if (copy[i] == copy[i + 1]) { + duplicate = copy[i]; + break; + } + } + + free(copy); + return duplicate; +} diff --git a/test_binary.c b/test_binary.c new file mode 100644 index 0000000..a0d9cbc --- /dev/null +++ b/test_binary.c @@ -0,0 +1,105 @@ +#include "unity.h" +#include +#include +#include + +#include "bintree.h" +int compareUnsignedInt(const void *a, const void *b) { + unsigned int x = *(unsigned int *)a; + unsigned int y = *(unsigned int *)b; + + if (x < y) + return -1; + if (x > y) + return 1; + return 0; +} + +TreeNode *root = NULL; + +void setUp(void) { + root = NULL; // vor jedem Test leeren +} + +void tearDown(void) { clearTree(root); } + +// Test, ob addToTree Knoten korrekt hinzufügt +void test_addToTree_basic(void) { + int isDup; + unsigned int val = 10; + root = addToTree(root, &val, sizeof(val), compareUnsignedInt, &isDup); + TEST_ASSERT_NOT_NULL(root); + TEST_ASSERT_EQUAL_UINT(10, *(unsigned int *)root->data); + TEST_ASSERT_EQUAL_INT(0, isDup); + TEST_ASSERT_EQUAL_UINT(1, treeSize(root)); +} + +// Test, dass Duplikate erkannt werden +void test_addToTree_duplicate(void) { + int isDup; + unsigned int val1 = 10, val2 = 10; + root = addToTree(root, &val1, sizeof(val1), compareUnsignedInt, &isDup); + TEST_ASSERT_EQUAL_INT(0, isDup); + root = addToTree(root, &val2, sizeof(val2), compareUnsignedInt, &isDup); + TEST_ASSERT_EQUAL_INT(1, isDup); + TEST_ASSERT_EQUAL_UINT(1, treeSize(root)); // Duplikate nicht hinzufügen +} + +// Test nextTreeData Traversierung +void test_nextTreeData_in_order(void) { + unsigned int values[] = {20, 10, 30}; + int isDup; + for (int i = 0; i < 3; i++) { + root = addToTree(root, &values[i], sizeof(values[i]), compareUnsignedInt, + &isDup); + } + + unsigned int expected[] = {10, 20, 30}; + int idx = 0; + void *data; + + // **Neue Iteration starten** + data = nextTreeData(root); + while (data != NULL) { + TEST_ASSERT_EQUAL_UINT(expected[idx], *(unsigned int *)data); + idx++; + data = nextTreeData(NULL); // weitere Elemente abrufen + } + + TEST_ASSERT_EQUAL_INT(3, idx); // alle 3 Knoten besucht +} + +// Test clearTree gibt Speicher frei +void test_clearTree(void) { + unsigned int val = 42; + int isDup; + root = addToTree(root, &val, sizeof(val), compareUnsignedInt, &isDup); + clearTree(root); + root = NULL; // clearTree löscht nicht die root-Variable selbst + TEST_ASSERT_NULL(root); +} + +// Test treeSize zählt korrekt +void test_treeSize(void) { + unsigned int vals[] = {10, 20, 5}; + int isDup; + for (int i = 0; i < 3; i++) { + root = + addToTree(root, &vals[i], sizeof(vals[i]), compareUnsignedInt, &isDup); + } + TEST_ASSERT_EQUAL_UINT(3, treeSize(root)); +} + +int main(void) { + UNITY_BEGIN(); + + printf( + "\n------------------------binarytree test------------------------\n\n"); + + RUN_TEST(test_addToTree_basic); + RUN_TEST(test_addToTree_duplicate); + RUN_TEST(test_nextTreeData_in_order); + RUN_TEST(test_clearTree); + RUN_TEST(test_treeSize); + return UNITY_END(); +} \ No newline at end of file diff --git a/test_numbers.c b/test_numbers.c new file mode 100644 index 0000000..8992bb8 --- /dev/null +++ b/test_numbers.c @@ -0,0 +1,61 @@ +#include "unity.h" +#include +#include +#include + +#include "numbers.h" + +#define TEST_ARRAY_LEN 100 + +void test_createNumbers_length(void) { + unsigned int *arr = createNumbers(TEST_ARRAY_LEN); + TEST_ASSERT_NOT_NULL(arr); + free(arr); +} + +void test_createNumbers_single_duplicate(void) { + unsigned int *arr = createNumbers(TEST_ARRAY_LEN); + TEST_ASSERT_NOT_NULL(arr); + + unsigned int duplicate = getDuplicate(arr, TEST_ARRAY_LEN); + TEST_ASSERT_TRUE(duplicate > 0); + + unsigned int count = 0; + for (unsigned int i = 0; i < TEST_ARRAY_LEN; i++) { + if (arr[i] == duplicate) { + count++; + } + } + TEST_ASSERT_EQUAL_UINT(2, count); + + free(arr); +} + +void test_getDuplicate_manual_array(void) { + unsigned int numbers[5] = {10, 20, 30, 40, 20}; + unsigned int dup = getDuplicate(numbers, 5); + TEST_ASSERT_EQUAL_UINT(20, dup); +} + +void test_getDuplicate_invalid_input(void) { + TEST_ASSERT_EQUAL_UINT(0, getDuplicate(NULL, 5)); + unsigned int arr[1] = {42}; + TEST_ASSERT_EQUAL_UINT(0, getDuplicate(arr, 1)); +} + +void setUp(void) {} +void tearDown(void) {} + +int main(void) { + + UNITY_BEGIN(); + + printf("\n------------------------numbers test------------------------\n\n"); + + RUN_TEST(test_createNumbers_length); + RUN_TEST(test_createNumbers_single_duplicate); + RUN_TEST(test_getDuplicate_manual_array); + RUN_TEST(test_getDuplicate_invalid_input); + + return UNITY_END(); +} diff --git a/test_stack.c b/test_stack.c index 9f14a45..533af6a 100644 --- a/test_stack.c +++ b/test_stack.c @@ -41,13 +41,13 @@ void test_deleteTopElement(void) { stack = push(stack, &testInts[i]); } - TEST_ASSERT_EQUAL_PTR(&testInts[2], top(stack)); + TEST_ASSERT_EQUAL_PTR(&testInts[2], stack->data); stack = pop(stack); - TEST_ASSERT_EQUAL_PTR(&testInts[1], top(stack)); + TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->data); stack = pop(stack); - TEST_ASSERT_EQUAL_PTR(&testInts[0], top(stack)); + TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->data); stack = pop(stack); TEST_ASSERT_NULL(stack); @@ -98,7 +98,7 @@ int main(void) { UNITY_BEGIN(); - printf("------------------------stack test------------------------\n"); + printf("\n------------------------stack test------------------------\n\n"); RUN_TEST(test_createNode); RUN_TEST(test_pushDataToStack); From a3d0585ac16bac87fa6f532fa53b1657137ac5e6 Mon Sep 17 00:00:00 2001 From: Kristin Date: Sun, 7 Dec 2025 19:05:11 +0100 Subject: [PATCH 06/11] stack.c eingebunden --- bintree.c | 29 ++++++++++++++++++----------- bintree.h | 27 ++++++++++++++++----------- highscores.txt | 2 ++ makefile | 14 ++++++-------- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/bintree.c b/bintree.c index 82d2789..bf5a4ff 100644 --- a/bintree.c +++ b/bintree.c @@ -12,22 +12,34 @@ // Adds a copy of data's pointer destination to the tree using compareFct for // ordering. Accepts duplicates if isDuplicate is NULL, otherwise ignores // duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). + +void copyData(void *dest, const void *src, size_t size) { + unsigned char *d = dest; + const unsigned char *s = src; + for (size_t i = 0; i < size; i++) { + d[i] = s[i]; + } +} + TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) { + // isDuplicate initialisieren (auf 0 setzen) if (isDuplicate) { *isDuplicate = 0; } + // leerer Baum if (root == NULL) { TreeNode *node = malloc(sizeof(TreeNode)); node->data = malloc(dataSize); - memcpy(node->data, data, dataSize); + copyData(node->data, data, dataSize); node->left = NULL; node->right = NULL; return node; } + // mit compareFct <0 links >0 rechts =0 Duplikat int cmp = compareFct(data, root->data); if (cmp < 0) { @@ -36,7 +48,7 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); } else { - // Duplikat + // isDuplicate auf 1 setzen if (isDuplicate) { *isDuplicate = 1; } @@ -50,7 +62,6 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, // the root node and all left nodes first. On returning the next element, push // the top node and push all its left nodes. void *nextTreeData(TreeNode *root) { - static StackNode *stack = NULL; // Neue Iteration starten @@ -58,23 +69,20 @@ void *nextTreeData(TreeNode *root) { clearStack(&stack); TreeNode *curr = root; - - // Alle linken Kinder pushen while (curr != NULL) { stack = push(stack, curr); curr = curr->left; } } - // Wenn leer → fertig if (stack == NULL) - return NULL; + return NULL; // alles durchlaufen - // Oberstes Element lesen - TreeNode *node = (TreeNode *)stack->data; + // Oberstes Element abrufen + TreeNode *node = (TreeNode *)top(stack); stack = pop(stack); - // Jetzt den rechten Teilbaum verarbeiten + // Rechten Teilbaum pushen TreeNode *curr = node->right; while (curr != NULL) { stack = push(stack, curr); @@ -86,7 +94,6 @@ void *nextTreeData(TreeNode *root) { // Releases all memory resources (including data copies). void clearTree(TreeNode *root) { - if (root == NULL) return; diff --git a/bintree.h b/bintree.h index 25e16b2..1ced26b 100644 --- a/bintree.h +++ b/bintree.h @@ -5,19 +5,24 @@ typedef int (*CompareFctType)(const void *arg1, const void *arg2); -typedef struct node -{ - void *data; - struct node *left; - struct node *right; +typedef struct node { + void *data; + struct node *left; + struct node *right; } TreeNode; -// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates -// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). -TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate); -// Iterates over the tree given by root. Follows the usage of strtok. If tree is NULL, the next entry of the last tree given is returned in ordering direction. -// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, -// push the top node and push all its left nodes. +void copyData(void *dest, const void *src, size_t size); + +// Adds a copy of data's pointer destination to the tree using compareFct for +// ordering. Accepts duplicates if isDuplicate is NULL, otherwise ignores +// duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). +TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, + CompareFctType compareFct, int *isDuplicate); +// Iterates over the tree given by root. Follows the usage of strtok. If tree is +// NULL, the next entry of the last tree given is returned in ordering +// direction. Use your implementation of a stack to organize the iterator. Push +// the root node and all left nodes first. On returning the next element, push +// the top node and push all its left nodes. void *nextTreeData(TreeNode *root); // Releases all memory resources (including data copies). void clearTree(TreeNode *root); diff --git a/highscores.txt b/highscores.txt index cf3230a..77970c8 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1,3 +1,5 @@ +Kristin;6962 +Kristin;5975 krisp;4986 krisp;4985 Kristin;4972 diff --git a/makefile b/makefile index bc65fb7..805ac68 100644 --- a/makefile +++ b/makefile @@ -24,11 +24,12 @@ doble_initial: # -------------------------- # Selbst implementiertes Programm bauen # -------------------------- +# alle Objektdateien program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o - +# alle ausführbaren Dateien zu ausführbarem Programm linken doble : main.o $(program_obj_files) $(CC) $(FLAGS) $^ -o doble - +# Regel Kompilieren allgemein $(program_obj_files): %.o: %.c $(CC) -c $(FLAGS) $^ -o $@ @@ -42,8 +43,7 @@ BINARY_TEST_BIN = runBinaryTests # --- Stack Tests --- stackTests: stack.o test_stack.o - $(CC) $(FLAGS) -I$(unityfolder) -o $(STACK_TEST_BIN) \ - stack.o test_stack.o $(unityfolder)/unity.c + $(CC) $(FLAGS) -I$(unityfolder) -o $(STACK_TEST_BIN) stack.o test_stack.o $(unityfolder)/unity.c test_stack.o: test_stack.c $(CC) $(FLAGS) -I$(unityfolder) -c test_stack.c -o test_stack.o @@ -51,8 +51,7 @@ test_stack.o: test_stack.c # --- Numbers Tests --- numbersTests: numbers.o bintree.o stack.o test_numbers.o - $(CC) $(FLAGS) -I$(unityfolder) -o $(NUMBERS_TEST_BIN) \ - numbers.o bintree.o stack.o test_numbers.o $(unityfolder)/unity.c + $(CC) $(FLAGS) -I$(unityfolder) -o $(NUMBERS_TEST_BIN) numbers.o bintree.o stack.o test_numbers.o $(unityfolder)/unity.c test_numbers.o: test_numbers.c $(CC) $(FLAGS) -I$(unityfolder) -c test_numbers.c -o test_numbers.o @@ -60,8 +59,7 @@ test_numbers.o: test_numbers.c # --- Binary Tree Tests --- binaryTests: bintree.o stack.o test_binary.o - $(CC) $(FLAGS) -I$(unityfolder) -o $(BINARY_TEST_BIN) \ - bintree.o stack.o test_binary.o $(unityfolder)/unity.c + $(CC) $(FLAGS) -I$(unityfolder) -o $(BINARY_TEST_BIN) bintree.o stack.o test_binary.o $(unityfolder)/unity.c test_binary.o: test_binary.c $(CC) $(FLAGS) -I$(unityfolder) -c test_binary.c -o test_binary.o From 6528686fb0975937d01bde2bad96178c5f8c2ce9 Mon Sep 17 00:00:00 2001 From: Kristin Date: Sun, 7 Dec 2025 20:11:40 +0100 Subject: [PATCH 07/11] Fehler bei nichtreservierung von Speicher, stack.c kommentiert --- bintree.c | 14 ++++++++++---- highscores.txt | 2 ++ stack.c | 39 ++++++++++++++++++++++++++------------- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/bintree.c b/bintree.c index bf5a4ff..a07d6e0 100644 --- a/bintree.c +++ b/bintree.c @@ -70,11 +70,14 @@ void *nextTreeData(TreeNode *root) { TreeNode *curr = root; while (curr != NULL) { - stack = push(stack, curr); + StackNode *oldStack = stack; + StackNode *newStack = push(stack, curr); + if (newStack == oldStack) + return NULL; // push fehlgeschlagen + stack = newStack; curr = curr->left; } } - if (stack == NULL) return NULL; // alles durchlaufen @@ -85,10 +88,13 @@ void *nextTreeData(TreeNode *root) { // Rechten Teilbaum pushen TreeNode *curr = node->right; while (curr != NULL) { - stack = push(stack, curr); + StackNode *oldStack = stack; + StackNode *newStack = push(stack, curr); + if (newStack == oldStack) + return NULL; // push fehlgeschlagen + stack = newStack; curr = curr->left; } - return node->data; } diff --git a/highscores.txt b/highscores.txt index 77970c8..c7639ae 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1,7 +1,9 @@ +Kristin;7947 Kristin;6962 Kristin;5975 krisp;4986 krisp;4985 Kristin;4972 player1;3999 +Kristin;3992 krisp;3991 diff --git a/stack.c b/stack.c index 8f9d54b..9a7c81c 100644 --- a/stack.c +++ b/stack.c @@ -6,6 +6,7 @@ void *data; struct StackNode *next; + struct StackNode *prev; } StackNode;*/ @@ -16,12 +17,13 @@ * `clearStack`: gibt den gesamten Speicher frei. */ // [A] -> [B] -> [C] -> NULL -// head -> stack.next +// stack -> stack.next +// Funktion zum erstellen neuer nodes StackNode *createNode(void *data) { - + // Speicher reservieren StackNode *node = malloc(sizeof(StackNode)); - + // Speicher konnte nicht reserviert werden if (node == NULL) return NULL; @@ -37,46 +39,57 @@ StackNode *push(StackNode *stack, void *data) { StackNode *newNode = createNode(data); + // Fehler beim Reservieren des Speichers, stack wird unverändert zurückgegeben if (newNode == NULL) { return stack; } + // der aktuelle Kopf wird der nächste Node newNode->next = stack; + + // bisheriger Kopf bekommt Pointer auf oberstes Element if (stack != NULL) { stack->prev = newNode; } - return newNode; + return newNode; // neuer Kopf wird zurückgegeben } // 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) { + // Stack ohne Elemente if (stack == NULL) return NULL; + // Element unter Kopf wird als nextNode gespeichert StackNode *nextNode = stack->next; if (nextNode != NULL) { - nextNode->prev = NULL; + nextNode->prev = NULL; // der Zeiger zum Kopf wird auf NULL gesetzt } free(stack); - stack = NULL; + stack = NULL; // Speicher des Kopfes freigeben - return nextNode; + return nextNode; // neuen Kopf zurückgeben } // Returns the data of the top element. -void *top(StackNode *stack) { return stack ? stack->data : NULL; } +void *top(StackNode *stack) { + // wenn stack leer ist, wird NULL zurückgegeben + // Zeiger auf Daten des obersten Elements + return stack ? stack->data : NULL; +} // Clears stack and releases all memory. -void clearStack(StackNode **stack) { - +void clearStack(StackNode **stack) { // Zeiger auf den Zeiger auf den Stackkopf + // verändert den Zeiger selbst, mit *stack lokale Kopie + // im Aufruf &stack verwenden while (*stack != NULL) { - StackNode *next = (*stack)->next; - free(*stack); - *stack = next; + StackNode *next = (*stack)->next; // nächstes Element speichern + free(*stack); // aktuelles Element freigeben + *stack = next; // Zeiger auf nächsten Knoten setzen } } \ No newline at end of file From 13cb5d8c869bf422edce07c883988f229ec8c981 Mon Sep 17 00:00:00 2001 From: Kristin Date: Tue, 9 Dec 2025 09:13:18 +0100 Subject: [PATCH 08/11] push test im teststack verbessert --- highscores.txt | 1 + test_stack.c | 55 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/highscores.txt b/highscores.txt index c7639ae..04947fc 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1,3 +1,4 @@ +Kristin;9944 Kristin;7947 Kristin;6962 Kristin;5975 diff --git a/test_stack.c b/test_stack.c index 533af6a..fc24468 100644 --- a/test_stack.c +++ b/test_stack.c @@ -5,31 +5,62 @@ #include "stack.h" +// StackNode *createNode(void *data) testen void test_createNode(void) { int testInt = 26; - StackNode *testNode = createNode(&testInt); + StackNode *testNode = createNode(&testInt); // Adresse des testInts - TEST_ASSERT_NOT_NULL(testNode); - TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data); - TEST_ASSERT_NULL(testNode->next); + TEST_ASSERT_NOT_NULL( + testNode); // Speicher konnte reserviert werden, malloc ist nicht NULL + TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data); // data pointer gesetzt + TEST_ASSERT_NULL(testNode->next); // vorheriger und nächster Eintrag NULL TEST_ASSERT_NULL(testNode->prev); - free(testNode); + free(testNode); // Speicher freigeben } +// StackNode *push(StackNode *stack, void *data) testen void test_pushDataToStack(void) { - int testInt = 27; + int testInts[] = {27, 28}; - StackNode *testNode = push(NULL, &testInt); + StackNode *testStack = NULL; // leeren testStack initialisieren - TEST_ASSERT_NOT_NULL(testNode); - TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data); - TEST_ASSERT_NULL(testNode->next); - TEST_ASSERT_NULL(testNode->prev); + testStack = + push(testStack, &testInts[0]); // leerer Stack mit Adresse des testInts - free(testNode); + TEST_ASSERT_NOT_NULL(testStack); // im Fehlerfall wird testStack unverändert + // zurückgegeben -> bei Fehler NULL + TEST_ASSERT_EQUAL_PTR(&testInts[0], testStack->data); // data pointer gesetzt + TEST_ASSERT_NULL(testStack->next); // vorheriger und nächster pointer auf NULL + // gesetzt, da es nur einen Knoten gibt + TEST_ASSERT_NULL(testStack->prev); + + // zweiter Push + StackNode *oldHead = testStack; + + testStack = push(testStack, &testInts[1]); + + TEST_ASSERT_NOT_NULL(testStack); + TEST_ASSERT_NOT_EQUAL( + oldHead, + testStack); // bei malloc Fehler wird der head unverändert zurückgegeben + + TEST_ASSERT_EQUAL_PTR(&testInts[0], + oldHead->data); // data pointer wurden richtig gesetzt + TEST_ASSERT_EQUAL_PTR(&testInts[1], testStack->data); + + TEST_ASSERT_EQUAL_PTR(oldHead, testStack->next); + TEST_ASSERT_EQUAL_PTR(testStack, oldHead->prev); + TEST_ASSERT_NULL(testStack->prev); + + // Speicherfreigabe + testStack->next = NULL; + oldHead->prev = NULL; + + free(oldHead); + free(testStack); } void test_deleteTopElement(void) { From 09d7f457dd96015be5ff41b0df2cbc045a84253f Mon Sep 17 00:00:00 2001 From: Kristin Date: Tue, 9 Dec 2025 09:49:46 +0100 Subject: [PATCH 09/11] =?UTF-8?q?stacktest=20=C3=BCberarbeitet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- highscores.txt | 2 +- test_stack.c | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/highscores.txt b/highscores.txt index 04947fc..2924551 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1,10 +1,10 @@ Kristin;9944 Kristin;7947 Kristin;6962 +Kristin;5987 Kristin;5975 krisp;4986 krisp;4985 Kristin;4972 player1;3999 Kristin;3992 -krisp;3991 diff --git a/test_stack.c b/test_stack.c index fc24468..bad0e40 100644 --- a/test_stack.c +++ b/test_stack.c @@ -38,8 +38,7 @@ void test_pushDataToStack(void) { TEST_ASSERT_NULL(testStack->prev); // zweiter Push - StackNode *oldHead = testStack; - + StackNode *oldHead = testStack; // bisherigen head speichern testStack = push(testStack, &testInts[1]); TEST_ASSERT_NOT_NULL(testStack); @@ -51,12 +50,15 @@ void test_pushDataToStack(void) { oldHead->data); // data pointer wurden richtig gesetzt TEST_ASSERT_EQUAL_PTR(&testInts[1], testStack->data); + // richtige Verkettung: NULL <- testStack -> testStack->next -> oldHead -> + // NULL TEST_ASSERT_EQUAL_PTR(oldHead, testStack->next); TEST_ASSERT_EQUAL_PTR(testStack, oldHead->prev); TEST_ASSERT_NULL(testStack->prev); // Speicherfreigabe - testStack->next = NULL; + testStack->next = NULL; // pointer ungültig machen, damit nicht ausversehen + // später aufgerufen oldHead->prev = NULL; free(oldHead); @@ -68,7 +70,8 @@ void test_deleteTopElement(void) { int testInts[] = {10, 20, 30}; StackNode *stack = NULL; - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 3; + i++) { // Stack mit drei Elementen, oberestes Element mit data 30 stack = push(stack, &testInts[i]); } @@ -76,11 +79,13 @@ void test_deleteTopElement(void) { stack = pop(stack); TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->data); + TEST_ASSERT_NULL(stack->prev); stack = pop(stack); TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->data); + TEST_ASSERT_NULL(stack->prev); - stack = pop(stack); + stack = pop(stack); // bei leerem Stack wird NULL zurückgegeben TEST_ASSERT_NULL(stack); } From 57f9914e2b029fc91a75410b07e48fcddd2c8953 Mon Sep 17 00:00:00 2001 From: Kristin Date: Tue, 9 Dec 2025 09:57:41 +0100 Subject: [PATCH 10/11] =?UTF-8?q?stacktest=20=C3=BCberarbeitet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test_stack.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/test_stack.c b/test_stack.c index bad0e40..a47882b 100644 --- a/test_stack.c +++ b/test_stack.c @@ -75,11 +75,12 @@ void test_deleteTopElement(void) { stack = push(stack, &testInts[i]); } - TEST_ASSERT_EQUAL_PTR(&testInts[2], stack->data); + TEST_ASSERT_EQUAL_PTR(&testInts[2], stack->data); // oberstes Element ist 30 - stack = pop(stack); + stack = pop(stack); // oberstes Element löschen TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->data); - TEST_ASSERT_NULL(stack->prev); + TEST_ASSERT_NULL( + stack->prev); // pointer zum alten head wurde auf NULL gesetzt stack = pop(stack); TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->data); @@ -98,20 +99,16 @@ void test_returnData(void) { stack = push(stack, &testInts[i]); } - TEST_ASSERT_EQUAL_PTR(&testInts[2], top(stack)); + TEST_ASSERT_EQUAL_PTR(&testInts[2], + top(stack)); // top gibt richtige Adresse zurück + stack = pop(stack); // oberstes Element löschen + TEST_ASSERT_EQUAL_PTR(&testInts[1], top(stack)); - if (stack->next != NULL) { - TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->next->data); - if (stack->next->next != NULL) { - TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->next->next->data); - } - } + stack = pop(stack); + TEST_ASSERT_EQUAL_PTR(&testInts[0], top(stack)); - StackNode *last = stack; - while (last->next != NULL) { - last = last->next; - } - TEST_ASSERT_NULL(last->next); + stack = pop(stack); // bei leerem Stack wird NULL zurückgegeben + TEST_ASSERT_NULL(stack); } void test_clearStack(void) { From 9bf5e6a54179eb659198ed023001b3a2f053c608 Mon Sep 17 00:00:00 2001 From: Kristin Date: Tue, 9 Dec 2025 10:10:13 +0100 Subject: [PATCH 11/11] stacktest clearstack pointer null setzen --- stack.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/stack.c b/stack.c index 9a7c81c..db5de07 100644 --- a/stack.c +++ b/stack.c @@ -88,8 +88,13 @@ void clearStack(StackNode **stack) { // Zeiger auf den Zeiger auf den Stackkopf // verändert den Zeiger selbst, mit *stack lokale Kopie // im Aufruf &stack verwenden while (*stack != NULL) { + + (*stack)->prev = NULL; // späteren Pointerzugriff verhindern StackNode *next = (*stack)->next; // nächstes Element speichern - free(*stack); // aktuelles Element freigeben - *stack = next; // Zeiger auf nächsten Knoten setzen + + (*stack)->next = NULL; // späteren Pointerzugriff verhindern + + free(*stack); // aktuelles Element freigeben + *stack = next; // Zeiger auf nächsten Knoten setzen } } \ No newline at end of file