From 9fb140fecf29e0811e9ee7e253efa52b70989f35 Mon Sep 17 00:00:00 2001 From: Kristin Date: Thu, 11 Dec 2025 16:16:52 +0100 Subject: [PATCH] =?UTF-8?q?cleartree=20angepasst,=20Kommentare=20vollst?= =?UTF-8?q?=C3=A4ndig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bintree.c | 15 +++-- bintree.h | 2 +- highscore.c | 165 ++++++++++++++++++++++++------------------------- highscores.txt | 2 +- numbers.c | 18 +++--- test_binary.c | 92 ++++++++++++++++----------- test_numbers.c | 50 +++++++++------ 7 files changed, 188 insertions(+), 156 deletions(-) diff --git a/bintree.c b/bintree.c index 42d1118..a1e0e34 100644 --- a/bintree.c +++ b/bintree.c @@ -109,15 +109,18 @@ void *nextTreeData(TreeNode *root) { } // Releases all memory resources (including data copies). -void clearTree(TreeNode *root) { - if (root == NULL) +void clearTree(TreeNode **root) { // rekursive Funktion zum freigeben des + // Speichers und Nullsetzen der Pointer + if (root == NULL || *root == NULL) return; - clearTree(root->left); - clearTree(root->right); + clearTree(&(*root)->left); // linken Teilbaum löschen + clearTree(&(*root)->right); // rechten Teilbaum löschen - free(root->data); - free(root); + free((*root)->data); // Daten freigeben + (*root)->data = NULL; + free(*root); // Knoten freigeben + *root = NULL; // Zeiger auf NULL setzen } // Returns the number of entries in the tree given by root. diff --git a/bintree.h b/bintree.h index aeb72ed..2fa6272 100644 --- a/bintree.h +++ b/bintree.h @@ -25,7 +25,7 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, // the top node and push all its left nodes. void *nextTreeData(TreeNode *root); // Releases all memory resources (including data copies). -void clearTree(TreeNode *root); +void clearTree(TreeNode **root); // Returns the number of entries in the tree given by root. unsigned int treeSize(const TreeNode *root); diff --git a/highscore.c b/highscore.c index fe8a458..d1ae64b 100644 --- a/highscore.c +++ b/highscore.c @@ -1,134 +1,129 @@ -#include -#include -#include #include "highscore.h" #include "bintree.h" +#include +#include +#include #define MAX_LINE_LEN 100 #define MAX_PLAYER_NAME_LEN 20 -typedef struct -{ - char name[MAX_PLAYER_NAME_LEN]; - int score; +typedef struct { + char name[MAX_PLAYER_NAME_LEN]; + int score; } HighscoreEntry; static TreeNode *highscoreTree = NULL; -// Compare two highscore entries by score (descending), then by name (ascending). -static int compareHighscoreEntries(const void *arg1, const void *arg2) -{ - const HighscoreEntry *entry1 = (const HighscoreEntry *)arg1; - const HighscoreEntry *entry2 = (const HighscoreEntry *)arg2; +// Compare two highscore entries by score (descending), then by name +// (ascending). +static int compareHighscoreEntries(const void *arg1, const void *arg2) { + const HighscoreEntry *entry1 = (const HighscoreEntry *)arg1; + const HighscoreEntry *entry2 = (const HighscoreEntry *)arg2; - int result = entry2->score - entry1->score; + int result = entry2->score - entry1->score; - if(result == 0) - result = strcmp(entry1->name, entry2->name); + if (result == 0) + result = strcmp(entry1->name, entry2->name); - return result; + return result; } // Create a new highscore entry from name and score. -static HighscoreEntry createHighscoreEntry(const char *name, int score) -{ - HighscoreEntry entry = {"", score}; +static HighscoreEntry createHighscoreEntry(const char *name, int score) { + HighscoreEntry entry = {"", score}; - if(name != NULL) - { - strncpy(entry.name, name, MAX_PLAYER_NAME_LEN); - entry.name[MAX_PLAYER_NAME_LEN-1] = '\0'; - } + if (name != NULL) { + strncpy(entry.name, name, MAX_PLAYER_NAME_LEN); + entry.name[MAX_PLAYER_NAME_LEN - 1] = '\0'; + } - return entry; + return entry; } // Calculate score based on time used and number of shown numbers. -static int calculateScore(double timeInSeconds, unsigned int len) -{ - return (1000.0 - timeInSeconds) * len; +static int calculateScore(double timeInSeconds, unsigned int len) { + return (1000.0 - timeInSeconds) * len; } // Load highscores from file into memory. -void loadHighscores(const char *path) -{ - FILE *file = fopen(path, "r"); +void loadHighscores(const char *path) { + FILE *file = fopen(path, "r"); - if(file != NULL) - { - char buffer[MAX_LINE_LEN+1]; + if (file != NULL) { + char buffer[MAX_LINE_LEN + 1]; - while(fgets(buffer, MAX_LINE_LEN+1, file) != NULL) - { - char *name = strtok(buffer, ";\n"); - char *scoreStr = strtok(NULL, ";\n"); + while (fgets(buffer, MAX_LINE_LEN + 1, file) != NULL) { + char *name = strtok(buffer, ";\n"); + char *scoreStr = strtok(NULL, ";\n"); - if(name != NULL && scoreStr != NULL) - { - HighscoreEntry entry = createHighscoreEntry(name, strtol(scoreStr, NULL, 10)); - highscoreTree = addToTree(highscoreTree, &entry, sizeof(entry), compareHighscoreEntries, NULL); - } - } - - fclose(file); + if (name != NULL && scoreStr != NULL) { + HighscoreEntry entry = + createHighscoreEntry(name, strtol(scoreStr, NULL, 10)); + highscoreTree = addToTree(highscoreTree, &entry, sizeof(entry), + compareHighscoreEntries, NULL); + } } + + fclose(file); + } } // Add a new highscore entry and return the calculated score. -int addHighscore(const char *name, double timeInSeconds, unsigned int len) -{ - HighscoreEntry entry = createHighscoreEntry(name, calculateScore(timeInSeconds, len)); - highscoreTree = addToTree(highscoreTree, &entry, sizeof(entry), compareHighscoreEntries, NULL); +int addHighscore(const char *name, double timeInSeconds, unsigned int len) { + HighscoreEntry entry = + createHighscoreEntry(name, calculateScore(timeInSeconds, len)); + highscoreTree = addToTree(highscoreTree, &entry, sizeof(entry), + compareHighscoreEntries, NULL); - return entry.score; + return entry.score; } // Print highscores (up to NUMBER_OF_SHOWN_HIGHSCORES) in a formatted table. -void showHighscores() -{ - const char *blanks = " "; - const char *stripes = "------------------------------------------------------------------------------------------------------------------------"; - const char *header = "H I G H S C O R E S"; - const int lineWidth = MAX_PLAYER_NAME_LEN + MAX_PLAYER_NAME_LEN + 5; +void showHighscores() { + const char *blanks = + " " + " "; + const char *stripes = + "------------------------------------------------------------------------" + "------------------------------------------------"; + const char *header = "H I G H S C O R E S"; + const int lineWidth = MAX_PLAYER_NAME_LEN + MAX_PLAYER_NAME_LEN + 5; - int blankSpace = (int)(lineWidth - strlen(header)) / 2; + int blankSpace = (int)(lineWidth - strlen(header)) / 2; - HighscoreEntry *entry = nextTreeData(highscoreTree); + HighscoreEntry *entry = nextTreeData(highscoreTree); + printf("+%*.*s+\n", lineWidth, lineWidth, stripes); + printf("|%*.*s%s%*.*s|\n", blankSpace, blankSpace, blanks, header, blankSpace, + blankSpace, blanks); + printf("+%*.*s+\n", lineWidth, lineWidth, stripes); + + for (int i = 0; i < NUMBER_OF_SHOWN_HIGHSCORES && entry != NULL; i++) { + printf("| %-*s | %*d |\n", MAX_PLAYER_NAME_LEN, entry->name, + MAX_PLAYER_NAME_LEN, entry->score); printf("+%*.*s+\n", lineWidth, lineWidth, stripes); - printf("|%*.*s%s%*.*s|\n", blankSpace, blankSpace, blanks, header, blankSpace, blankSpace, blanks); - printf("+%*.*s+\n", lineWidth, lineWidth, stripes); - - for(int i = 0; i < NUMBER_OF_SHOWN_HIGHSCORES && entry != NULL; i++) - { - printf("| %-*s | %*d |\n", MAX_PLAYER_NAME_LEN, entry->name, MAX_PLAYER_NAME_LEN, entry->score); - printf("+%*.*s+\n", lineWidth, lineWidth, stripes); - entry = nextTreeData(NULL); - } + entry = nextTreeData(NULL); + } } // Save highscores to file (up to NUMBER_OF_SHOWN_HIGHSCORES). -void saveHighscores(const char *path) -{ - FILE *file = fopen(path, "w"); +void saveHighscores(const char *path) { + FILE *file = fopen(path, "w"); - if(file != NULL) - { - HighscoreEntry *entry = nextTreeData(highscoreTree); + if (file != NULL) { + HighscoreEntry *entry = nextTreeData(highscoreTree); - for(int i = 0; i < NUMBER_OF_SHOWN_HIGHSCORES && entry != NULL; i++) - { - fprintf(file, "%s;%d\n", entry->name, entry->score); - entry = nextTreeData(NULL); - } - - fclose(file); + for (int i = 0; i < NUMBER_OF_SHOWN_HIGHSCORES && entry != NULL; i++) { + fprintf(file, "%s;%d\n", entry->name, entry->score); + entry = nextTreeData(NULL); } + + fclose(file); + } } // Free all memory used for highscores. -void clearHighscores() -{ - clearTree(highscoreTree); - highscoreTree = NULL; +void clearHighscores() { + clearTree(&highscoreTree); + highscoreTree = NULL; } \ No newline at end of file diff --git a/highscores.txt b/highscores.txt index bda4db4..a4f4431 100644 --- a/highscores.txt +++ b/highscores.txt @@ -7,4 +7,4 @@ krisp;19934 krisp;19916 kristin;19861 Kristin;19858 -krisp;19460 +p;19729 diff --git a/numbers.c b/numbers.c index 1fdae3f..6b0b3aa 100644 --- a/numbers.c +++ b/numbers.c @@ -63,20 +63,22 @@ unsigned int *createNumbers(unsigned int len) { numbersArray[newIndex] = numbersArray[duplicateIndex]; // Wert vom ersten Index kopieren - clearTree(root); // Speicher wieder freigeben, wird nicht mehr benötigt + clearTree(&root); // Speicher wieder freigeben, wird nicht mehr benötigt return numbersArray; } // 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) { +unsigned int getDuplicate( + const unsigned int *numbers, + unsigned int len) { // array numbers, sowie die Länge wird übergeben if (!numbers || len < 2) - return 0; // Sicherheit: kein Array oder zu kurz + return 0; // fehlerhaftes Array - TreeNode *root = NULL; - unsigned int duplicateValue = 0; + TreeNode *root = NULL; // leerer Baum + unsigned int duplicateValue = 0; // Wert des Duplikats - for (unsigned int i = 0; i < len; i++) { + for (unsigned int i = 0; i < len && duplicateValue == 0; i++) { // Schleife int isDuplicate = 0; // Zahl in den Baum einfügen @@ -85,10 +87,10 @@ unsigned int getDuplicate(const unsigned int *numbers, unsigned int len) { // Duplikat erkannt if (isDuplicate && duplicateValue == 0) { - duplicateValue = numbers[i]; // das erste Duplikat merken + duplicateValue = numbers[i]; // Duplikat merken, for-Schleife wird beendet } } - clearTree(root); // Baum freigeben + clearTree(&root); // Baum freigeben return duplicateValue; // 0, falls kein Duplikat } diff --git a/test_binary.c b/test_binary.c index c7aca72..800940c 100644 --- a/test_binary.c +++ b/test_binary.c @@ -22,71 +22,91 @@ void setUp(void) { root = NULL; // vor jedem Test leeren } -void tearDown(void) { clearTree(root); } +void tearDown(void) { clearTree(&root); } // Test, ob addToTree Knoten korrekt hinzufügt + +/*TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, + CompareFctType compareFct, int *isDuplicate) */ 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)); + int isDuplicate; + unsigned int testInt = 10; + root = addToTree(root, &testInt, sizeof(testInt), compareUnsignedInt, + &isDuplicate); + TEST_ASSERT_NOT_NULL(root); // Knoten wurde erfolgreich erzeugt + TEST_ASSERT_EQUAL_UINT( + 10, + *(unsigned int *)root + ->data); // Datenzeiger wurde richtig gesetzt, void pointer auf + // unsigned int pointer casten, mit *wird der Wert abgerufen + TEST_ASSERT_EQUAL_INT(0, isDuplicate); // kein Duplikat + TEST_ASSERT_EQUAL_UINT(1, treeSize(root)); // der tree hat einen Eintrag } // 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 + int isDuplicate; + unsigned int val1 = 10, val2 = 10; // Duplikate + root = addToTree(root, &val1, sizeof(val1), compareUnsignedInt, + &isDuplicate); // val 1 zum leeren Baum hinzufügen + TEST_ASSERT_EQUAL_INT(0, isDuplicate); // erster Knoten->kein Duplikat + root = addToTree(root, &val2, sizeof(val2), compareUnsignedInt, + &isDuplicate); // val 2 hinzufügen + TEST_ASSERT_EQUAL_INT(1, isDuplicate); // Duplikat erkannt + TEST_ASSERT_EQUAL_UINT(1, + treeSize(root)); // Duplikate wurde nicht hinzugefügt } // Test nextTreeData Traversierung void test_nextTreeData_in_order(void) { - unsigned int values[] = {20, 10, 30}; - int isDup; + unsigned int values[] = {20, 10, 30}; // erwartete Ausgabe: 10 -> 20 -> 30 + int isDuplicate; for (int i = 0; i < 3; i++) { root = addToTree(root, &values[i], sizeof(values[i]), compareUnsignedInt, - &isDup); + &isDuplicate); // Baum füllen } - unsigned int expected[] = {10, 20, 30}; - int idx = 0; + unsigned int expected[] = {10, 20, 30}; // erwartet in Order Reihenfolge + int valueID = 0; void *data; - // **Neue Iteration starten** + // Neue Iteration starten data = nextTreeData(root); while (data != NULL) { - TEST_ASSERT_EQUAL_UINT(expected[idx], *(unsigned int *)data); - idx++; + TEST_ASSERT_EQUAL_UINT(expected[valueID], + *(unsigned int *)data); // entspricht erwartetem Wert + + valueID++; data = nextTreeData(NULL); // weitere Elemente abrufen } - TEST_ASSERT_EQUAL_INT(3, idx); // alle 3 Knoten besucht + TEST_ASSERT_EQUAL_INT(3, valueID); // 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 +// Testet, dass clearTree Speicher freigibt und Root auf NULL setzt +void test_clearTree_sets_root_null(void) { + int isDuplicate; + unsigned int val1 = 10, val2 = 20; + + root = addToTree(root, &val1, sizeof(val1), compareUnsignedInt, &isDuplicate); + root = addToTree(root, &val2, sizeof(val2), compareUnsignedInt, &isDuplicate); + + // Vor dem Clear prüfen, dass Root nicht NULL ist + TEST_ASSERT_NOT_NULL(root); + + clearTree(&root); + + // Nach dem Clear muss Root auf NULL gesetzt sein TEST_ASSERT_NULL(root); } // Test treeSize zählt korrekt void test_treeSize(void) { - unsigned int vals[] = {10, 20, 5}; - int isDup; + unsigned int testInts[] = {10, 20, 5}; + int isDuplicate; for (int i = 0; i < 3; i++) { - root = - addToTree(root, &vals[i], sizeof(vals[i]), compareUnsignedInt, &isDup); + root = addToTree(root, &testInts[i], sizeof(testInts[i]), + compareUnsignedInt, &isDuplicate); } TEST_ASSERT_EQUAL_UINT(3, treeSize(root)); } @@ -100,7 +120,7 @@ int main(void) { RUN_TEST(test_addToTree_basic); RUN_TEST(test_addToTree_duplicate); RUN_TEST(test_nextTreeData_in_order); - RUN_TEST(test_clearTree); + RUN_TEST(test_clearTree_sets_root_null); RUN_TEST(test_treeSize); return UNITY_END(); } \ No newline at end of file diff --git a/test_numbers.c b/test_numbers.c index 8992bb8..3a27284 100644 --- a/test_numbers.c +++ b/test_numbers.c @@ -7,40 +7,52 @@ #define TEST_ARRAY_LEN 100 -void test_createNumbers_length(void) { - unsigned int *arr = createNumbers(TEST_ARRAY_LEN); - TEST_ASSERT_NOT_NULL(arr); - free(arr); +// Speicher für ein Array wird reserviert +void test_createNumbers_length(void) { // erstellt ein Array der Länge hundert + unsigned int *testArray = createNumbers(TEST_ARRAY_LEN); + TEST_ASSERT_NOT_NULL(testArray); + free(testArray); } +// Duplikat ist genau einmal vorhanden void test_createNumbers_single_duplicate(void) { - unsigned int *arr = createNumbers(TEST_ARRAY_LEN); - TEST_ASSERT_NOT_NULL(arr); + unsigned int *testArray = createNumbers(TEST_ARRAY_LEN); // Array erstellen + TEST_ASSERT_NOT_NULL(testArray); // Speicher konnte reserviert werden - unsigned int duplicate = getDuplicate(arr, TEST_ARRAY_LEN); - TEST_ASSERT_TRUE(duplicate > 0); + unsigned int duplicate = + getDuplicate(testArray, TEST_ARRAY_LEN); // Duplikat holen + TEST_ASSERT_TRUE(duplicate > 0); // Duplikat ist größer als 0 + TEST_ASSERT_TRUE( + duplicate < + (2 * TEST_ARRAY_LEN)); // Duplikat liegt im vorgegebenen Zahlenbereich - unsigned int count = 0; - for (unsigned int i = 0; i < TEST_ARRAY_LEN; i++) { - if (arr[i] == duplicate) { + unsigned int count = 0; // Anzahl der Duplikate + for (unsigned int i = 0; i < TEST_ARRAY_LEN; + i++) { // Einträge des testArrays auf Duplikate prüfen + if (testArray[i] == duplicate) { count++; } } - TEST_ASSERT_EQUAL_UINT(2, count); + TEST_ASSERT_EQUAL_UINT(2, count); // Duplikat zwei mal vorhanden - free(arr); + free(testArray); // Speicher freigeben } -void test_getDuplicate_manual_array(void) { +// getDuplicate testen +void test_getDuplicate_manual_array( + void) { // duplikat in fremden array wird gefunden unsigned int numbers[5] = {10, 20, 30, 40, 20}; - unsigned int dup = getDuplicate(numbers, 5); - TEST_ASSERT_EQUAL_UINT(20, dup); + unsigned int duplicate = getDuplicate(numbers, 5); + TEST_ASSERT_EQUAL_UINT(20, duplicate); } +// getDuplicate erkennt fehlerhaftes Array 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)); + TEST_ASSERT_EQUAL_UINT( + 0, getDuplicate(NULL, 5)); // unsigned int getDuplicate(const unsigned int + // *numbers, unsigned int len) + unsigned int testArray[1] = {2}; + TEST_ASSERT_EQUAL_UINT(0, getDuplicate(testArray, 1)); } void setUp(void) {}