From 1ab79ceb81eeafa8a4d33d583a8a7465c344ce74 Mon Sep 17 00:00:00 2001 From: Anton Timofeev Date: Wed, 17 Dec 2025 14:12:36 +0100 Subject: [PATCH] Add Unity unit tests for numbers and finalize sorting --- bintree.c | 152 +++++++++++++++++++++++++++++++++++- bintree.o | Bin 0 -> 2360 bytes doble | Bin 0 -> 35640 bytes exportToHTML/numbers.c.html | 151 +++++++++++++++++++++++++++++++++++ highscore.o | Bin 0 -> 4512 bytes highscores.txt | 2 + main.o | Bin 0 -> 2784 bytes makefile | 9 ++- numbers.c | 60 ++++---------- numbers.o | Bin 0 -> 2040 bytes stack.c | 31 ++++---- stack.h | 23 +++--- stack.o | Bin 0 -> 1088 bytes test_numbers | Bin 33888 -> 55744 bytes test_numbers.c | 100 +++++++++++++++++++----- timer.o | Bin 0 -> 1040 bytes 16 files changed, 435 insertions(+), 93 deletions(-) create mode 100644 bintree.o create mode 100755 doble create mode 100644 exportToHTML/numbers.c.html create mode 100644 highscore.o create mode 100644 main.o create mode 100644 numbers.o create mode 100644 stack.o create mode 100644 timer.o diff --git a/bintree.c b/bintree.c index 5cf82a9..ca05ad8 100644 --- a/bintree.c +++ b/bintree.c @@ -8,29 +8,177 @@ * `treeSize`: zählt die Knoten im Baum (rekursiv), * `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */ + + +//Hilfsfunktion für addToTree. Erstellt eine treenode. +static TreeNode* createTreeNode(const void *data, size_t dataSize) +{ + TreeNode* newNode = calloc(1, sizeof(TreeNode)); + if(!newNode) + { + return NULL; + } + newNode ->data = malloc(dataSize); + if(!newNode->data) + { + free(newNode); + return NULL; + } + memcpy(newNode -> data, data, dataSize); + return newNode; +} + // 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). +// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). (auf 1 wenn duplikat geaddet) TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) { - + if(!root) + { + TreeNode *newNode = createTreeNode(data, dataSize); + if(isDuplicate != NULL) + { + *isDuplicate = 0; + } + return newNode; + } + int compare = compareFct(data, root-> data); + if(compare < 0) + { + root -> left = addToTree(root -> left, data, dataSize, compareFct, isDuplicate); + } + else if(compare > 0) + { + root -> right = addToTree(root -> right, data, dataSize, compareFct, isDuplicate); + } + else + { + if(isDuplicate != NULL) + { + *isDuplicate = 1; + return root; + } + //Konvention: rechts ist >= also das Duplikat wird nach rechts verfrachtet. + root -> right = addToTree(root -> right, data, dataSize, compareFct, isDuplicate); + } + 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. +// Wir brauchen eine statische Variable, die überdauernd existiert +// (Alternativ kann man diese auch global ausserhalb definieren) +// Die statische Variable (das Gedächtnis) muss außerhalb oder static innerhalb sein + +/* + * nextTreeData - Iterative In-Order Traversierung (wie strtok) + * * Funktionsweise: + * 1. Initialisierung (root != NULL): + * - Löscht alten Stack. + * - Wandert von root so weit nach LINKS wie möglich. + * - Pushed alle Knoten auf dem Weg auf den Stack. + * -> Das kleinste Element liegt nun oben. + * * 2. Iteration (root == NULL): + * - Pop: Nimmt oberstes Element vom Stack (aktuell kleinstes). + * - Logik: Hat dieses Element einen RECHTEN Nachbarn? + * -> JA: Gehe eins nach rechts, dann wieder alles nach LINKS pushen. + * -> NEIN: Nichts tun (der Elternknoten liegt schon als nächstes auf dem Stack). + * - Gibt die Daten des gepoppten Elements zurück. + */ +static StackNode *iteratorStack = NULL; + void *nextTreeData(TreeNode *root) { + //neuer Baum wird übergeben (root != NULL) + if (root != NULL) + { + // 1. Aufräumen: Falls noch Reste vom letzten Mal da sind + if (iteratorStack != NULL) { + clearStack(iteratorStack); + iteratorStack = NULL; + } + // 2. Initial befüllen: "Push root and all left nodes" + TreeNode *currentNode = root; + while (currentNode != NULL) + { + + iteratorStack = push(iteratorStack, currentNode); + + // Immer weiter nach links absteigen + currentNode = currentNode->left; + } + } + + // PHASE 2: Iteration (Nächsten Wert holen) + + // Wenn der Stack leer ist (oder leer war), sind wir fertig. + if (iteratorStack == NULL) + { + return NULL; + } + + // 1. Wir schauen uns das oberste Element an (der nächste Knoten in der Reihe) + // Wir wissen, dass es ein TreeNode* ist, also casten wir. + TreeNode *nodeToReturn = (TreeNode*) top(iteratorStack); + + // 2. Wir entfernen ihn vom Stack (er ist jetzt "verarbeitet") + // Auch hier: pop gibt den neuen Head zurück, also variable aktualisieren! + iteratorStack = pop(iteratorStack); + + // 3. Wir retten die Nutzer-Daten (z.B. den Integer), bevor wir weiterwandern + void *userData = nodeToReturn->data; + + // 4. Nachfolger suchen (Die Logik für In-Order: Rechts, dann alles links) + if (nodeToReturn->right != NULL) + { + TreeNode *currentNode = nodeToReturn->right; + while (currentNode != NULL) + { + // Auch hier: Stack aktualisieren + iteratorStack = push(iteratorStack, currentNode); + currentNode = currentNode->left; + } + } + + // Wir geben die echten Daten zurück (nicht den Knoten, sondern den Inhalt) + return userData; } // Releases all memory resources (including data copies). + +// Gibt den gesamten Speicher (Knoten + Daten) frei void clearTree(TreeNode *root) { + if (root) + { + // 2. Rekursion: Erst tief in den Baum absteigen (Post-Order) + clearTree(root->left); + clearTree(root->right); + // 3. Jetzt sind die Kinder weg. Wir kümmern uns um den aktuellen Knoten. + + // Erst den Inhalt (die Datenkopie) löschen! + // (free(NULL) ist in C erlaubt, daher müssen wir nicht zwingend auf NULL prüfen, + // aber es schadet auch nicht). + free(root->data); + + // 4. Dann den Container (den Knoten selbst) löschen + free(root); + } } // Returns the number of entries in the tree given by root. unsigned int treeSize(const TreeNode *root) { + // Abbruchbedingung: Wenn kein Knoten da ist, ist die Größe 0 + if (root == NULL) + { + return 0; + } + // Rekursionsschritt: + // 1 (für den aktuellen Knoten) + alles im linken Baum + alles im rechten Baum + return 1 + treeSize(root->left) + treeSize(root->right); } \ No newline at end of file diff --git a/bintree.o b/bintree.o new file mode 100644 index 0000000000000000000000000000000000000000..f1ce014227b773256f1f55249ae34d132c781271 GIT binary patch literal 2360 zcma)8O=w(I6h1F+l1xnOSXxXgm_+O%iws2B-Yq>Jfp2D)&eFj*;NQ&14QD0P>lT|A+JV5Re<&z*UhwBUvN&iT&& zJ?FkR^UFVf{5wJ95EefY*ezyeu(6I~zofMq9(Xj^0qd67)CG@1#@l5jmQq1sH88xv z*)!*}eQdc0;=u8SAY2_GdYY99sxq-lsrOb^EC5w1Gnbv~3v3<9zNl9Viw2LRRIXgA z__;t`T>5BnDX-LgCgy4y13_Jcw}#Ex7H~+gytv%nItA_+w#kzM^OV-H5zE)%cNp|C z3ao>UW1q$5#qoG^E61?oX8`6TethQ(NXj)$AVANp$|WIDBJTJJLvb5 z^&6w;sMH2OUFYwJJ4@BKW>G80<~q@JQ^P}IwPLY2r_IZL%-3tG-C4^t(Z`J+U3Ig& zP3Y%Pvs0su9rSM(eVU=_4acqC(0y~!H`j~S$@KIG#CZ~NcF;4{vksR*+a%Gi>teUV za_HIqG1wbBFWSX<_TcMM^(*VYzqZ$!sL9k;<5>?kJE)ast!L|+zTobB$@$P1-6zH& z?f~)3xGu~D^NsrFpVH@VU}lZD56;X!JWK6|`uIF-m&A-4xL<#DyOSKp=3I~UVpilK z`qs;h^VQv{b{y-NE@C2AIEnboV}6YxQ@_O_?lR{Jaj*8(>6-ZVKAV1`@37-K+0WJ) zPIBGxd7o)^YclT|&)Y#yF>ln2I~rY=elXAX`abTE=2720%S&JF+_}ci+8pA_tOo88 zzhAvRZBMrz=QD9{5&v(*OeW|s=C!3|$nz)XN$K}xya9WTU*A@(&RYLIU_QNd76w@I zRqlyNiKzpm=Z74*(e7 zGxT&z@VB6cpuZ-#4*CS}6~UW^o~{bMBseel9Z-&+6+AEclY&ox;#-`a5qwPa6M~b1 ze@1`sZBAbU<#T)nirJ-$pm>kdFW}r@(^W%97KD02XM}>V-N-kfhrrmi0EV%h({aYg zZGYD`2k;k+(K|cox51`j@!k+@=T;SbS8QGpZ0E+mM=^I=9l&^>_vteOxH5q8GrrGW z`U9z1oGYG>R8X#vs_;XpQlXTqe5`U8J|MLi6qfyra$E*A>t z7C$MFdLNuvWHsyO^VzatbIS!kC@}wKIS;FnUo4h$uok+6zbmZG_<>Kwpj0`fpU>;( GbMzleSqiHF literal 0 HcmV?d00001 diff --git a/doble b/doble new file mode 100755 index 0000000000000000000000000000000000000000..b3bff351d7e4dbdefdd684db2e3d11688ca0d316 GIT binary patch literal 35640 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 literal 0 HcmV?d00001 diff --git a/exportToHTML/numbers.c.html b/exportToHTML/numbers.c.html new file mode 100644 index 0000000..0b3baea --- /dev/null +++ b/exportToHTML/numbers.c.html @@ -0,0 +1,151 @@ + + +numbers.c + + + + + +
+ +numbers.c +
+
#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include "numbers.h"
+#include "bintree.h"
+
+//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.
+// Vergleichsfunktion für qsort
+static int compareUnsignedInt(const void *a, const void *b)
+{
+const unsigned int *x = (const unsigned int *)a;
+   const unsigned int *y = (const unsigned int *)b;
+
+   if (*x < *y) return -1;
+   if (*x > *y) return 1;
+   return 0;
+}
+
+// Fisher-Yates Shuffle Algorithmus zum Mischen des Arrays
+static void shuffleArray(unsigned int *array, unsigned int n)
+{
+   if (n > 1)
+   {
+       for (unsigned int i = n - 1; i > 0; i--)
+       {
+           unsigned int j = rand() % (i + 1);
+           unsigned int temp = array[i];
+           array[i] = array[j];
+           array[j] = temp;
+       }
+   }
+}
+
+unsigned int *createNumbers(unsigned int len)
+{
+   if (len < 2) return NULL;
+
+   // 1. Array reservieren
+   unsigned int *numbers = malloc(len * sizeof(unsigned int));
+   if (numbers == NULL) return NULL;
+
+   // Hilfsvariablen für den Baum
+   TreeNode *root = NULL;
+   int isDuplicate = 0;
+   unsigned int count = 0;
+
+   // 2. PHASE 1: Erzeuge (len - 1) EINZIGARTIGE Zahlen mit Hilfe des Baums
+   // Wir nutzen den Baum als "Türsteher"
+   while (count < len - 1)
+   {
+       // Zufallszahl generieren (1 bis 2*len)
+       unsigned int value = (rand() % (2 * len)) + 1;
+
+       // Versuchen, in den Baum einzufügen
+       // Wir übergeben &isDuplicate, damit der Baum Duplikate ABLEHNT.
+       root = addToTree(root, &value, sizeof(unsigned int), compareUnsignedInt, &isDuplicate);
+
+       // Prüfen: War es ein Duplikat?
+       if (isDuplicate == 0)
+       {
+           // Nein, es war neu! -> Ins Array schreiben
+           numbers[count] = value;
+           count++;
+       }
+       // Falls isDuplicate == 1, machen wir einfach weiter (while-Schleife läuft weiter)
+   }
+
+   // 3. PHASE 2: Das garantierte Duplikat erzeugen
+   // Wir wählen zufällig eine der bereits existierenden Zahlen aus
+   unsigned int randomIndex = rand() % (len - 1);
+   unsigned int duplicateValue = numbers[randomIndex];
+
+   // Wir schreiben das Duplikat an die allerletzte Stelle
+   numbers[len - 1] = duplicateValue;
+
+   // Optional: Duplikat auch in den Baum einfügen (Modus: Akzeptieren / isDuplicate = NULL)
+   // Damit der Baum konsistent zum Array ist (falls man ihn später noch braucht).
+   root = addToTree(root, &duplicateValue, sizeof(unsigned int), compareUnsignedInt, NULL);
+
+   // 4. Mischen
+   // Da das Duplikat jetzt immer ganz am Ende steht, müssen wir mischen.
+   shuffleArray(numbers, len);
+
+   // 5. Aufräumen
+   // Der Baum war nur ein Hilfsmittel zur Überprüfung. Er wird jetzt gelöscht.
+   // WICHTIG: Damit verhindern wir Memory Leaks [cite: 12]
+   clearTree(root);
+
+   return numbers;
+}
+
+// ... Hierunter bleibt die getDuplicate Funktion deines Kollegen unverändert ...
+// Sie ist korrekt implementiert laut Aufgabenstellung (mit qsort)[cite: 11, 43].
+unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
+{
+ if (numbers == NULL || len < 2) {
+   return 0;
+ }
+
+ unsigned int *copy = malloc(len * sizeof(unsigned int));
+ if (copy == NULL) {
+   return 0;
+ }
+
+ memcpy(copy, numbers, len * sizeof(unsigned int));
+
+ qsort(copy, len, sizeof(unsigned int), compareUnsignedInt);
+
+ unsigned int duplicate = 0;
+
+ for (unsigned int i = 0; i + 1 < len; ++i) {
+   if (copy[i] == copy[i + 1]) {
+     duplicate = copy[i];
+     break;
+   }
+ }
+
+ free(copy);
+ return duplicate;
+}
+ + \ No newline at end of file diff --git a/highscore.o b/highscore.o new file mode 100644 index 0000000000000000000000000000000000000000..f9053456c239b1f382121aac16b0b66cfb504c5b GIT binary patch literal 4512 zcmc&&Z){Ul6hGZ#tibrQ3^HJ_Jsi_A*u?)c^1{Q8IFq7gEQSxvN9oGCP}bQNnHkY0 zHEIk|mY~tZU`hDUq9jY?!<`4PqeI6Ahx#qc*HzxNQ`%FGjKd!Lr!OaxKHn4a|XayB-pS-;GEPsm+WrkJF$8Tc^+A5zHM8E^B1uz{SpCJo({Fx+)!)>B8>wAY&O ztN~)4ZkNmxd_Du7tV&E@)wFXwj}2M#9(tDNEsj2)!CYca&4oF&OcC6fOKYBGTO4az z10qK@$G^tR&LGY$K*Vqu`Yhtk+C)#W%^Y-j^y9g(x3W@}EslCKbDB%cmE^gqu{T`z z?+vV5uAYkdX4u90IO|kz7Lm&=+sw=LNhj%2`Py(^*vHCs!L{P-2lk!UhVx`MQug20 zBiCrc=iOKn>9dzE0<8z?aGL2l%x06k?>FPvJ+S@ddO1?JBF@sOrI5Tb+-FT4_ zJ?`Z{u1{-C&R*bnxzBZ+r&My|EU(p!Mq_P=wXK>8o+Zc$a)XL>-5~5~uT9*>zDfgc z0ncNdzrtM1Z%FxdM#$OLqp;NhTkWv5Z8;UT*1`4~*j`t%UGic7LOz`O&bx7f_d~|p z2j3GtTei^a_D;%Pm**gz?3+c5f7mr&tY_ZvnR`}Ki z-#qY5#mfGuT%1Gx9+VI6qwWjN9nXRuD4PSr387_`?XXd?D_dy3aotq;yZVXi^MG}C~yqvEeG#n1Q0eEg6*@zr?`;brym#ND7=7vgM1}iSU`VK>UXeymGeXs zJ>_q$d=yPB;NNBGQBL%~&%X=u{kMGq{blGe$oCU)BT@U5-)?X25`~+lwc)vaZJPv#q7?#)%giF2y0u6q{HbcJ+r~^GfOznfu zjK(S;`&BEjFDK-SCncsNCL|t^XiC&20@&W-^Y~eTs>%o&E8vj&J~_*J@ZS(57w*da z)j8(;tU!RBSWGS!D(lrb{+jhji29zmCH3l@e$0B*O|jt^*xh=k1HWl_fm)C>YjL6 za)48I;+OlYdj@xb!_~cX8XW5R(gIS>Co1$yD)e_N^t=zt$2U~)_bT`g6`UU~<>N0_ z=-;m3A6D@33jRq2Co2#Q`s2aw!GTaL5QzqN55=Qzl67bx7>|(^3q_92tH1-{pg&qJ zi22_rjYWrW#NS`8cfLxar7moKFc_n-)q(GGOc0L-jtpbI$Z&ATp<#*fNElz)=->|= zwgREU)*=5OBp48n92T1BP+<5?)?xfGKKA2>$WnMH5RSxxWcm9`{=k2KIB+zKc=vLw zGM?UOP;~5#h-OG7L(p<329Elp{bUW{&k9y{`Qv^WOUJXS(Wx5GsK(Q(@f3yQM~0tN c6b;ZP6h#B{aYfMpeN0g_K)27+?O00s8+t*2AOHXW literal 0 HcmV?d00001 diff --git a/highscores.txt b/highscores.txt index 213846a..16d8f29 100644 --- a/highscores.txt +++ b/highscores.txt @@ -2,4 +2,6 @@ anton;39632 player_name;39611 lukas;35728 anton;9956 +anton;9944 +Anton;9940 player1;3999 diff --git a/main.o b/main.o new file mode 100644 index 0000000000000000000000000000000000000000..f3ad2af569c34a3f06ae353d2036f52575652483 GIT binary patch literal 2784 zcmb7GPiz!r6o1RMb&Ej3RzUuA$HYyFrUjuOHY{lbmBWNIP=hhTFzkNaopg3~J2Ol9 zcW6=%c%z0yF2)i)EXIQe4!iLHNj>Pva8Zw|5VJKX#u&3zYW=;P?<>Rn{VIj*MI)}_Zp%YVeq33v&w>oiSZ2P{+6{xAA5}O0*vpZkK#{2$1~1G48!on zIX{pCKKkmLqmQ_f>Z<~YL_XPEL-yLCS#tHJ0Y+&f>*YHx{R9W_CK+TfZdwfc z)lpX?Ib56HiQG8t3ZiN|otoxo}3f-VkZ2y;)jK zZ+K=-3~4D(J5aLC^TO2}vmg$xro5HQdzqpuya69==!7M-vzD-h_LiBqg`;^zn;|DI z2rK7nlfumkXGo(H!p`IaFKxV7DEL~oSSktI*UlDQ*pDMn-aLb)SxDnW*A?Tw^tT)> zHL%Yf(~gVrvXd2k&JH9PW6{y@)KX<_r0lT2a4(=5e_%D~!pfp-%k$anSed-9!VYN1 zm|8h)(iE;>drnLWPdHeo#^peWbUPxcr)&RV$NOuI+W|hd{tGm&ZnR?b4MHdDuL8FL zZvxTJ`YS+uEBZeM;=Sv$0j8&<{t^&X>gNJXzYTl}{)51cz~_Lyz->VEzy8fYv_`!r z!1Q|HcIejt*8?B&r2yUsvVQ}J-{l$ypIGBEnaU6Fnu4V!+QMo_#3I;3o!ke)PD*@zt$@OrcVRWfcnt~Xe)38h|+aE z!1Mti$J-A?3VkrZ^l*S3nnVEGI|lJshpEOX2+Q%wnM%v`8LUalzgq^4(T$?KB8F8Q~T=OiDJ@vD-jBv&i@(0cK)V@`9~4{d4#_k;YTB!-*-6P!3e(@;kdgi{6&OM zL^v54p`ac~*qET{N>HZW{ym_kH4EqLA2yz zNs5+JD*Hh)GIGMtZ7#Rw^jOl=4#o=CA_4BeM;D?gh3_jA=@vMb}I@2^hHG>fbLqRyKtgJ{{W{^9~S@s literal 0 HcmV?d00001 diff --git a/makefile b/makefile index 1f15f75..a08d448 100644 --- a/makefile +++ b/makefile @@ -35,9 +35,14 @@ $(program_obj_filesobj_files): %.o: %.c # -------------------------- # Unit Tests # -------------------------- -unitTests: - echo "needs to be implemented" +unitTests: test_numbers + ./test_numbers + +test_numbers: test_numbers.c numbers.c bintree.c stack.c unity/unity.c + gcc -Wall -Wextra -std=c99 -Iunity \ + -o test_numbers \ + test_numbers.c numbers.c bintree.c stack.c unity/unity.c # -------------------------- # Clean # -------------------------- diff --git a/numbers.c b/numbers.c index ead4cb0..6843f72 100644 --- a/numbers.c +++ b/numbers.c @@ -11,10 +11,7 @@ * 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. -// Vergleichsfunktion für qsort +//Vergleichsfunktion von qsort static int compareUnsignedInt(const void *a, const void *b) { const unsigned int *x = (const unsigned int *)a; @@ -25,7 +22,7 @@ const unsigned int *x = (const unsigned int *)a; return 0; } -// Fisher-Yates Shuffle Algorithmus zum Mischen des Arrays +//Mischen des Arrays static void shuffleArray(unsigned int *array, unsigned int n) { if (n > 1) @@ -39,91 +36,68 @@ static void shuffleArray(unsigned int *array, unsigned int n) } } } - +//Wenn weniger als zwei Zahlen unsigned int *createNumbers(unsigned int len) { if (len < 2) return NULL; - // 1. Array reservieren +//Dynamisches Array unsigned int *numbers = malloc(len * sizeof(unsigned int)); if (numbers == NULL) return NULL; - - // Hilfsvariablen für den Baum +//Variabelen für den Binärbaum TreeNode *root = NULL; int isDuplicate = 0; unsigned int count = 0; - // 2. PHASE 1: Erzeuge (len - 1) EINZIGARTIGE Zahlen mit Hilfe des Baums - // Wir nutzen den Baum als "Türsteher" + while (count < len - 1) - { - // Zufallszahl generieren (1 bis 2*len) + { //Zufallszahlen generieren unsigned int value = (rand() % (2 * len)) + 1; - // Versuchen, in den Baum einzufügen - // Wir übergeben &isDuplicate, damit der Baum Duplikate ABLEHNT. + root = addToTree(root, &value, sizeof(unsigned int), compareUnsignedInt, &isDuplicate); - // Prüfen: War es ein Duplikat? if (isDuplicate == 0) - { - // Nein, es war neu! -> Ins Array schreiben + { //in array schreiben falls kein Duplikat numbers[count] = value; count++; } - // Falls isDuplicate == 1, machen wir einfach weiter (while-Schleife läuft weiter) - } - // 3. PHASE 2: Das garantierte Duplikat erzeugen - // Wir wählen zufällig eine der bereits existierenden Zahlen aus + } + //Duplikat erzeugen unsigned int randomIndex = rand() % (len - 1); unsigned int duplicateValue = numbers[randomIndex]; - - // Wir schreiben das Duplikat an die allerletzte Stelle numbers[len - 1] = duplicateValue; - - // Optional: Duplikat auch in den Baum einfügen (Modus: Akzeptieren / isDuplicate = NULL) - // Damit der Baum konsistent zum Array ist (falls man ihn später noch braucht). root = addToTree(root, &duplicateValue, sizeof(unsigned int), compareUnsignedInt, NULL); - - // 4. Mischen - // Da das Duplikat jetzt immer ganz am Ende steht, müssen wir mischen. + //Array mischen damit duplikat nicht am Ende immer ist shuffleArray(numbers, len); - // 5. Aufräumen - // Der Baum war nur ein Hilfsmittel zur Überprüfung. Er wird jetzt gelöscht. - // WICHTIG: Damit verhindern wir Memory Leaks [cite: 12] clearTree(root); - return numbers; } - -// ... Hierunter bleibt die getDuplicate Funktion deines Kollegen unverändert ... -// Sie ist korrekt implementiert laut Aufgabenstellung (mit qsort)[cite: 11, 43]. +//get Duplicate unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) { if (numbers == NULL || len < 2) { return 0; } - +//Kopie vom Array anlegen unsigned int *copy = malloc(len * sizeof(unsigned int)); + if (copy == NULL) { return 0; } - memcpy(copy, numbers, len * sizeof(unsigned int)); - qsort(copy, len, sizeof(unsigned int), compareUnsignedInt); - unsigned int duplicate = 0; - +//Duplikat finden for (unsigned int i = 0; i + 1 < len; ++i) { if (copy[i] == copy[i + 1]) { duplicate = copy[i]; break; } } - +//Speicher freigeben free(copy); return duplicate; } \ No newline at end of file diff --git a/numbers.o b/numbers.o new file mode 100644 index 0000000000000000000000000000000000000000..623d87a9a0b3ee83fe3cf96bf9c221d14a52eda8 GIT binary patch literal 2040 zcmb7FU1(cn7=F|A=ftX^Yq7e*x(hGbLfHI+2^NmFVwECOGuRMzmL;c4ZIU)WWi3Gs z3&Olx#0xJ|@giqeUQEb=fnsj-YHWg6B8dt+EqJGp2=Vwl=O-qiUigylJm33%@BjDa zoO^%${`aFI0Rizbik0N%G#2P7EX&y)|F}W}&`rmKh|f0PC9ZbQT`e19s?#()Ggp7)_E)vTfjwKs5x~5{ukLRf&1O! zsL>4uD%F+wdTm9kDp`(^zT+&r1D!{Dzt4Pjy12EYXNz|i8G5h$ma<07WS9wj7vY3m&ebxJxe>* z5MnNU@vLbvS+LsET$E9ecp!68?afpv{WC?2cz-8&!-9>2heqSwd2Ht ztcLzE$7)$?cZ;hA`d#@ZsQqX+4k)IZn^;^cK)t>Y;ZtHjp_q&!{Hi_TqPoBSyC@l`3*P@b4bA8l&z#IkNzs zJ#zZY9t9-(ao;^6cN0CG8t5tdS3|viPf?r8qo?e#fwLpnId?V5K7+>@`Cc3^?ytBz z%DTl@j9%_R&TP==qLyk9xi?PLYeB93oyZ;P)*6=wXSgw6f6kpJt(D5oI8b_vQ|*J-9M8&vr(^&8lBux4`yQW4^MjtpxyXKz{j!i=?Rbb`@|!j`+fP4JQDQZ`%B=%efF<;yx%9xA>;IDV~Bru zh`%tzUmxP}#Tf9H9pXjHCwDhCQu@oeTx?&oY<@de5ceaN(=TN5o7XaW;`Iz=IXza; z-`q`K)pL1#IJLB%j_>Si@#L0h*Yv{b?oMhm4i(Whayp*zlpf1Pooy_Uh;F;vTr86i UEgegxw&Rj2q<5Zip1c6iKl)L~IsgCw literal 0 HcmV?d00001 diff --git a/stack.c b/stack.c index e3a90d4..282c14a 100644 --- a/stack.c +++ b/stack.c @@ -1,33 +1,34 @@ #include #include "stack.h" -//TODO: grundlegende Stackfunktionen implementieren: -/* * `push`: legt ein Element oben auf den Stack, - * `pop`: entfernt das oberste Element, - * `top`: liefert das oberste Element zurück, - * `clearStack`: gibt den gesamten Speicher frei. */ - -// Pushes data as pointer onto the stack. StackNode *push(StackNode *stack, void *data) { - + StackNode *node = malloc(sizeof(StackNode)); + if (node == NULL) return stack; + node->data = data; + node->next = stack; + return node; } -// 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) { - + if (stack == NULL) return NULL; + StackNode *next = stack->next; + free(stack); + return next; } -// Returns the data of the top element. void *top(StackNode *stack) { - + if (stack == NULL) return NULL; + return stack->data; } -// Clears stack and releases all memory. void clearStack(StackNode *stack) { - + while (stack != NULL) { + StackNode *next = stack->next; + free(stack); + stack = next; + } } \ No newline at end of file diff --git a/stack.h b/stack.h index f7d542d..1f39743 100644 --- a/stack.h +++ b/stack.h @@ -1,25 +1,22 @@ #ifndef STACK_H #define STACK_H -/* A stack is a special type of queue which uses the LIFO (last in, first out) principle. -This means that with each new element all other elements are pushed deeper into the stack. -The latest element is taken from the stack. */ +// Eigener Stack-Knotentyp, damit es keinen Konflikt mit bintree.h gibt +typedef struct stack_node { + void *data; // Nutzdaten + struct stack_node *next; // Zeiger auf das nächste Element im Stack +} StackNode; -#include - -//TODO: passenden Datentyp als struct anlegen - -// Pushes data as pointer onto the stack. +// Legt ein Element oben auf den Stack StackNode *push(StackNode *stack, void *data); -// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be -// freed by caller.) +// Entfernt das oberste Element und gibt den neuen Stack-Kopf zurück StackNode *pop(StackNode *stack); -// Returns the data of the top element. +// Liefert die Daten des obersten Elements (ohne zu entfernen) void *top(StackNode *stack); -// Clears stack and releases all memory. +// Gibt den gesamten Stack frei void clearStack(StackNode *stack); -#endif +#endif // STACK_H \ No newline at end of file diff --git a/stack.o b/stack.o new file mode 100644 index 0000000000000000000000000000000000000000..f1cc76c588d27162a75d9458f2739fd5e444b96e GIT binary patch literal 1088 zcmb7Dze`(D6h29sCN`oS1g%gS=pqzBJ2|G+LI(#y2e;esnv&v+3Hn4KOCU?uK>q+o zv$t~tUEEqbI6t>IxR$)a>+AR3oJ&%5=^^L$Ip00^zLW32Z~jb+qy$9q09>U}1cRP{ z2iCe@oZC*3j%w%UP)<&3n=wJ{ zIodz|xc}am%?+2Meycbw4gLTaajFo!Bgl#lDVWe?`xfo{`U%q5?yd zi|5{pxh@xOPKTACH%lzcmrsqb*c$>TS=U+GymzV>!w*q!?}t3T-)CprIq(MTvvUBC zbNxz^`MCM2m*CBKugM4ZM~;5#aYo~!t9K{g*HV6CdHnB=Ff^n9ZI0BPetZY+!15{b z)Z88X50>9SGgVSuR1Ib0tI#tjaP)#cmJ07+iTgGS+nvunqwnrBuf8pYU>oy&4LsGD vy7K&%FD9rr#55>8zfwNf4$9sh0!N2cF&_>p6*0B4@7F!?gIZ(N$`z5nNHo5V literal 0 HcmV?d00001 diff --git a/test_numbers b/test_numbers index 68278c1a5187c4d42c6a3305a8e123ca9644a82f..df9c41fbacb04362bc4155d08280e12dff5ec35b 100755 GIT binary patch literal 55744 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 Y4^}*KTiMh*22FnMm5vr~o;2$J0YTy!i~s-t literal 33888 zcmeI5U2IfE6vxl*wsc#dtx!c#+tpYsXe{wt9?T+CK(R$WO#Pg;ySMGq?zY^$D^^ff zDhWnSSmi-u)Z&Y+UonVgn`mroVl)vAn5Z#IiW=EsjL}H!8teK$bMKbBi|7MSCTEg! zXU@!-bI<(F+-+a(olpPx>909N9zyX#&VU3;h;~u{EuwQEt079QTfVC4j;8f3+*?@m zPRk6P|7_z@^X9DZIu9;Fo z$(c49O2w^2M|`HM*x!eK+h3bw!MfX@-|+{Ax+oQjTV^EIHKP}HO2aAr1!1d8(4OyTGz$%&oGB;v+1fSDH#eJ z27dJY+?{AwLIM!p7mbOy+1MNDXbcbZhM{vg7s7Ge`r7lQ-%MY>|LM6Ut77B#(&gw2 zKsW}XDl``AHnS(sCnZZzx$oD2^|7BehXIL*ptvz3qk(tUWd6Q=jL2 z9x(8YOhX@9QI{TGfjG-)3lQo!-y5u(0{$BAr{fQP_8I%E0*k6(b{E+!*yeWFAVPb+ z3$R}HgY{lG%l5=ylGgQD&B#?fBs}!I$>qb-3Za zljzsn=G$X?ome>!%nHwMjpoO8%n$y40zb|}hUh9ihPmLMJqG^`1546g%=r>FdW`SM z^RS)+=zGD5+Z}JFj7FdNr+%LkyAS@$?D#Hla{k0A?2p^AWwkx;2aXH#IWFdmeK^H& zVJ}WiZ(A{foSmFIU)|K+@!IsTPfdMDw4d#V$L}f3CHBB|PCw_e4e{jn^-L~dvlKQH z*q?jhi+y-u>!ak8&DtLEpzny!|MCtzFL?HMhXNO*Hejqccg%2vW57OmKc7F|_xb#x zeGKiJV7K`8&D!pWlS_Wq@^+`n=}~awI4{AyIk)@_YEI+4$6cK8oKMWB>=E9#^MiPf z?fr`!I?uGuRd%t*&ew}h41P+^%QVs`ev51DXTQ*H#J%re2NpFs)EvV^V{kP8jDhFw zYHu)0-n!3qdzPzR;c8d9+VfoPvs~?ku6C{6zR~FJHOys!kZH7AMsp(CVVLoNX;=v} zW`qOHo7S$apeFNvBhh6U@xXG^Y#&%wLG_6MRnRJ4)$!v-Y;D!3P99wGbRs z?pX%83DOD)LrmBzrJ_bO)IXp?-94l_O~W7+ZSU>v3z6zKBQdL!)RuUkX^}G9V_{Np zyRsrt1M@w~J|~wyRN$lUD{vXA#AO1Jm#ApBGVU`%3CmF3Mtj&Wsl4FCUYgrwSo#d! z5RUPsdC~SrjQG&+3I8MBcYMS4=MSK7g;WB>YPe+{JW%DS#?{u((mGLCpQ=t&@8|)1 z7=i6^?mX;CpW(|o&V=TEZtAiMSGRskk-n)&zq?2W&Vu=yi}Wo;I)A@`zumy!ZQvZ2 zL-_n*KKGu_ivO?i01|gHTvZ5H6~IMS0r&LstwMd#{&v&Y6pKf?aM1Fan1x_n<&VR2 z#y|qcgwL?8K_BnJo#e&t_3G3a7{@Nu1xw#C7Vzq2J6-=)m2^9!9vtj!shEBAGyVBX z{L+@AUv|7ZwC|m-554m7;it~2TRLg@y?^dH`_6+)#$S8r)qSmfA53u-Lxsim@f^2o1?*4I9~?)R#S#id8@sQuyXSI*qJ$vV{FK>HgJ(J*-c diff --git a/test_numbers.c b/test_numbers.c index 66625a4..891849a 100644 --- a/test_numbers.c +++ b/test_numbers.c @@ -1,30 +1,94 @@ -#include #include #include + +#include "unity.h" #include "numbers.h" -int main(void) +void setUp(void) { - srand((unsigned int) time(NULL)); // für echte Zufallszahlen +} +void tearDown(void) +{ +} + +static unsigned int countOccurrences(const unsigned int *numbers, + unsigned int len, + unsigned int value) +{ + unsigned int count = 0; + for (unsigned int i = 0; i < len; ++i) { + if (numbers[i] == value) { + count++; + } + } + return count; +} + +void test_createNumbers_returns_non_null(void) +{ unsigned int len = 20; unsigned int *numbers = createNumbers(len); - if (numbers == NULL) { - printf("Fehler: createNumbers returned NULL\n"); - return 1; - } - - printf("Erzeugtes Array:\n"); - for (unsigned int i = 0; i < len; i++) { - printf("%u ", numbers[i]); - } - printf("\n"); - - unsigned int d = getDuplicate(numbers, len); - - printf("Gefundenes Duplikat: %u\n", d); + TEST_ASSERT_NOT_NULL(numbers); free(numbers); - return 0; +} + +void test_createNumbers_value_range(void) +{ + unsigned int len = 30; + unsigned int *numbers = createNumbers(len); + + TEST_ASSERT_NOT_NULL(numbers); + + for (unsigned int i = 0; i < len; ++i) { + TEST_ASSERT_TRUE(numbers[i] >= 1); + TEST_ASSERT_TRUE(numbers[i] <= 2 * len); + } + + free(numbers); +} + +void test_getDuplicate_finds_exactly_one_duplicate(void) +{ + unsigned int len = 25; + unsigned int *numbers = createNumbers(len); + + TEST_ASSERT_NOT_NULL(numbers); + + unsigned int duplicate = getDuplicate(numbers, len); + TEST_ASSERT_NOT_EQUAL_UINT(0, duplicate); + + unsigned int occurrences = + countOccurrences(numbers, len, duplicate); + + TEST_ASSERT_EQUAL_UINT(2, occurrences); + + free(numbers); +} + +void test_error_cases(void) +{ + TEST_ASSERT_NULL(createNumbers(0)); + TEST_ASSERT_NULL(createNumbers(1)); + + TEST_ASSERT_EQUAL_UINT(0, getDuplicate(NULL, 10)); + + unsigned int oneElement[1] = { 42 }; + TEST_ASSERT_EQUAL_UINT(0, getDuplicate(oneElement, 1)); +} + +int main(void) +{ + srand((unsigned int) time(NULL)); + + UNITY_BEGIN(); + + RUN_TEST(test_createNumbers_returns_non_null); + RUN_TEST(test_createNumbers_value_range); + RUN_TEST(test_getDuplicate_finds_exactly_one_duplicate); + RUN_TEST(test_error_cases); + + return UNITY_END(); } \ No newline at end of file diff --git a/timer.o b/timer.o new file mode 100644 index 0000000000000000000000000000000000000000..d73004d6b5d953dab0c2d764768bf92779a5d517 GIT binary patch literal 1040 zcmah|KWGzC82?_+Hf^qLI%J3r_Bse=P_#HmvG}SHO6XAJ2DfJ#Ln$^*XihAImVk@k z(twkKI5;%m;NZ~Bijz24Gf2j`*_J}>cEYK@@9w=M+QARL@Av(E@AvM#`~36p*D#SF z2%A&TZFU?el$y(Qif{}s zsgrNOi_bO>!#p7xqF@q`f=2r!;G78y+{F32nB(uW3zR?`IuB*xJ7DGB0qDP6k@~L$ z)pw1+qWTWiZexCPf~bz6r$P1o){dpV{{BE;f@)tQcog+~yBXE@Z0X0*KgcSmo)ywh zi}*o&_HlDxygW{?$Di*fq;L02KP&75d%f1oj(mECo+o=T^4l>PP%F1Fw7J{-c<%f0 zgjjq*sodGNMZq9uu;z~uK`uBYd5w!Y$NRFp0*`}pn9VLzIEnp z4(>z_f2P00(b0B3J`a4A*qqy7q7=}6gcff z$k)d4z!Y#4juCc8ak1uo@_N1TMUL?%%zMK(qD0R;@5`|RWEqF{l<^}}yxgj%!CfjA fR@pC=wVPiq