Compare commits

..

No commits in common. "main" and "YB_Branch" have entirely different histories.

26 changed files with 55 additions and 828 deletions

40
.vscode/launch.json vendored
View File

@ -1,40 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug test_stack",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/test_stack.exe",
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"miDebuggerPath": "C:/ProgramData/mingw64/mingw64/bin/gdb.exe",
"preLaunchTask": "Build via Makefile"
},
{
"name": "Debug test_numbers",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/test_numbers.exe",
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"miDebuggerPath": "C:/ProgramData/mingw64/mingw64/bin/gdb.exe",
"preLaunchTask": "Build via Makefile"
},
{
"name": "Debug test_bintree",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/test_bintree.exe",
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"miDebuggerPath": "C:/ProgramData/mingw64/mingw64/bin/gdb.exe",
"preLaunchTask": "Build via Makefile"
}
]
}

27
.vscode/tasks.json vendored
View File

@ -1,27 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build via Makefile",
"type": "shell",
"command": "mingw32-make",
"args": ["${input:target}"],
"options": {
"cwd": "${workspaceFolder}"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": "$gcc"
}
],
"inputs": [
{
"id": "target",
"type": "pickString",
"description": "Welches Makefile-Target soll gebaut werden?",
"options": ["test_stack", "test_numbers", "test_bintree", "doble", "unitTests"]
}
]
}

155
bintree.c
View File

