12 Commits
15 changed files with 249 additions and 299 deletions
+70 -1
View File
@@ -12,25 +12,94 @@
// 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(data!= NULL && dataSize > 0)
{
if(root == NULL) //Abbruchbedingung: Keine Wurzel vorhanden, deshalb fügen wir hier einen neuen Knote ein
{
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(root->data, data);
if(cmp > 0)
{
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
}
else if(cmp < 0){
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
}
else
{
if (isDuplicate) {
*isDuplicate = 1;
}
else {
// isDuplicate == NULL → trotzdem ein Duplikat einfügen (z.B. rechts)
root->right = addToTree(root->right, data, dataSize, compareFct, NULL);
}
}
return root;
}
return NULL;
} }
// 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.
// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, // 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. // push the top node and push all its left nodes.
void *nextTreeData(TreeNode *root) void *nextTreeData(TreeNode *root)
{
if(root == NULL)
{ {
}
stackNode.top(root);
} }
// 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)
{
return;
} }
// Erst linken Knoten löschen
clearTree(root->left);
// Dann rechten Knoten löschen
clearTree(root->right);
// Dann eigenen Speicher freigeben
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 numNodes;
}
return 1 + treeSize(root->left) + treeSize(root->right); //1, weil eine Wurzel gefunden wurde und dann immer plus eins fuer einen Teilbaum
} }
BIN
View File
Binary file not shown.
+1
View File
@@ -1 +1,2 @@
Silvana;9944
player1;3999 player1;3999
+36 -19
View File
@@ -1,10 +1,17 @@
CC = gcc CC = gcc
FLAGS = -g -Wall -lm
raylibfolder = ./raylib
unityfolder = ./unity
FLAGS = -g -Wall -I$(unityfolder)
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
include makefile_windows.variables include makefile_windows.variables
else else
UNAME = $(shell uname) UNAME := $(shell uname)
ifeq ($(UNAME),Linux) ifeq ($(UNAME),Linux)
include makefile_linux.variables include makefile_linux.variables
else else
@@ -12,38 +19,48 @@ else
endif endif
endif endif
raylibfolder = ./raylib # --------------------------
unityfolder = ./unity # Objektdateien
# --------------------------
program_obj_files := stack.o bintree.o numbers.o timer.o highscore.o
# --------------------------
# Initiales Programm bauen (zum ausprobieren)
# --------------------------
doble_initial:
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
# -------------------------- %.o: %.c
# Selbst implementiertes Programm bauen $(CC) $(FLAGS) -c $< -o $@
# --------------------------
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
doble: main.o $(program_obj_files) doble: main.o $(program_obj_files)
$(CC) $(FLAGS) $^ -o doble $(CC) $(FLAGS) $^ -o doble
$(program_obj_filesobj_files): %.o: %.c
$(CC) -c $(FLAGS) $^ -o $@ doble_initial:
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
# -------------------------- # --------------------------
# Unit Tests # Unit Tests
# -------------------------- # --------------------------
unitTests: unitTests:
echo "needs to be implemented" @echo "needs to be implemented"
binTreeTest: stack.o bintree.o binTreeTest.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -o runbinTreeTest binTreeTest.c bintree.o stack.o $(unityfolder)/unity.c
test_numbers: numbers_no_tree.o bintree.o stack.o test_numbers.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -o run_numbersTests test_numbers.c numbers_no_tree.o bintree.o stack.o $(unityfolder)/unity.c
test_stack: stack.o test_stack.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -o runtest_stack test_stack.c stack.o $(unityfolder)/unity.c
# -------------------------- # --------------------------
# Clean # Cleaning
# -------------------------- # --------------------------
clean: clean:
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
del /f *.o doble del /f *.o doble runstackTests run_numbersTests runbintreeTests
else else
rm -f *.o doble rm -f *.o doble runstackTests run_numbersTests runbintreeTests
endif endif
+26
View File
@@ -0,0 +1,26 @@
#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.
unsigned int *createNumbers(unsigned int len)
{
}
// 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)
{
}
BIN
View File
Binary file not shown.
-115
View File
@@ -1,115 +0,0 @@
#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. */
// -------------------------------------------------------------
// Vergleichsfunktion für qsort (Aufsteigend sortieren)
// -------------------------------------------------------------
static int compareUnsignedInt(const void *a, const void *b)
{
const unsigned int *ia = a;
const unsigned int *ib = b;
if (*ia < *ib) return -1;
if (*ia > *ib) return 1;
return 0;
}
// -------------------------------------------------------------
// createNumbers
// Erzeugt ein Array aus len Zufallszahlen (1..2*len), alle verschieden.
// Danach wird genau EIN zufälliger Eintrag dupliziert.
// Parameter: len = Anzahl der gewünschten Zufallszahlen
// Rückgabe: Pointer auf das erzeugte Array
// -------------------------------------------------------------
unsigned int *createNumbers(unsigned int len)
{
if (len < 2)
return NULL;
srand(time(NULL));
unsigned int *numbers = malloc(len * sizeof(unsigned int));
if (!numbers)
return NULL;
unsigned int count = 0;
// alle Werte verschieden erzeugen
while (count < len)
{
unsigned int value = (rand() % (2 * len)) + 1;
// Duplikatsprüfung
int exists = 0;
for (unsigned int i = 0; i < count; i++) {
if (numbers[i] == value) {
exists = 1;
break;
}
}
if (!exists)
numbers[count++] = value;
}
// EIN Duplikat erzeugen
unsigned int i1 = rand() % len;
unsigned int i2 = rand() % len;
while (i2 == i1)
i2 = rand() % len;
numbers[i2] = numbers[i1];
return numbers;
}
// -------------------------------------------------------------
// getDuplicate
// Findet die einzige Zahl, die im Array zweimal vorkommt.
// Sortiert dazu eine Kopie des Arrays und vergleicht benachbarte Werte.
// Parameter: numbers = Array von Zufallszahlen
// len = Anzahl der Elemente
// Rückgabe: die doppelte Zahl oder 0 bei Fehler
// -------------------------------------------------------------
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
{
if (!numbers || len < 2)
return 0;
// Kopie erzeugen, damit das Original unverändert bleibt
unsigned int *copy = malloc(len * sizeof(unsigned int));
if (!copy)
return 0;
memcpy(copy, numbers, len * sizeof(unsigned int));
// Sortieren
qsort(copy, len, sizeof(unsigned int), compareUnsignedInt);
// benachbarte Elemente vergleichen
unsigned int duplicate = 0;
for (unsigned int i = 1; i < len; i++) {
if (copy[i] == copy[i - 1]) {
duplicate = copy[i];
break;
}
}
free(copy);
return duplicate;
}
BIN
View File
Binary file not shown.
+32 -4
View File
@@ -10,24 +10,52 @@
// Pushes data as pointer onto the stack. // Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data) StackNode *push(StackNode *stack, void *data)
{ {
if (!data)
{
return stack; //Nichts pushen
}
//if(stack && data){
StackNode *t = (StackNode *)malloc(sizeof(StackNode));
if(!t)
{
return NULL; //Speicherfehler
}
t->next = stack;
t->data = data;
return t; //Gibt den ersten StackNode des Stacks zurueck
//}
return NULL;
} }
// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be // Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be
// freed by caller.) // freed by caller.)
StackNode *pop(StackNode *stack) StackNode *pop(StackNode *stack)
{ {
if(stack == NULL)
{
return NULL;
}
return stack->next;
} }
// Returns the data of the top element. // Returns the data of the top element.
void *top(StackNode *stack) void *top(StackNode *stack)
{ {
if(stack)
{
return stack->data;
}
return NULL;
} }
// Clears stack and releases all memory. // Clears stack and releases all memory.
void clearStack(StackNode *stack) void clearStack(StackNode *stack)
{ {
while(stack)
{
StackNode *tmp = stack; //merkt sich den momentanen obersten Knoten
stack = stack->next; //setzt den obersten Knoten auf den Zweiten im Stack
free(tmp->data);
free(tmp);
}
} }
+4
View File
@@ -8,6 +8,10 @@ The latest element is taken from the stack. */
#include <stdlib.h> #include <stdlib.h>
//TODO: passenden Datentyp als struct anlegen //TODO: passenden Datentyp als struct anlegen
typedef struct StackNode {
void* data;
struct StackNode *next;
}StackNode;
// Pushes data as pointer onto the stack. // Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data); StackNode *push(StackNode *stack, void *data);
BIN
View File
Binary file not shown.
-152
View File
@@ -1,152 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "unity.h"
#include "numbers.h"
// -------------------------------------------------------------
// Hilfsfunktion: zählt, wie oft ein Wert im Array vorkommt
// -------------------------------------------------------------
static unsigned int countOccurrences(const unsigned int *arr, unsigned int len, unsigned int value)
{
unsigned int count = 0;
for (unsigned int i = 0; i < len; i++)
if (arr[i] == value)
count++;
return count;
}
// -------------------------------------------------------------
// Test 1: Array wird korrekt erzeugt (nicht NULL)
// -------------------------------------------------------------
void test_createNumbersReturnsNotNull(void)
{
unsigned int len = 20;
unsigned int *numbers = createNumbers(len);
TEST_ASSERT_NOT_NULL(numbers);
free(numbers);
}
// -------------------------------------------------------------
// Test 2: Alle Zahlen liegen im erlaubten Bereich (1..2*len)
// -------------------------------------------------------------
void test_numbersAreInCorrectRange(void)
{
unsigned int len = 50;
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);
}
// -------------------------------------------------------------
// Test 3: Es gibt GENAU EIN Duplikat
// -------------------------------------------------------------
void test_exactlyOneDuplicateExists(void)
{
unsigned int len = 80;
unsigned int *numbers = createNumbers(len);
TEST_ASSERT_NOT_NULL(numbers);
unsigned int duplicatesFound = 0;
for (unsigned int i = 0; i < len; i++)
{
unsigned int occurrences = countOccurrences(numbers, len, numbers[i]);
if (occurrences == 2)
duplicatesFound++;
}
// Da das Duplikat an zwei Positionen vorkommt,
// erwarten wir duplicatesFound == 2
TEST_ASSERT_EQUAL_UINT(2, duplicatesFound);
free(numbers);
}
// -------------------------------------------------------------
// Test 4: getDuplicate() findet die richtige doppelte Zahl
// -------------------------------------------------------------
void test_getDuplicateFindsCorrectValue(void)
{
unsigned int len = 100;
unsigned int *numbers = createNumbers(len);
TEST_ASSERT_NOT_NULL(numbers);
unsigned int duplicate = getDuplicate(numbers, len);
TEST_ASSERT_TRUE(duplicate >= 1);
TEST_ASSERT_TRUE(duplicate <= 2 * len);
TEST_ASSERT_EQUAL_UINT(2, countOccurrences(numbers, len, duplicate));
free(numbers);
}
// -------------------------------------------------------------
// Test 5: createNumbers() erzeugt len Elemente
// -------------------------------------------------------------
void test_arrayLengthIsCorrect(void)
{
unsigned int len = 30;
unsigned int *numbers = createNumbers(len);
TEST_ASSERT_NOT_NULL(numbers);
// Unity-Funktion prüft nicht direkt Länge, aber wir können checken,
// ob Zugriff auf alle Elemente möglich ist (Segfault würde Test crashen).
for (unsigned int i = 0; i < len; i++)
TEST_ASSERT_TRUE(numbers[i] >= 1);
free(numbers);
}
// -------------------------------------------------------------
// Leere setUp/tearDown
// -------------------------------------------------------------
void setUp(void) {}
void tearDown(void) {}
// -------------------------------------------------------------
// Hauptprogramm für Unity-Tests
// -------------------------------------------------------------
int main(void)
{
UNITY_BEGIN();
printf("\n============================\nNumbers tests\n============================\n");
RUN_TEST(test_createNumbersReturnsNotNull);
RUN_TEST(test_numbersAreInCorrectRange);
RUN_TEST(test_exactlyOneDuplicateExists);
RUN_TEST(test_getDuplicateFindsCorrectValue);
RUN_TEST(test_arrayLengthIsCorrect);
return UNITY_END();
}
BIN
View File
Binary file not shown.
+72
View File
@@ -0,0 +1,72 @@
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
//Testfunkionen zu push, pull, top & clearStack schreiben
void setUp()
{
}
void tearDown()
{
}
void test(char *name, int condition) {
if (condition) {
printf("[OK] %s\n", name);
} else {
printf("[FAIL] %s\n", name);
}
}
int main() {
StackNode *stack = NULL;
// Werte dynamisch anlegen
int *val1 = malloc(sizeof(int));
*val1 = 5;
stack = push(stack, val1);
test("push(5) legt 5 oben auf den Stack", *(int*)stack->data == 5);
int *val2 = malloc(sizeof(int));
*val2 = 6;
stack = push(stack, val2);
test("push(6) legt 6 oben auf den Stack", *(int*)stack->data == 6);
int *val3 = malloc(sizeof(int));
*val3 = 24;
stack = push(stack, val3);
test("push(24) legt 24 oben auf den Stack", *(int*)stack->data == 24);
// Test top()
int t = *(int*)top(stack);
test("top() liefert 24", t == 24);
// Test pop()
StackNode *tmp;
tmp = stack;
stack = pop(stack);
free(tmp->data); // Daten freigeben
free(tmp); // Knoten freigeben
test("pop() entfernt 24, 6 ist jetzt oben", *(int*)stack->data == 6);
tmp = stack;
stack = pop(stack);
free(tmp->data);
free(tmp);
test("pop() entfernt 6, 5 ist jetzt oben", *(int*)stack->data == 5);
tmp = stack;
stack = pop(stack);
free(tmp->data);
free(tmp);
test("pop() entfernt 5, Stack ist jetzt leer", stack == NULL);
// Am Ende Stack leeren (falls noch Elemente übrig)
clearStack(stack);
return 0;
}
BIN
View File
Binary file not shown.