From d9222b83b44a999cc9241f85eb6ed2de9460db6e Mon Sep 17 00:00:00 2001 From: Kristin Date: Tue, 9 Dec 2025 10:27:18 +0100 Subject: [PATCH 1/4] =?UTF-8?q?highscore=20zum=20gitignore=20hinzugef?= =?UTF-8?q?=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- bintree.c | 10 +--------- bintree.h | 2 -- highscores.txt | 4 ++-- 4 files changed, 5 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 80f665a..9e312e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ doble_initial.exe *.o -*.exe \ No newline at end of file +*.exe +highscore.txt \ No newline at end of file diff --git a/bintree.c b/bintree.c index a07d6e0..14632fa 100644 --- a/bintree.c +++ b/bintree.c @@ -13,14 +13,6 @@ // 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) { @@ -33,7 +25,7 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, if (root == NULL) { TreeNode *node = malloc(sizeof(TreeNode)); node->data = malloc(dataSize); - copyData(node->data, data, dataSize); + memcpy(node->data, data, dataSize); node->left = NULL; node->right = NULL; return node; diff --git a/bintree.h b/bintree.h index 1ced26b..9e6b45c 100644 --- a/bintree.h +++ b/bintree.h @@ -11,8 +11,6 @@ typedef struct node { struct node *right; } TreeNode; -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). diff --git a/highscores.txt b/highscores.txt index 2924551..aaac161 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1,3 +1,5 @@ +Kristin;49209 +Kristin;9959 Kristin;9944 Kristin;7947 Kristin;6962 @@ -6,5 +8,3 @@ Kristin;5975 krisp;4986 krisp;4985 Kristin;4972 -player1;3999 -Kristin;3992 From 799667ed1c991a45b98de1adf155afdbbb3c39b7 Mon Sep 17 00:00:00 2001 From: Kristin Date: Wed, 10 Dec 2025 21:05:36 +0100 Subject: [PATCH 2/4] =?UTF-8?q?numbers.c=20bintree.c=20=C3=A4nderungen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bintree.c | 72 +++++++++++++++++---------- bintree.h | 2 + highscores.txt | 18 +++---- main.c | 132 ++++++++++++++++++++++++------------------------- numbers.c | 102 +++++++++++++++++++------------------- numbers.h | 12 +++-- test_binary.c | 1 + 7 files changed, 181 insertions(+), 158 deletions(-) diff --git a/bintree.c b/bintree.c index 14632fa..42d1118 100644 --- a/bintree.c +++ b/bintree.c @@ -13,34 +13,50 @@ // 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 *createTreeNode(const void *data, size_t dataSize) { + TreeNode *node = + malloc(sizeof(TreeNode)); // Speicher für neuen Knoten reservieren + if (node == NULL) + return NULL; // Abbrechen bei Fehler + + node->data = malloc(dataSize); // Speicher für Daten reservieren + if (node->data == NULL) { + free(node); + return NULL; + } + + memcpy(node->data, data, dataSize); // Standardfunktion string.h, kopiert + // size bytes von data nach node->data, + // daten dürfen sich nicht überschneiden + // speichern der Daten in node->data + node->left = NULL; // Kinder sind NULL + node->right = NULL; + return node; +} + TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) { - // isDuplicate initialisieren (auf 0 setzen) + // isDuplicate initialisieren (auf 0 setzen), verhindert Änderung am Baum if (isDuplicate) { *isDuplicate = 0; - } + } // bei 0: neuer Wert wurde eingefügt, bei 1: Wert war bereits im Baum // leerer Baum 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; + return createTreeNode(data, dataSize); } // mit compareFct <0 links >0 rechts =0 Duplikat - int cmp = compareFct(data, root->data); + int compare = compareFct(data, root->data); - if (cmp < 0) { + if (compare < 0) { // Eintrag links root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate); - } else if (cmp > 0) { + } else if (compare > 0) { // Eintrag rechts root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); - } else { - // isDuplicate auf 1 setzen + } else { // Duplikat + // isDuplicate auf 1 setzen, keine Änderung am Baum if (isDuplicate) { *isDuplicate = 1; } @@ -54,40 +70,42 @@ 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; + static StackNode *stack = NULL; // static -> behält Wert bei mehreren Aufrufen // Neue Iteration starten if (root != NULL) { - clearStack(&stack); + clearStack(&stack); // alte Stack-Inhalte werden gelöscht - TreeNode *curr = root; - while (curr != NULL) { + TreeNode *currentNode = root; + while (currentNode != + NULL) { // alle linken Knoten werden vom root an auf den Stack gelegt StackNode *oldStack = stack; - StackNode *newStack = push(stack, curr); + StackNode *newStack = push(stack, currentNode); if (newStack == oldStack) return NULL; // push fehlgeschlagen stack = newStack; - curr = curr->left; + currentNode = currentNode->left; } } if (stack == NULL) - return NULL; // alles durchlaufen + return NULL; // wenn Stack leer ist sind keine Elemente mehr vorhanden, + // Iteration beendet - // Oberstes Element abrufen - TreeNode *node = (TreeNode *)top(stack); + // oberster Knoten vom Stack + TreeNode *node = top(stack); stack = pop(stack); // Rechten Teilbaum pushen - TreeNode *curr = node->right; - while (curr != NULL) { + TreeNode *currentNode = node->right; + while (currentNode != NULL) { StackNode *oldStack = stack; - StackNode *newStack = push(stack, curr); + StackNode *newStack = push(stack, currentNode); if (newStack == oldStack) return NULL; // push fehlgeschlagen stack = newStack; - curr = curr->left; + currentNode = currentNode->left; } - return node->data; + return node->data; // Pointer auf Daten } // Releases all memory resources (including data copies). diff --git a/bintree.h b/bintree.h index 9e6b45c..aeb72ed 100644 --- a/bintree.h +++ b/bintree.h @@ -11,6 +11,8 @@ typedef struct node { struct node *right; } TreeNode; +TreeNode *createTreeNode(const void *data, size_t dataSize); + // 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). diff --git a/highscores.txt b/highscores.txt index aaac161..bda4db4 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1,10 +1,10 @@ Kristin;49209 -Kristin;9959 -Kristin;9944 -Kristin;7947 -Kristin;6962 -Kristin;5987 -Kristin;5975 -krisp;4986 -krisp;4985 -Kristin;4972 +krisp;29797 +krisp;29792 +Kristin;29782 +Kristin;19943 +krisp;19934 +krisp;19916 +kristin;19861 +Kristin;19858 +krisp;19460 diff --git a/main.c b/main.c index 34163d0..1dd21cf 100644 --- a/main.c +++ b/main.c @@ -1,90 +1,88 @@ -#include -#include +#include "highscore.h" #include "numbers.h" #include "timer.h" -#include "highscore.h" +#include +#include +#include // Read an unsigned integer from stdin with prompt (retries until valid). -int inputNumber(const char *promptText) -{ - unsigned int number; - int numberOfInputs = 0; +int inputNumber(const char *promptText) { + unsigned int number; + int numberOfInputs = 0; - while(numberOfInputs != 1) - { - printf("%s", promptText); - numberOfInputs = scanf("%u", &number); - while(getchar() != '\n') {} // clear input buffer - } + while (numberOfInputs != 1) { + printf("%s", promptText); + numberOfInputs = scanf("%u", &number); + while (getchar() != '\n') { + } // clear input buffer + } - return number; + return number; } // Print an array of numbers. -void showNumbers(const unsigned int *numbers, unsigned int len) -{ - if(numbers != NULL) - { - printf("Numbers:"); +void showNumbers(const unsigned int *numbers, unsigned int len) { + if (numbers != NULL) { + printf("Numbers:"); - for(int i = 0; i < len; i++) - printf(" %5d", numbers[i]); + for (int i = 0; i < len; i++) + printf(" %5d", numbers[i]); - printf("\n"); - } + printf("\n"); + } } -// Main game loop: generate numbers, ask user for duplicate, measure time, update highscores. -int main(int argc, char *argv[]) -{ - int exitCode = EXIT_FAILURE; +// Main game loop: generate numbers, ask user for duplicate, measure time, +// update highscores. +int main(int argc, char *argv[]) { + srand(time(NULL)); // seed für srand + int exitCode = EXIT_FAILURE; - if(argc != 2) - { - fprintf(stderr, "Usage: %s \n", argv[0]); - exitCode = EXIT_FAILURE; - } - else - { - const char *highscorePath = "highscores.txt"; - const char *playerName = argv[1]; - unsigned int *numbers = NULL; - unsigned int duplicate = 0; - double measuredSeconds; - unsigned int userInput; - unsigned int numberOfElements = 0; + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exitCode = EXIT_FAILURE; + } else { + const char *highscorePath = "highscores.txt"; + const char *playerName = argv[1]; + unsigned int *numbers = NULL; + unsigned int duplicate = 0; + double measuredSeconds; + unsigned int userInput; + unsigned int numberOfElements = 0; - // ask until valid number of elements (3..1000) - while(numberOfElements < 3 || numberOfElements > 1000) - numberOfElements = inputNumber("Wie viele Zahlen sollen gezeigt werden: "); + // ask until valid number of elements (3..1000) + while (numberOfElements < 3 || numberOfElements > 1000) + numberOfElements = + inputNumber("Wie viele Zahlen sollen gezeigt werden: "); - // create numbers and show them - numbers = createNumbers(numberOfElements); - showNumbers(numbers, numberOfElements); + // create numbers and show them + numbers = createNumbers(numberOfElements); + showNumbers(numbers, numberOfElements); - // measure time while user guesses the duplicate - startTimer(); - userInput = inputNumber("Welche Zahl kommt doppelt vor: "); - measuredSeconds = stopTimer(); + // measure time while user guesses the duplicate + startTimer(); + userInput = inputNumber("Welche Zahl kommt doppelt vor: "); + measuredSeconds = stopTimer(); - duplicate = getDuplicate(numbers, numberOfElements); + duplicate = getDuplicate(numbers, numberOfElements); - // check result and update highscores - if(userInput == duplicate) - { - int score = addHighscore(playerName, measuredSeconds, numberOfElements); - printf("Sie haben die korrekte Zahl in %.6lf Sekunde(n) gefunden und %u Punkte erzielt.\n", measuredSeconds, score); - } - else - printf("Leider ist %u nicht korrekt. Richtig waere %u gewesen.\n", userInput, duplicate); + // check result and update highscores + if (userInput == duplicate) { + int score = addHighscore(playerName, measuredSeconds, numberOfElements); + printf("Sie haben die korrekte Zahl in %.6lf Sekunde(n) gefunden und %u " + "Punkte erzielt.\n", + measuredSeconds, score); + } else + printf("Leider ist %u nicht korrekt. Richtig waere %u gewesen.\n", + userInput, duplicate); - loadHighscores(highscorePath); - showHighscores(); - saveHighscores(highscorePath); - clearHighscores(); + loadHighscores(highscorePath); + showHighscores(); + saveHighscores(highscorePath); + clearHighscores(); - exitCode = EXIT_SUCCESS; - } + exitCode = EXIT_SUCCESS; + } - return exitCode; + return exitCode; } \ No newline at end of file diff --git a/numbers.c b/numbers.c index 414a4a4..5c2f30a 100644 --- a/numbers.c +++ b/numbers.c @@ -3,18 +3,6 @@ #include #include #include -#include - -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; -} // TODO: getDuplicate und createNumbers implementieren /**Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an @@ -27,65 +15,77 @@ int compareUnsignedInt(const void *a, const void *b) { // 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. + +// vergleicht zwei Werte: ab: 1 a=b: 0 +int compareUnsignedInt(const void *a, const void *b) { + unsigned int x = *(unsigned int *)a; + unsigned int y = *(unsigned int *)b; + return (x < y) ? -1 : (x > y); +} + unsigned int *createNumbers(unsigned int len) { - if (len < 2) + if (len < 2) // Duplikat bei zwei Einträgen sinnlos return NULL; - unsigned int *arr = malloc(sizeof(unsigned int) * len); - if (!arr) + unsigned int *numbersArray = malloc( + sizeof(unsigned int) * len); // Speicher für das Ausgabearray reservieren: + // Größe eines Eintrags * Größe des Arrays + if (!numbersArray) // Speicher konnte nicht reserviert werden return NULL; - TreeNode *root = NULL; - srand((unsigned int)time(NULL)); + TreeNode *root = + NULL; // Binärbaum zum Generieren der Zufallszahlen ohne Duplikate - for (unsigned int i = 0; i < len - 1; i++) { - unsigned int num; + for (unsigned int i = 0; i < len; i++) { + unsigned int currentNumber; int isDuplicate; - - do { - num = (rand() % (2 * len)) + 1; + do { // mindestens eine Zufallszahl erzeugen + currentNumber = (rand() % (2 * len)) + 1; // Zahlenbereich 1 bis 2*len isDuplicate = 0; - - root = addToTree(root, &num, sizeof(unsigned int), compareUnsignedInt, - &isDuplicate); - - } while (isDuplicate); // nur akzeptieren, wenn eindeutig - - arr[i] = num; + root = addToTree(root, ¤tNumber, sizeof(unsigned int), + compareUnsignedInt, + &isDuplicate); // compareUnsignedInt wird zum Verwenden + // bei Vergleichen übergeben + } while (isDuplicate); // wenn isDuplicate gesetzt wird, muss eine neue Zahl + // erzeugt werden, die Schleife wird wiederholt + numbersArray[i] = currentNumber; } - // Jetzt gezielt EIN Duplikat erzeugen - unsigned int duplicateIndex = rand() % (len - 1); - arr[len - 1] = arr[duplicateIndex]; + // Ein zufälliges Duplikat erzeugen + unsigned int duplicateIndex = + rand() % len; // Index des Duplikats per Zufall bestimmen + unsigned int newIndex; + do { + newIndex = rand() % len; + } while (newIndex == duplicateIndex); // zweiten Index bestimmen, der nicht + // mit dem ersten übereinstimmt - clearTree(root); - return arr; + numbersArray[newIndex] = + numbersArray[duplicateIndex]; // Wert vom ersten Index kopieren + + 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) { if (!numbers || len < 2) - return 0; + return NULL; // Fehlerhaftes Array - unsigned int *copy = malloc(sizeof(unsigned int) * len); - if (!copy) - return 0; + TreeNode *root = NULL; // neuer Baum + unsigned int duplicateValue = 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]; + for (unsigned int i = 0; i < len; i++) { + int isDuplicate = 0; + root = addToTree(root, &numbers[i], sizeof(unsigned int), + compareUnsignedInt, &isDuplicate); + if (isDuplicate) { + duplicateValue = numbers[i]; break; } } - free(copy); - return duplicate; + clearTree(root); + return duplicateValue; } diff --git a/numbers.h b/numbers.h index 2315581..6708308 100644 --- a/numbers.h +++ b/numbers.h @@ -1,12 +1,16 @@ #ifndef NUMBERS_H #define NUMBERS_H -// 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. +int compareUnsignedInt(const void *a, const void *b); + +// 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); -// Returns only the only number in numbers which is present twice. Returns zero on errors. +// 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); #endif \ No newline at end of file diff --git a/test_binary.c b/test_binary.c index a0d9cbc..c7aca72 100644 --- a/test_binary.c +++ b/test_binary.c @@ -4,6 +4,7 @@ #include #include "bintree.h" + int compareUnsignedInt(const void *a, const void *b) { unsigned int x = *(unsigned int *)a; unsigned int y = *(unsigned int *)b; From 99a974cc9b200b367c5485fe3b1f0a4bf37d1849 Mon Sep 17 00:00:00 2001 From: Kristin Date: Wed, 10 Dec 2025 21:09:03 +0100 Subject: [PATCH 3/4] getduplicate neu --- numbers.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/numbers.c b/numbers.c index 5c2f30a..1fdae3f 100644 --- a/numbers.c +++ b/numbers.c @@ -71,21 +71,24 @@ unsigned int *createNumbers(unsigned int len) { // on errors. unsigned int getDuplicate(const unsigned int *numbers, unsigned int len) { if (!numbers || len < 2) - return NULL; // Fehlerhaftes Array + return 0; // Sicherheit: kein Array oder zu kurz - TreeNode *root = NULL; // neuer Baum + TreeNode *root = NULL; unsigned int duplicateValue = 0; for (unsigned int i = 0; i < len; i++) { int isDuplicate = 0; + + // Zahl in den Baum einfügen root = addToTree(root, &numbers[i], sizeof(unsigned int), compareUnsignedInt, &isDuplicate); - if (isDuplicate) { - duplicateValue = numbers[i]; - break; + + // Duplikat erkannt + if (isDuplicate && duplicateValue == 0) { + duplicateValue = numbers[i]; // das erste Duplikat merken } } - clearTree(root); - return duplicateValue; + clearTree(root); // Baum freigeben + return duplicateValue; // 0, falls kein Duplikat } From 9fb140fecf29e0811e9ee7e253efa52b70989f35 Mon Sep 17 00:00:00 2001 From: Kristin Date: Thu, 11 Dec 2025 16:16:52 +0100 Subject: [PATCH 4/4] =?UTF-8?q?cleartree=20angepasst,=20Kommentare=20volls?= =?UTF-8?q?t=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) {}