@ -1,153 +1,36 @@
#include <stdlib.h>
#include <string.h>
#include "stack.h"
#include "bintree.h"
/*
Schiebt einen Knoten und alle seine linken Nachfolger
(entlang der "linken Kante") auf den Iterator-Stack.
iterStackPtr: Zeiger auf den Top-Zeiger des Stacks (LIFO) für die Wiederholung
knoten: aktueller Startknoten, dessen linke Kette abgelegt wird
*/
static void bintree_pushLefts(StackNode **iterStackPtr, TreeNode *knoten)
//TODO: binären Suchbaum implementieren
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv),
* `clearTree`: gibt den gesamten Baum frei (rekursiv),
* `treeSize`: zählt die Knoten im Baum (rekursiv),
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */
// 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).
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
{
while (knoten != NULL)
{
*iterStackPtr = push(*iterStackPtr, knoten); // aktuellen Knoten oben auf den Stack legen
knoten = knoten->left; // zum linken Kind weiterlaufen
}
}
/*
Fügt eine Kopie der Daten (Speicherbereich von 'data' mit Länge 'dataSize') in den Baum ein.
Die Ordnung wird über 'compareFct' festgelegt.
Duplikate:
- Wenn 'isDuplicate' != NULL übergeben wird: Duplikate werden NICHT eingefügt,
stattdessen wird *isDuplicate = 1 gesetzt (bei neuem Eintrag = 0).
- Wenn 'isDuplicate' == NULL: Duplikate SIND erlaubt; der Duplikat-Eintrag
wird in den rechten Teilbaum eingefügt.
Rückgabe:
- Zeiger auf die (ggf. unveränderte oder neue) Wurzel des Teilbaums.
- NULL bei Speicherfehlern beim Anlegen des ersten Knotens.
*/
TreeNode *addToTree(TreeNode *wurzel,
const void *daten,
size_t datenGroesse,
CompareFctType vergleichFkt,
int *istDuplikat)
// 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.
void *nextTreeData(TreeNode *root)
{
// Standardmäßig annehmen: kein Duplikat (falls Ausgabefeld vorhanden)
if (istDuplikat != NULL)
*istDuplikat = 0;
// Leerer Baum/Teilbaum: neuen Knoten erzeugen
if (wurzel == NULL)
{
TreeNode *neuerKnoten = (TreeNode *)malloc(sizeof(TreeNode));
if (neuerKnoten == NULL)
return NULL; // Speicherfehler
neuerKnoten->data = malloc(datenGroesse);
if (neuerKnoten->data == NULL)
{
free(neuerKnoten);
return NULL; // Speicherfehler für Datenbereich
}
memcpy(neuerKnoten->data, daten, datenGroesse); // tiefe Kopie der Nutzdaten
neuerKnoten->left = neuerKnoten->right = NULL; // Blatt
return neuerKnoten;
}
// Vergleich der einzufügenden Daten mit dem aktuellen Knoten
int vergleich = vergleichFkt(daten, wurzel->data);
if (vergleich < 0)
{
// links einfügen
wurzel->left = addToTree(wurzel->left, daten, datenGroesse, vergleichFkt, istDuplikat);
}
else if (vergleich > 0)
{
// rechts einfügen
wurzel->right = addToTree(wurzel->right, daten, datenGroesse, vergleichFkt, istDuplikat);
}
else
{
// Gleichheit (potenzielles Duplikat)
if (istDuplikat != NULL)
{
*istDuplikat = 1; // Duplikat erkannt, NICHT einfügen
// keine Änderung am Baum
}
else
{
// Duplikate erlaubt -> konventionell in den rechten Teilbaum einfügen
wurzel->right = addToTree(wurzel->right, daten, datenGroesse, vergleichFkt, istDuplikat);
}
}
return wurzel;
}
/*
Die Funktion gibt bei jedem Aufruf das nächste Element des Binärbaums in **Inorder-Reihenfolge**
zurück und merkt sich intern, wo sie zuletzt war.
*/
void *nextTreeData(TreeNode *wurzel)
// Releases all memory resources (including data copies).
void clearTree(TreeNode *root)
{
static StackNode *iteratorStack = NULL; // interner Zustand über Aufrufe hinweg
// Neuer Baum übergeben -> Iterator zurücksetzen/initialisieren
if (wurzel != NULL)
{
clearStack(iteratorStack); // ggf. alten Stack leeren (Speicher freigeben)
iteratorStack = NULL; // Top-Zeiger zurücksetzen
bintree_pushLefts(&iteratorStack, wurzel); // Wurzel und linke Kette ablegen
}
// Kein weiterer Eintrag?
if (iteratorStack == NULL)
return NULL;
// Nächsten Knoten holen (oberstes Stack-Element)
TreeNode *aktuellerKnoten = (TreeNode *)top(iteratorStack); //Oberstes Element zurück
iteratorStack = pop(iteratorStack); // entfernt Oberstes Element
// Falls rechter Teilbaum existiert: dessen linke Kette ablegen
if (aktuellerKnoten->right != NULL)
bintree_pushLefts(&iteratorStack, aktuellerKnoten->right);
// Daten des aktuellen Knotens zurückgeben
return aktuellerKnoten->data;
}
/*
Gibt den gesamten Baum frei (inkl. der tief kopierten Daten).
*/
void clearTree(TreeNode *wurzel)
// Returns the number of entries in the tree given by root.
unsigned int treeSize(const TreeNode *root)
{
if (wurzel == NULL)
return;
clearTree(wurzel->left);
clearTree(wurzel->right);
free(wurzel->data);
free(wurzel);
}
/*
Liefert die Anzahl der Knoten/Einträge im Teilbaum 'wurzel'.
*/
unsigned int treeSize(const TreeNode *wurzel)
{
if (wurzel == NULL)
return 0;
return 1U + treeSize(wurzel->left) + treeSize(wurzel->right);
}
}

View File

