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;