generated from freudenreichan/info2Praktikum-DobleSpiel
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d06168f6c1 | ||
|
|
b3279a2486 | ||
|
|
cc42231e0c | ||
|
|
dc3e99e899 | ||
|
|
7f765d5373 | ||
|
|
321b9630cc | ||
|
|
70119f897a | ||
|
|
49ba00aad6 |
@@ -1,3 +1,4 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
#include "bintree.h"
|
#include "bintree.h"
|
||||||
@@ -12,7 +13,42 @@
|
|||||||
// 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).
|
||||||
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
|
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
|
||||||
{
|
{
|
||||||
|
if (root == NULL) {
|
||||||
|
TreeNode *newNode = (TreeNode *)malloc(sizeof(TreeNode));
|
||||||
|
if (newNode == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
newNode->data = malloc(dataSize);
|
||||||
|
if (newNode->data == NULL) {
|
||||||
|
free(newNode);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(newNode->data, data, dataSize);
|
||||||
|
newNode->left = NULL;
|
||||||
|
newNode->right = NULL;
|
||||||
|
|
||||||
|
if (isDuplicate != NULL) {
|
||||||
|
*isDuplicate = 0;
|
||||||
|
}
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmp = compareFct(data, root->data);
|
||||||
|
|
||||||
|
if (cmp == 0 && isDuplicate != NULL) {
|
||||||
|
*isDuplicate = 1;
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmp < 0) {
|
||||||
|
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
|
||||||
|
} else {
|
||||||
|
/* Insert duplicates on the right side if they are allowed (isDuplicate == NULL). */
|
||||||
|
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.
|
// 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.
|
||||||
@@ -21,16 +57,51 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFc
|
|||||||
void *nextTreeData(TreeNode *root)
|
void *nextTreeData(TreeNode *root)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static StackNode *iterStack = NULL;
|
||||||
|
|
||||||
|
// Start of traversal
|
||||||
|
if (root != NULL) {
|
||||||
|
clearStack(iterStack);
|
||||||
|
iterStack = NULL;
|
||||||
|
|
||||||
|
for (TreeNode *n = root; n != NULL; n = n->left) {
|
||||||
|
iterStack = push(iterStack, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stops if no elements left
|
||||||
|
if (iterStack == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop the top node
|
||||||
|
TreeNode *node = (TreeNode *)top(iterStack);
|
||||||
|
iterStack = pop(iterStack);
|
||||||
|
|
||||||
|
// select node one to the right --> push all lefts
|
||||||
|
for (TreeNode *n = node->right; n != NULL; n = n->left) {
|
||||||
|
iterStack = push(iterStack, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Releases all memory resources (including data copies).
|
// Releases all memory resources (including data copies).
|
||||||
void clearTree(TreeNode *root)
|
void clearTree(TreeNode *root)
|
||||||
{
|
{
|
||||||
|
if (root != NULL) {
|
||||||
|
clearTree(root->left);
|
||||||
|
clearTree(root->right);
|
||||||
|
free(root->data);
|
||||||
|
free(root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of entries in the tree given by root.
|
// Returns the number of entries in the tree given by root.
|
||||||
unsigned int treeSize(const TreeNode *root)
|
unsigned int treeSize(const TreeNode *root)
|
||||||
{
|
{
|
||||||
|
if (root == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1 + treeSize(root->left) + treeSize(root->right);
|
||||||
}
|
}
|
||||||
@@ -1 +1,4 @@
|
|||||||
|
patric;9910
|
||||||
|
patric;5988
|
||||||
player1;3999
|
player1;3999
|
||||||
|
test;3994
|
||||||
|
|||||||
@@ -35,8 +35,11 @@ $(program_obj_filesobj_files): %.o: %.c
|
|||||||
# --------------------------
|
# --------------------------
|
||||||
# Unit Tests
|
# Unit Tests
|
||||||
# --------------------------
|
# --------------------------
|
||||||
unitTests:
|
numbers_tests:
|
||||||
echo "needs to be implemented"
|
$(CC) $(FLAGS) numbers.c bintree.c stack.c unity.c test_numbers.c -o test_numbers
|
||||||
|
|
||||||
|
stack_tests:
|
||||||
|
$(CC) $(FLAGS) stack.c unity.c stackunitytest.c -o test_stack
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Clean
|
# Clean
|
||||||
|
|||||||
@@ -1,26 +1,221 @@
|
|||||||
#include <stdlib.h>
|
/************************************************************
|
||||||
#include <stdio.h>
|
* BLOCK 0 – Zweck der Datei
|
||||||
#include <time.h>
|
* ----------------------------------------------------------
|
||||||
#include <string.h>
|
* Diese Datei liefert zwei Funktionen für das Spiel:
|
||||||
#include "numbers.h"
|
* - createNumbers(len): erzeugt ein Array mit len Zufallszahlen,
|
||||||
#include "bintree.h"
|
* in dem GENAU EINE Zahl doppelt vorkommt.
|
||||||
|
* - getDuplicate(numbers, len): findet effizient die doppelte Zahl.
|
||||||
|
*
|
||||||
|
* Technik:
|
||||||
|
* - Beim Erzeugen verhindert ein Binärsuchbaum (BST) Duplikate.
|
||||||
|
* - Beim Finden sortieren wir eine Kopie und vergleichen Nachbarn.
|
||||||
|
************************************************************/
|
||||||
|
|
||||||
//TODO: getDuplicate und createNumbers implementieren
|
#include <stdlib.h> // malloc, free, rand
|
||||||
/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen.
|
#include <stdio.h> // optional für Debug/printf
|
||||||
* Sicherstellen, dass beim Befüllen keine Duplikate entstehen.
|
#include <time.h> // time() für einmaliges srand-Seed
|
||||||
* Duplizieren eines zufälligen Eintrags im Array.
|
#include <string.h> // memcpy
|
||||||
* in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */
|
#include "numbers.h" // Deklarationen: createNumbers, getDuplicate
|
||||||
|
#include "bintree.h" // BST-API: addToTree, clearTree, CompareFctType
|
||||||
// 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)
|
* BLOCK 1 – Gemeinsame Vergleichsfunktion
|
||||||
{
|
* ----------------------------------------------------------
|
||||||
|
* compareUInt:
|
||||||
}
|
* - Definiert die Ordnung für unsigned int (aufsteigend).
|
||||||
|
* - Geeignet sowohl für den Binärbaum (addToTree)
|
||||||
// Returns only the only number in numbers which is present twice. Returns zero on errors.
|
* als auch für qsort.
|
||||||
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
|
* Rückgabewerte:
|
||||||
{
|
* - < 0 : a < b → im BST nach LINKS
|
||||||
|
* - = 0 : a == b → Duplikat
|
||||||
}
|
* - > 0 : a > b → im BST nach RECHTS
|
||||||
|
************************************************************/
|
||||||
|
static int compareUInt(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
unsigned int va = *(const unsigned int *)a;
|
||||||
|
unsigned int vb = *(const unsigned int *)b;
|
||||||
|
if (va < vb) return -1;
|
||||||
|
if (va > vb) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
* BLOCK 2 – Zahlen erzeugen: createNumbers(len)
|
||||||
|
* ----------------------------------------------------------
|
||||||
|
* Ziel:
|
||||||
|
* - Ein Array mit len Zufallszahlen im Bereich [1 .. 2*len].
|
||||||
|
* - Zuerst ALLE eindeutig (via BST geprüft).
|
||||||
|
* - Danach GENAU EINE Zahl absichtlich duplizieren.
|
||||||
|
* - Zum Schluss das Array gleichverteilt mischen (Fisher–Yates).
|
||||||
|
*
|
||||||
|
* Rückgabe:
|
||||||
|
* - Pointer auf dynamisch allokiertes Array (Caller muss free).
|
||||||
|
* - NULL bei Fehlern (z. B. len < 2, malloc/Insert-Fehler).
|
||||||
|
************************************************************/
|
||||||
|
unsigned int *createNumbers(unsigned int len)
|
||||||
|
{
|
||||||
|
/***********************
|
||||||
|
* 2.1 Vorbedingungen & Speicher
|
||||||
|
***********************/
|
||||||
|
if (len < 2) // Ein Duplikat macht erst ab 2 Elementen Sinn
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
unsigned int *numbers = (unsigned int *)malloc(sizeof(unsigned int) * len);
|
||||||
|
if (!numbers) // Speicherfehler
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* 2.2 Einmaliges Zufalls-Seed
|
||||||
|
* (falls main() nicht seedet, sorgen wir einmalig dafür)
|
||||||
|
***********************/
|
||||||
|
static int seeded = 0; // Merker: srand nur einmal pro Prozess
|
||||||
|
if (!seeded) {
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
seeded = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* 2.3 BST-Setup & Wertebereich
|
||||||
|
***********************/
|
||||||
|
TreeNode *root = NULL; // Leerer Binärbaum zum Duplikat-Check
|
||||||
|
unsigned int range = 2 * len; // Zahlenbereich: 1..2*len
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* 2.4 len-1 EINDEUTIGE Zahlen erzeugen
|
||||||
|
* – jede Zahl sofort gegen den BST prüfen
|
||||||
|
***********************/
|
||||||
|
for (unsigned int i = 0; i < len - 1; i++)
|
||||||
|
{
|
||||||
|
unsigned int val;
|
||||||
|
int isDup;
|
||||||
|
|
||||||
|
// Wiederholen, bis eine wirklich neue Zahl eingefügt wurde
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
isDup = 0; // vor jedem Insert zurücksetzen
|
||||||
|
val = (unsigned int)(rand() % range) + 1; // Kandidat in [1..2*len]
|
||||||
|
|
||||||
|
// Versuch, val in den Baum einzufügen (Kopie wird im Knoten gespeichert)
|
||||||
|
TreeNode *newRoot = addToTree(root, &val, sizeof(val), compareUInt, &isDup);
|
||||||
|
|
||||||
|
// Fehlerfall: Es wäre ein neuer Knoten, aber newRoot ist NULL (z. B. malloc-Fehler)
|
||||||
|
if (newRoot == NULL && isDup == 0) {
|
||||||
|
free(numbers); // Array freigeben
|
||||||
|
clearTree(root); // bisherige Baumknoten freigeben
|
||||||
|
return NULL; // sauber abbrechen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wurzel ggf. aktualisieren (z. B. wenn Baum vorher leer war)
|
||||||
|
if (newRoot) {
|
||||||
|
root = newRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isDup) {
|
||||||
|
// Wert war eindeutig → ins Array übernehmen und weiter zum nächsten i
|
||||||
|
numbers[i] = val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// sonst: Duplikat → neue Zufallszahl probieren
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* 2.5 GENAU EIN Duplikat erzeugen
|
||||||
|
* – eine der bestehenden Zahlen zufällig wählen und erneut eintragen
|
||||||
|
***********************/
|
||||||
|
unsigned int idx = (unsigned int)(rand() % (len - 1)); // Quelle in [0..len-2]
|
||||||
|
numbers[len - 1] = numbers[idx]; // Duplikat absichtlich erzeugt
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* 2.6 Gleichverteiltes Mischen (Fisher–Yates)
|
||||||
|
***********************/
|
||||||
|
for (unsigned int i = len - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
unsigned int j = (unsigned int)(rand() % (i + 1)); // j ∈ [0..i]
|
||||||
|
unsigned int tmp = numbers[i];
|
||||||
|
numbers[i] = numbers[j];
|
||||||
|
numbers[j] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* 2.7 Aufräumen & Rückgabe
|
||||||
|
***********************/
|
||||||
|
clearTree(root); // BST wird nicht mehr gebraucht
|
||||||
|
return numbers; // Ownership des Arrays liegt beim Aufrufer (free(numbers))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
* BLOCK 3 – Duplikat finden: getDuplicate(numbers, len)
|
||||||
|
* ----------------------------------------------------------
|
||||||
|
* Idee:
|
||||||
|
* - Original-Array unangetastet lassen → KOPIE erstellen.
|
||||||
|
* - Kopie aufsteigend sortieren (qsort mit demselben Comparator).
|
||||||
|
* - Ein linearer Durchlauf findet das erste Paar identischer Nachbarn.
|
||||||
|
*
|
||||||
|
* Rückgabe:
|
||||||
|
* - die doppelte Zahl
|
||||||
|
* - 0 bei Fehlern (z. B. ungültige Parameter, malloc-Fehler).
|
||||||
|
************************************************************/
|
||||||
|
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
|
||||||
|
{
|
||||||
|
/***********************
|
||||||
|
* 3.1 Vorbedingungen & Kopie allokieren
|
||||||
|
***********************/
|
||||||
|
if (!numbers || len < 2) // ungültig oder zu kurz
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unsigned int *copy = (unsigned int *)malloc(sizeof(unsigned int) * len);
|
||||||
|
if (!copy) // Speicherfehler
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memcpy(copy, numbers, sizeof(unsigned int) * len); // Original in Kopie übertragen
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* 3.2 Kopie sortieren (qsort + compareUInt)
|
||||||
|
***********************/
|
||||||
|
qsort(copy, len, sizeof(unsigned int), compareUInt);
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* 3.3 Nachbarvergleich: erstes Paar gleicher Werte = Duplikat
|
||||||
|
***********************/
|
||||||
|
unsigned int result = 0;
|
||||||
|
for (unsigned int i = 0; i + 1 < len; i++)
|
||||||
|
{
|
||||||
|
if (copy[i] == copy[i + 1]) {
|
||||||
|
result = copy[i];
|
||||||
|
break; // Duplikat gefunden → fertig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* 3.4 Aufräumen & Rückgabe
|
||||||
|
***********************/
|
||||||
|
free(copy); // Kopie freigeben
|
||||||
|
return result; // 0, falls (unerwartet) kein Duplikat gefunden
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
* BLOCK 4 – Hinweise für die Vorstellung
|
||||||
|
* ----------------------------------------------------------
|
||||||
|
* Ownership:
|
||||||
|
* - Das von createNumbers zurückgegebene Array muss vom Aufrufer
|
||||||
|
* später mit free(numbers) freigegeben werden.
|
||||||
|
*
|
||||||
|
* Fehlerbehandlung:
|
||||||
|
* - Bei jedem Fehlerpfad werden ALLLE angelegten Ressourcen sauber
|
||||||
|
* freigegeben (Array/Kopie/Baum).
|
||||||
|
*
|
||||||
|
* Komplexität:
|
||||||
|
* - Erzeugen: O(n log n) durch BST-Einfügen + O(n) fürs Shuffle.
|
||||||
|
* - Finden: O(n log n) durch qsort + O(n) für den Nachbarvergleich.
|
||||||
|
*
|
||||||
|
* Zusammenarbeit:
|
||||||
|
* - addToTree setzt bei Gleichheit isDuplicate=1 (Duplikat),
|
||||||
|
* und liefert bei neuen Werten die (ggf. neue) Wurzel zurück.
|
||||||
|
* - clearTree gibt ALLE Knoten inkl. Datenkopien frei.
|
||||||
|
************************************************************/
|
||||||
|
|
||||||
+159
@@ -0,0 +1,159 @@
|
|||||||
|
|
||||||
|
// test_numbers_unity.c
|
||||||
|
#include "unity.h"
|
||||||
|
#include "numbers.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void setUp(void) { /* nothing */ }
|
||||||
|
void tearDown(void){ /* nothing */ }
|
||||||
|
|
||||||
|
// Zählt Vorkommen eines Werts im Array
|
||||||
|
static unsigned count_occurrences(const unsigned int *arr, unsigned int len, unsigned int value)
|
||||||
|
{
|
||||||
|
unsigned cnt = 0;
|
||||||
|
for (unsigned i = 0; i < len; ++i)
|
||||||
|
if (arr[i] == value) ++cnt;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prüft Eigenschaften von createNumbers:
|
||||||
|
- Wertebereich: [1..2*len]
|
||||||
|
- Genau EIN Wert doppelt (keiner > 2x)
|
||||||
|
Liefert den doppelten Wert per Out-Param zurück.
|
||||||
|
*/
|
||||||
|
static void assert_numbers_properties(const unsigned int *arr, unsigned int len, unsigned int *dup_out)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_NOT_NULL(arr);
|
||||||
|
TEST_ASSERT_TRUE(len >= 2);
|
||||||
|
|
||||||
|
const unsigned int maxVal = 2 * len;
|
||||||
|
|
||||||
|
// Häufigkeitstabelle von 0..maxVal (0 bleibt ungenutzt)
|
||||||
|
unsigned int *counts = (unsigned int*)calloc(maxVal + 1, sizeof(unsigned int));
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(counts, "calloc(counts) failed");
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
unsigned int v = arr[i];
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(v >= 1 && v <= maxVal, "value out of [1..2*len]");
|
||||||
|
counts[v]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dupCount = 0;
|
||||||
|
unsigned int dupVal = 0;
|
||||||
|
for (unsigned int v = 1; v <= maxVal; ++v)
|
||||||
|
{
|
||||||
|
if (counts[v] == 2) { dupCount++; dupVal = v; }
|
||||||
|
TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(2u, counts[v], "a value occurs more than twice");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(counts);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT_MESSAGE(1, dupCount, "not exactly one duplicated value");
|
||||||
|
if (dup_out) *dup_out = dupVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Einzeltests
|
||||||
|
|
||||||
|
// createNumbers: len < 2 -> NULL
|
||||||
|
static void test_createNumbers_len_too_small(void)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_NULL(createNumbers(0));
|
||||||
|
TEST_ASSERT_NULL(createNumbers(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// createNumbers: Eigenschaften bei repräsentativer Länge
|
||||||
|
static void test_createNumbers_properties_len20(void)
|
||||||
|
{
|
||||||
|
const unsigned int len = 20;
|
||||||
|
unsigned int *arr = createNumbers(len);
|
||||||
|
TEST_ASSERT_NOT_NULL(arr);
|
||||||
|
|
||||||
|
unsigned int dupVal = 0;
|
||||||
|
assert_numbers_properties(arr, len, &dupVal);
|
||||||
|
|
||||||
|
// Der gefundene doppelte Wert muss auch wirklich genau 2x im Array stehen
|
||||||
|
TEST_ASSERT_EQUAL_UINT(2u, count_occurrences(arr, len, dupVal));
|
||||||
|
|
||||||
|
free(arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDuplicate: Minimalfall [x, x] -> x
|
||||||
|
static void test_getDuplicate_minimal_pair(void)
|
||||||
|
{
|
||||||
|
unsigned int a[2] = { 5, 5 };
|
||||||
|
TEST_ASSERT_EQUAL_UINT(5u, getDuplicate(a, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDuplicate: Bekannte, unsortierte Arrays
|
||||||
|
static void test_getDuplicate_known_arrays(void)
|
||||||
|
{
|
||||||
|
unsigned int a1[] = {1,2,3,4,5,3}; // dup = 3
|
||||||
|
unsigned int a2[] = {7,1,3,4,7}; // dup = 7
|
||||||
|
unsigned int a3[] = {9,8,9,1,2,3,4}; // dup = 9
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT(3u, getDuplicate(a1, (unsigned) (sizeof a1/sizeof a1[0])));
|
||||||
|
TEST_ASSERT_EQUAL_UINT(7u, getDuplicate(a2, (unsigned) (sizeof a2/sizeof a2[0])));
|
||||||
|
TEST_ASSERT_EQUAL_UINT(9u, getDuplicate(a3, (unsigned) (sizeof a3/sizeof a3[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDuplicate: Ungültige Eingaben -> 0
|
||||||
|
static void test_getDuplicate_invalid_inputs(void)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_UINT(0u, getDuplicate(NULL, 10));
|
||||||
|
unsigned int x = 42;
|
||||||
|
TEST_ASSERT_EQUAL_UINT(0u, getDuplicate(&x, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Integration: createNumbers + getDuplicate (mehrere Läufe)
|
||||||
|
static void test_integration_create_then_getDuplicate_multi_runs(void)
|
||||||
|
{
|
||||||
|
const unsigned int len = 30;
|
||||||
|
for (int run = 0; run < 3; ++run)
|
||||||
|
{
|
||||||
|
unsigned int *arr = createNumbers(len);
|
||||||
|
TEST_ASSERT_NOT_NULL(arr);
|
||||||
|
|
||||||
|
// Eigenschaften prüfen
|
||||||
|
unsigned int dupVal = 0;
|
||||||
|
assert_numbers_properties(arr, len, &dupVal);
|
||||||
|
|
||||||
|
// getDuplicate muss genau diesen Wert liefern
|
||||||
|
TEST_ASSERT_EQUAL_UINT(dupVal, getDuplicate(arr, len));
|
||||||
|
|
||||||
|
free(arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDuplicate verändert das Original-Array NICHT
|
||||||
|
static void test_getDuplicate_does_not_modify_input(void)
|
||||||
|
{
|
||||||
|
unsigned int arr[] = { 10, 2, 10, 7, 8, 9, 1 };
|
||||||
|
unsigned int original[sizeof arr/sizeof arr[0]];
|
||||||
|
memcpy(original, arr, sizeof arr);
|
||||||
|
|
||||||
|
unsigned int dup = getDuplicate(arr, (unsigned) (sizeof arr/sizeof arr[0]));
|
||||||
|
TEST_ASSERT_EQUAL_UINT(10u, dup);
|
||||||
|
|
||||||
|
// Speicherinhalt identisch?
|
||||||
|
TEST_ASSERT_EQUAL_MEMORY(original, arr, sizeof arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Runner
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(test_createNumbers_len_too_small);
|
||||||
|
RUN_TEST(test_createNumbers_properties_len20);
|
||||||
|
RUN_TEST(test_getDuplicate_minimal_pair);
|
||||||
|
RUN_TEST(test_getDuplicate_known_arrays);
|
||||||
|
RUN_TEST(test_getDuplicate_invalid_inputs);
|
||||||
|
RUN_TEST(test_integration_create_then_getDuplicate_multi_runs);
|
||||||
|
RUN_TEST(test_getDuplicate_does_not_modify_input);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user