@ -1,81 +1,27 @@
#ifndef BINTREE_H
#define BINTREE_H
#include <stdlib.h>
/*
Typdefinition für die Vergleichsfunktion.
Die Funktion muss zwei Datenzeiger vergleichen und zurückgeben:
- < 0, wenn arg1 kleiner als arg2 ist
- 0, wenn arg1 gleich arg2 ist
- > 0, wenn arg1 größer als arg2 ist
*/
typedef int (*CompareFctType)(const void *arg1, const void *arg2);
/*
Struktur für einen Binärbaum-Knoten.
Enthält:
- data: Zeiger auf die gespeicherten Daten (beliebiger Typ, dynamisch allokiert)
- left: Zeiger auf linken Teilbaum
- right: Zeiger auf rechten Teilbaum
*/
typedef struct node
{
void *data; // Zeiger auf die Nutzdaten
struct node *left; // Zeiger auf linken Kindknoten
struct node *right; // Zeiger auf rechten Kindknoten
void *data;
struct node *left;
struct node *right;
} TreeNode;
/*
Fügt eine Kopie der Daten in den Binärbaum ein.
Parameter:
root : Wurzel des (Teil-)Baums
data : Zeiger auf die einzufügenden Daten
dataSize : Größe der Daten in Bytes
compareFct : Vergleichsfunktion für die Ordnung
isDuplicate : Optionaler Zeiger:
- Wenn NULL: Duplikate sind erlaubt
- Wenn != NULL: Duplikate werden ignoriert und *isDuplicate wird gesetzt:
- 0: neuer Eintrag eingefügt
- 1: Duplikat erkannt, nicht eingefügt
Rückgabe:
Zeiger auf die (ggf. neue) Wurzel des Baums oder NULL bei Speicherfehler.
*/
// 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).
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate);
/*
Iteriert über den Baum in Inorder-Reihenfolge.
Verhalten:
- Erster Aufruf mit root != NULL: Iterator initialisieren
- Folgeaufrufe mit root == NULL: nächstes Element zurückgeben
Rückgabe:
Zeiger auf die Daten des nächsten Knotens oder NULL, wenn Ende erreicht.
Hinweis:
Intern wird ein Stack verwendet. Nicht threadsicher.
*/
// 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.
void *nextTreeData(TreeNode *root);
/*
Gibt den gesamten Baum frei (inklusive der gespeicherten Daten).
Nach dem Aufruf sind alle Zeiger ungültig.
*/
// Releases all memory resources (including data copies).
void clearTree(TreeNode *root);
/*
Liefert die Anzahl der Knoten im Baum.
Rückgabe:
Anzahl der Knoten (0 bei leerem Baum).
*/
// Returns the number of entries in the tree given by root.
unsigned int treeSize(const TreeNode *root);
#endif
#endif

BIN
doble.exe

Binary file not shown.

Binary file not shown.

View File

@ -1,10 +1 @@
Player1;19887
Player1;19843
Lena;19811
Lena;19702
Player1;19578
player_name;9981
Lena;9980
Lena;9978
Lena;9978
Lena;9976
player1;3999

View File

@ -29,38 +29,14 @@ program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
doble : main.o $(program_obj_files)
$(CC) $(FLAGS) $^ -o doble
# pattern rule to build .o from .c
%.o: %.c
$(CC) -c $(FLAGS) $< -o $@
$(program_obj_filesobj_files): %.o: %.c
$(CC) -c $(FLAGS) $^ -o $@
# --------------------------
# Unit Tests
# --------------------------
unitTests: test_stack test_numbers test_bintree
@total=0; passed=0; failed=0; \
for t in test_stack test_numbers test_bintree; do \
total=$$((total+1)); \
printf "Running %s...\n" "$$t"; \
./$$t; rc=$$?; \
if [ $$rc -eq 0 ]; then \
printf "%s: PASS\n\n" "$$t"; \
passed=$$((passed+1)); \
else \
printf "%s: FAIL (exit %d)\n\n" "$$t" $$rc; \
failed=$$((failed+1)); \
fi; \
done; \
printf "Summary: %d tests run, %d passed, %d failed\n" $$total $$passed $$failed; \
exit $$failed
test_stack: test_stack.c stack.c
$(CC) $(FLAGS) test_stack.c stack.c -o test_stack
test_numbers: test_numbers.c numbers.c bintree.c stack.c
$(CC) $(FLAGS) test_numbers.c numbers.c bintree.c stack.c -o test_numbers
test_bintree: test_bintree.c bintree.c stack.c
$(CC) $(FLAGS) test_bintree.c bintree.c stack.c -o test_bintree
unitTests:
echo "needs to be implemented"
# --------------------------
# Clean

193
numbers.c
View File

@ -1,4 +1,3 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
@ -6,194 +5,22 @@
#include "numbers.h"
#include "bintree.h"
/**
* @brief Vergleichsfunktion für unsigned int-Werte zur Verwendung im Binärbaum.
*
* Diese Funktion wird von der Binärbaum-Implementierung genutzt, um die
* Ordnung der Knoten zu bestimmen. Sie vergleicht die dereferenzierten
* unsigned int-Werte a und b.
*
* @param a Pointer auf einen unsigned int-Wert (linker Operand)
* @param b Pointer auf einen unsigned int-Wert (rechter Operand)
* @return -1, falls *a < *b; 1, falls *a > *b; 0, falls *a == *b
*/
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;
}
//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. */
/**
* @brief Vergleichsfunktion für qsort() zur Sortierung von unsigned int-Arrays.
*
* @param a Pointer auf einen Arrayeintrag
* @param b Pointer auf einen Arrayeintrag
* @return -1, 0, 1 analog zu compareUInt()
*/
static int qsort_uint_cmp(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;
}
/**
* @brief Erzeugt ein Array aus len Zufallszahlen im Bereich [1 .. 2*len],
* das genau einen duplizierten Wert enthält (d. h. len-1 eindeutige + 1 Duplikat),
* und mischt die Reihenfolge zufällig.
*
* Funktionsweise:
* - Es werden zunächst len-1 eindeutige Zufallszahlen erzeugt. Die Eindeutigkeit wird
* mithilfe eines Binärsuchbaums (BST) geprüft: addToTree() fügt die Zahl ein
* und signalisiert per isDup, ob sie bereits vorhanden war.
* - Anschließend wird eine der bereits erzeugten Zahlen zufällig ausgewählt und
* noch einmal an das Ende des Arrays geschrieben, um das geforderte Duplikat sicherzustellen.
* - Zum Schluss wird das gesamte Array mittels FisherYates-Algorithmus gemischt.
*
* Fehlerbehandlung:
* - Bei len < 2 wird NULL zurückgegeben, da das Problem ein Duplikat erfordert.
* - Bei Speicher- oder Baum-Insertionsfehlern wird aufgeräumt und NULL zurückgegeben.
* Wichtig: Der Baumzeiger root wird erst nach erfolgreichem Insert aktualisiert,
* um im Fehlerfall kein bereits aufgebautes Teilbaum-Objekt zu verlieren.
*
* Randbedingungen / Annahmen:
* - addToTree(root, &val, sizeof(val), compareUInt, &isDup) setzt isDup:
* isDup == 1 bedeutet Duplikat gefunden, Baum unverändert,
* isDup == 0 bedeutet neuer Wert eingefügt (oder Fehler).
* - Bei Speicherfehler gibt addToTree NULL zurück und isDup bleibt 0.
* - clearTree(root) darf mit NULL-Argument aufgerufen werden (No-Op).
*
* Komplexität:
* - Durchschnittlich O(len * log(len)) für die len-1 Einfügungen in den BST.
* - Shuffle in O(len).
*
* @param len Anzahl der zu erzeugenden Werte (muss >= 2 sein)
* @return Pointer auf ein Array mit len Einträgen bei Erfolg; NULL bei Fehlern
*/
// 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)
{
if (len < 2)
return NULL;
unsigned int *numbers = (unsigned int *)malloc(sizeof(unsigned int) * len);
if (numbers == NULL)
return NULL;
// Zufallszahlengenerator nur einmal pro Prozess initialisieren.
// Hintergrund: Wird createNumbers mehrfach schnell hintereinander gerufen,
// kann time(NULL) identische Seeds liefern und damit identische Zahlenfolgen erzeugen.
static int seeded = 0;
if (!seeded) {
srand((unsigned int)time(NULL));
seeded = 1;
}
TreeNode *root = NULL;
unsigned int range = 2 * len;
// Schritt 1: len-1 eindeutige Zufallszahlen erzeugen
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, um „alte“ Werte zu vermeiden
val = (unsigned int)(rand() % range) + 1; // Wertebereich [1 .. 2*len]
// addToTree kann bei Erfolg einen (ggf. neuen) Wurzelzeiger liefern.
// Zur Vermeidung eines Speicherlecks bei Fehlern zunächst in temp speichern.
TreeNode *newRoot = addToTree(root, &val, sizeof(val), compareUInt, &isDup);
if (newRoot == NULL && isDup == 0) {
// Vermutlich Speicher-/Insertionsfehler: aufräumen und abbrechen
free(numbers);
clearTree(root); // root zeigt noch auf den gültigen Teilbaum
return NULL;
}
if (!isDup) {
// Einfügen war erfolgreich und der Wert ist eindeutig.
root = newRoot;
numbers[i] = val;
break;
}
// Andernfalls Duplikat: Neue Zufallszahl versuchen.
}
}
// Schritt 2: Eine der bestehenden Zahlen zufällig duplizieren
unsigned int idx = (unsigned int)(rand() % (len - 1)); // Index im Bereich [0 .. len-2]
numbers[len - 1] = numbers[idx];
// Schritt 3: FisherYates-Shuffle über das gesamte Array
for (unsigned int i = len - 1; i > 0; i--)
{
unsigned int j = (unsigned int)(rand() % (i + 1));
unsigned int tmp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = tmp;
}
// Aufräumen: Baum freigeben
clearTree(root);
return numbers;
}
/**
* @brief Findet den einzigen duplizierten Wert in einem Array aus len unsigned int.
*
* Funktionsweise:
* - Es wird eine Kopie des Eingabearrays erstellt, um die Reihenfolge des
* Originalarrays nicht zu verändern.
* - Die Kopie wird mittels qsort() aufsteigend sortiert.
* - Beim Durchlauf werden benachbarte Elemente verglichen. Da genau ein Wert
* doppelt vorkommt, finden wir ihn als erstes Paar gleicher Nachbarn.
*
* Fehlerbehandlung:
* - Bei ungültigen Parametern (numbers == NULL oder len < 2) wird 0 geliefert.
* - Bei Speicherfehlern beim Kopieren ebenfalls 0.
*
* Komplexität:
* - Sortieren in O(len * log(len)), anschließender Linearpass O(len).
*
* @param numbers Pointer auf das Eingabearray
* @param len Länge des Arrays (muss >= 2 sein)
* @return Der doppelte Wert; 0 bei Fehlern oder falls kein Duplikat gefunden wurde
* (gemäß Aufgabenstellung sollte aber genau ein Duplikat existieren).
*/
// 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)
{
if (numbers == NULL || len < 2)
return 0;
// Kopie erstellen, damit das Original unangetastet bleibt
unsigned int *copy = (unsigned int *)malloc(sizeof(unsigned int) * len);
if (copy == NULL)
return 0;
memcpy(copy, numbers, sizeof(unsigned int) * len);
// Sortieren der Kopie
qsort(copy, len, sizeof(unsigned int), qsort_uint_cmp);
// Linearer Scan: erstes Paar identischer Nachbarn ist das Duplikat
unsigned int result = 0;
for (unsigned int i = 0; i + 1 < len; i++)
{
if (copy[i] == copy[i + 1]) {
result = copy[i];
break;
}
}
free(copy);
return result;
}
}

32
stack.c
View File

@ -1,47 +1,33 @@
#include <stdlib.h>
#include "stack.h"
// Push Daten auf den Stack legen.
//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; // allocation failed -> return unchanged stack
node->data = data; // Setze Daten
node->next = stack; // Setze nächsten Knoten auf aktuellen 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;
// Speicher des aktuellen Knotens freigeben
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;
// Do NOT free stack->data here; caller owns the pointed data
free(stack);
stack = next;
}
}

View File

@ -7,12 +7,7 @@ The latest element is taken from the stack. */
#include <stdlib.h>
// Stack node for linked-list based stack. Data pointer is stored but not freed by stack operations.
typedef struct StackNode
{
void *data;
struct StackNode *next;
} StackNode;
//TODO: passenden Datentyp als struct anlegen
// Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data);

Binary file not shown.

View File

@ -1,51 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bintree.h"
// Vergleichsfunktion für unsigned int
static int cmp_uint_ptr(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;
}
int main(void)
{
TreeNode *root = NULL;
unsigned int vals[] = {5, 2, 8, 1, 3, 7, 9};
const size_t n = sizeof(vals)/sizeof(vals[0]);
// Werte in den Baum einfügen
for(size_t i = 0; i < n; i++)
{
int isDup = 0;
root = addToTree(root, &vals[i], sizeof(unsigned int), cmp_uint_ptr, &isDup);
if(root == NULL && isDup == 0) { fprintf(stderr, "addToTree allocation failed\n"); return 1; }
}
// Baumgröße prüfen
unsigned int sz = treeSize(root);
if(sz != n) { fprintf(stderr, "treeSize expected %zu got %u\n", n, sz); clearTree(root); return 2; }
// Inorder-Traversierung (muss sortiert sein)
unsigned int last = 0;
int first = 1;
unsigned int *data = nextTreeData(root);
while(data != NULL)
{
unsigned int v = *data;
// Prüfen, ob Reihenfolge korrekt ist
if(!first && v < last) { fprintf(stderr, "inorder traversal not sorted: %u after %u\n", v, last); clearTree(root); return 3; }
last = v; first = 0;
data = nextTreeData(NULL); // nächstes Element holen
}
clearTree(root); // Speicher freigeben
printf("test_bintree: OK\n");
return 0;
}

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.test_bintree</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@ -1,20 +0,0 @@
---
triple: 'x86_64-apple-darwin'
binary-path: test_bintree
relocations:
- { offset: 0x26, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x1000007A0, symSize: 0x220 }
- { offset: 0x49, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x1000007A0, symSize: 0x220 }
- { offset: 0x121, size: 0x8, addend: 0x0, symName: _cmp_uint_ptr, symObjAddr: 0x220, symBinAddr: 0x1000009C0, symSize: 0x5A }
- { offset: 0x21B, size: 0x8, addend: 0x0, symName: _addToTree, symObjAddr: 0x0, symBinAddr: 0x100000A20, symSize: 0x1C0 }
- { offset: 0x228, size: 0x8, addend: 0x0, symName: _nextTreeData, symObjAddr: 0x1C0, symBinAddr: 0x100000BE0, symSize: 0xC0 }
- { offset: 0x24D, size: 0x8, addend: 0x0, symName: _nextTreeData.iterStack, symObjAddr: 0xFB0, symBinAddr: 0x100002000, symSize: 0x0 }
- { offset: 0x2EC, size: 0x8, addend: 0x0, symName: _addToTree, symObjAddr: 0x0, symBinAddr: 0x100000A20, symSize: 0x1C0 }
- { offset: 0x376, size: 0x8, addend: 0x0, symName: _bintree_pushLefts, symObjAddr: 0x280, symBinAddr: 0x100000CA0, symSize: 0x50 }
- { offset: 0x3A8, size: 0x8, addend: 0x0, symName: _clearTree, symObjAddr: 0x2D0, symBinAddr: 0x100000CF0, symSize: 0x60 }
- { offset: 0x3CC, size: 0x8, addend: 0x0, symName: _treeSize, symObjAddr: 0x330, symBinAddr: 0x100000D50, symSize: 0x56 }
- { offset: 0x47F, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100000DB0, symSize: 0x60 }
- { offset: 0x4C3, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100000DB0, symSize: 0x60 }
- { offset: 0x507, size: 0x8, addend: 0x0, symName: _pop, symObjAddr: 0x60, symBinAddr: 0x100000E10, symSize: 0x50 }
- { offset: 0x53D, size: 0x8, addend: 0x0, symName: _top, symObjAddr: 0xB0, symBinAddr: 0x100000E60, symSize: 0x40 }
- { offset: 0x565, size: 0x8, addend: 0x0, symName: _clearStack, symObjAddr: 0xF0, symBinAddr: 0x100000EA0, symSize: 0x3F }
...

Binary file not shown.

View File

@ -1,91 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "numbers.h"
/**
* @brief Selbsttest für createNumbers() und getDuplicate().
*
* Erzeugt ein Array aus len Zufallszahlen mit genau einem duplizierten Wert,
* validiert die Eigenschaften per Zähl-Array (Wertebereich, Häufigkeiten)
* und prüft anschließend, ob getDuplicate() dasselbe Duplikat ermittelt.
*
* Rückgabecodes:
* 0: OK
* 1: createNumbers() fehlgeschlagen
* 2: Speicherfehler für counts
* 3: Wert außerhalb des Bereichs [1..2*len]
* 4: Ein Wert erscheint öfter als zweimal
* 5: Nicht genau ein Duplikat gefunden
* 6: getDuplicate() liefert anderes Ergebnis als Zählung
*/
int main(void)
{
unsigned int len = 100; // Anzahl zu erzeugender Zahlen
unsigned int *nums = createNumbers(len);
if (nums == NULL) {
fprintf(stderr, "createNumbers returned NULL\n");
return 1; // Erzeugung fehlgeschlagen
}
unsigned int maxVal = 2 * len; // Erlaubter Bereich: [1 .. 2*len]
// Zähl-Array für Häufigkeiten pro Wert (Index 0 bleibt ungenutzt)
unsigned int *counts = calloc(maxVal + 1, sizeof(unsigned int));
if (counts == NULL) {
free(nums);
return 2; // Speicherfehler bei counts
}
// Häufigkeiten bestimmen und gleichzeitig Bereich prüfen
for (unsigned int i = 0; i < len; i++) {
unsigned int v = nums[i];
if (v == 0 || v > maxVal) { // sollte nicht passieren, wenn createNumbers korrekt ist
fprintf(stderr, "value out of expected range\n");
free(nums);
free(counts);
return 3;
}
counts[v]++; // Auftreten des Werts v zählen
}
// Exakt ein Wert muss doppelt vorkommen; keiner darf >2-mal vorkommen
int duplicatesFound = 0;
unsigned int duplicateValue = 0;
for (unsigned int v = 1; v <= maxVal; v++) {
if (counts[v] == 2) {
duplicatesFound++;
duplicateValue = v; // den doppelten Wert merken
} else if (counts[v] > 2) {
fprintf(stderr, "value %u appears more than twice\n", v);
free(nums);
free(counts);
return 4; // Vertragsbruch: zu häufiges Auftreten
}
// counts[v] == 0 oder 1 sind unkritisch
}
if (duplicatesFound != 1) {
fprintf(stderr, "expected exactly one duplicated value, found %d\n", duplicatesFound);
free(nums);
free(counts);
return 5; // zu wenige/zu viele Duplikate
}
// Ergebnis von getDuplicate() mit der Zählung abgleichen
unsigned int found = getDuplicate(nums, len);
if (found != duplicateValue) {
fprintf(stderr, "getDuplicate returned %u expected %u\n", found, duplicateValue);
free(nums);
free(counts);
return 6; // Abweichung zwischen Methoden
}
// Ressourcen freigeben und Erfolg melden
free(nums);
free(counts);
printf("test_numbers: OK (duplicate = %u)\n", duplicateValue);
return 0;
}

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.test_numbers</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@ -1,24 +0,0 @@
---
triple: 'x86_64-apple-darwin'
binary-path: test_numbers
relocations:
- { offset: 0x26, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x1000013A0, symSize: 0x287 }
- { offset: 0x41, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x1000013A0, symSize: 0x287 }
- { offset: 0x12E, size: 0x8, addend: 0x0, symName: _createNumbers, symObjAddr: 0x0, symBinAddr: 0x100001630, symSize: 0x1D0 }
- { offset: 0x152, size: 0x8, addend: 0x0, symName: _createNumbers, symObjAddr: 0x0, symBinAddr: 0x100001630, symSize: 0x1D0 }
- { offset: 0x23E, size: 0x8, addend: 0x0, symName: _compareUInt, symObjAddr: 0x1D0, symBinAddr: 0x100001800, symSize: 0x60 }
- { offset: 0x290, size: 0x8, addend: 0x0, symName: _getDuplicate, symObjAddr: 0x230, symBinAddr: 0x100001860, symSize: 0x110 }
- { offset: 0x2FE, size: 0x8, addend: 0x0, symName: _qsort_uint_cmp, symObjAddr: 0x340, symBinAddr: 0x100001970, symSize: 0x5A }
- { offset: 0x3C5, size: 0x8, addend: 0x0, symName: _addToTree, symObjAddr: 0x0, symBinAddr: 0x1000019D0, symSize: 0x1C0 }
- { offset: 0x3D2, size: 0x8, addend: 0x0, symName: _nextTreeData, symObjAddr: 0x1C0, symBinAddr: 0x100001B90, symSize: 0xC0 }
- { offset: 0x3F7, size: 0x8, addend: 0x0, symName: _nextTreeData.iterStack, symObjAddr: 0xFB0, symBinAddr: 0x100003000, symSize: 0x0 }
- { offset: 0x496, size: 0x8, addend: 0x0, symName: _addToTree, symObjAddr: 0x0, symBinAddr: 0x1000019D0, symSize: 0x1C0 }
- { offset: 0x520, size: 0x8, addend: 0x0, symName: _bintree_pushLefts, symObjAddr: 0x280, symBinAddr: 0x100001C50, symSize: 0x50 }
- { offset: 0x552, size: 0x8, addend: 0x0, symName: _clearTree, symObjAddr: 0x2D0, symBinAddr: 0x100001CA0, symSize: 0x60 }
- { offset: 0x576, size: 0x8, addend: 0x0, symName: _treeSize, symObjAddr: 0x330, symBinAddr: 0x100001D00, symSize: 0x56 }
- { offset: 0x629, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100001D60, symSize: 0x60 }
- { offset: 0x66D, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100001D60, symSize: 0x60 }
- { offset: 0x6B1, size: 0x8, addend: 0x0, symName: _pop, symObjAddr: 0x60, symBinAddr: 0x100001DC0, symSize: 0x50 }
- { offset: 0x6E7, size: 0x8, addend: 0x0, symName: _top, symObjAddr: 0xB0, symBinAddr: 0x100001E10, symSize: 0x40 }
- { offset: 0x70F, size: 0x8, addend: 0x0, symName: _clearStack, symObjAddr: 0xF0, symBinAddr: 0x100001E50, symSize: 0x3F }
...

View File

@ -1,52 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "stack.h"
int main(void)
{
StackNode *s = NULL;
// push 3 integers
int *a = malloc(sizeof(int));
*a = 1;
s = push(s, a);
int *b = malloc(sizeof(int));
*b = 2;
s = push(s, b);
int *c = malloc(sizeof(int));
*c = 3;
s = push(s, c);
// oben liegt c (3)
int *topv = (int *)top(s);
if(topv == NULL || *topv != 3) { fprintf(stderr, "stack top expected 3\n"); return 1; }
// oben liegt nun 2
s = pop(s);
topv = (int *)top(s);
if(topv == NULL || *topv != 2) { fprintf(stderr, "stack top expected 2 after pop\n"); return 2; }
// oben liegt nun 1
s = pop(s);
topv = (int *)top(s);
if(topv == NULL || *topv != 1) { fprintf(stderr, "stack top expected 1 after pop\n"); return 3; }
// letzen Stapelinhalt holen
s = pop(s);
if(s != NULL) { fprintf(stderr, "stack expected empty after popping all\n"); return 4; }
// Eigenen Speicher freigeben
free(a);
free(b);
free(c);
// test clearStack mit leerem Stack
s = push(s, malloc(sizeof(int)));
s = push(s, malloc(sizeof(int)));
clearStack(s); // clearStack must free nodes but not payload; free payloads not necessary because we leaked intentionally for test of API
// Note: above payloads are not freed (stack API spec); this test ensures clearStack doesn't crash.
// Funktioniert alles
printf("test_stack: OK\n");
return 0;
}

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.test_stack</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@ -1,12 +0,0 @@
---
triple: 'x86_64-apple-darwin'
binary-path: test_stack
relocations:
- { offset: 0x26, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x100000B80, symSize: 0x249 }
- { offset: 0x4E, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x100000B80, symSize: 0x249 }
- { offset: 0x10A, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100000DD0, symSize: 0x60 }
- { offset: 0x14E, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100000DD0, symSize: 0x60 }
- { offset: 0x192, size: 0x8, addend: 0x0, symName: _pop, symObjAddr: 0x60, symBinAddr: 0x100000E30, symSize: 0x50 }
- { offset: 0x1C8, size: 0x8, addend: 0x0, symName: _top, symObjAddr: 0xB0, symBinAddr: 0x100000E80, symSize: 0x40 }
- { offset: 0x1F0, size: 0x8, addend: 0x0, symName: _clearStack, symObjAddr: 0xF0, symBinAddr: 0x100000EC0, symSize: 0x3F }
...

Binary file not shown.