Compare commits

..
6 Commits
31 changed files with 137 additions and 681 deletions

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
Startcode/doble_initial
Startcode/doble
Startcode/unitTests
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# IDE folders
.vscode/
.idea/
# macOS
.DS_Store
Binary file not shown.
+36
View File
@@ -0,0 +1,36 @@
#include <string.h>
#include "stack.h"
#include "bintree.h"
//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)
{
}
// 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)
{
}
// Releases all memory resources (including data copies).
void clearTree(TreeNode *root)
{
}
// Returns the number of entries in the tree given by root.
unsigned int treeSize(const TreeNode *root)
{
}
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
+8 -24
View File
@@ -29,37 +29,21 @@ program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
doble : main.o $(program_obj_files)
$(CC) $(FLAGS) $^ -o doble
# --------------------------
# Objektdateien kompilieren
# --------------------------
%.o: %.c
$(CC) -c $(FLAGS) $< -o $@
$(program_obj_files): %.o: %.c
$(CC) -c $(FLAGS) $^ -o $@
# --------------------------
# Unit Tests
# --------------------------
numbersTests: numbers.o numbersTests.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -I$(unityfolder) \
-o runNumbersTests \
numbersTests.c numbers.o $(unityfolder)/unity.c
stackTests: stack.o stackTests.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -I$(unityfolder) \
-o runStackTests \
stackTests.c stack.o $(unityfolder)/unity.c
bintreeTests: bintree.o stack.o bintreeTests.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -I$(unityfolder) \
-o runBintreeTests \
bintreeTests.c bintree.o stack.o $(unityfolder)/unity.c
unitTests:
echo "needs to be implemented"
# --------------------------
# Clean
# --------------------------
clean:
ifeq ($(OS),!Windows_NT)
del /f *.o doble *.exe
ifeq ($(OS),Windows_NT)
del /f *.o doble
else
rm -f *.o doble run*Tests*
endif
rm -f *.o doble
endif
File renamed without changes.
File renamed without changes.
File renamed without changes.
+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)
{
}
View File
File renamed without changes.
+5 -19
View File
@@ -10,38 +10,24 @@
// Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data)
{
StackNode *top = malloc(sizeof(StackNode));
top->next= stack;
top->data= data;
return top;
}
// 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;
}
}
}
-5
View File
@@ -8,11 +8,6 @@ The latest element is taken from the stack. */
#include <stdlib.h>
//TODO: passenden Datentyp als struct anlegen
typedef struct StackNode
{
void *data;
struct StackNode *next;
}StackNode;
// Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data);
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-104
View File
@@ -1,104 +0,0 @@
#include <string.h>
#include "stack.h"
#include "bintree.h"
//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)
{
if(root == NULL)
{
TreeNode *newNode = malloc(sizeof(TreeNode));
newNode->data = malloc(dataSize);
memcpy(newNode->data, data, dataSize);
newNode->left = NULL;
newNode->right = NULL;
if(isDuplicate != NULL)
*isDuplicate = 0;
return newNode;
}
else
{
int cmpResult = compareFct(data, root->data);
if(cmpResult < 0)
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
else if(cmpResult > 0)
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
else
{
// Duplicate found
if(isDuplicate != NULL)
*isDuplicate = 1;
}
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.
void *nextTreeData(TreeNode *root)
{
static StackNode *stack = NULL;
if (root != NULL)
{
clearStack(stack);
stack = NULL;
TreeNode *current = root;
while (current != NULL)
{
stack = push(stack, current);
current = current->left;
}
}
if (stack == NULL)
return NULL;
TreeNode *node = (TreeNode *)top(stack);
stack = pop(stack);
void *data = node->data;
TreeNode *current = node->right;
while (current != NULL)
{
stack = push(stack, current);
current = current->left;
}
return data;
}
// Releases all memory resources (including data copies).
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.
unsigned int treeSize(const TreeNode *root)
{
if(root == NULL)
return 0;
return 1 + treeSize(root->left) + treeSize(root->right);
}
-122
View File
@@ -1,122 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "unity.h"
#include "bintree.h"
/* ---------- Helper ---------- */
int compareInt(const void *a, const void *b)
{
int ia = *(const int *)a;
int ib = *(const int *)b;
return ia - ib;
}
void setUp(void){}
void tearDown(void){}
/* ---------- addToTree ---------- */
void test_addToTree_adds_first_element(void)
{
TreeNode *root = NULL;
int value = 5;
int isDup = -1;
root = addToTree(root, &value, sizeof(int), compareInt, &isDup);
TEST_ASSERT_NOT_NULL(root);
TEST_ASSERT_EQUAL_INT(0, isDup);
TEST_ASSERT_EQUAL_INT(1, treeSize(root));
clearTree(root);
}
void test_addToTree_detects_duplicate(void)
{
TreeNode *root = NULL;
int value = 5;
int isDup = -1;
root = addToTree(root, &value, sizeof(int), compareInt, &isDup);
root = addToTree(root, &value, sizeof(int), compareInt, &isDup);
TEST_ASSERT_EQUAL_INT(1, isDup);
TEST_ASSERT_EQUAL_INT(1, treeSize(root));
clearTree(root);
}
/* ---------- treeSize ---------- */
void test_treeSize_counts_multiple_elements(void)
{
TreeNode *root = NULL;
int values[] = {5, 2, 8, 1, 3};
for (int i = 0; i < 5; i++)
root = addToTree(root, &values[i], sizeof(int), compareInt, NULL);
TEST_ASSERT_EQUAL_UINT(5, treeSize(root));
clearTree(root);
}
/* ---------- nextTreeData ---------- */
void test_nextTreeData_returns_sorted_order(void)
{
TreeNode *root = NULL;
int values[] = {5, 2, 8, 1, 3};
for (int i = 0; i < 5; i++)
root = addToTree(root, &values[i], sizeof(int), compareInt, NULL);
int expected[] = {1, 2, 3, 5, 8};
int *val;
/* erster Aufruf initialisiert den Iterator */
val = (int *)nextTreeData(root);
TEST_ASSERT_NOT_NULL(val);
TEST_ASSERT_EQUAL_INT(expected[0], *val);
/* weitere Aufrufe liefern die nächsten Elemente */
for (int i = 1; i < 5; i++)
{
val = (int *)nextTreeData(NULL);
TEST_ASSERT_NOT_NULL(val);
TEST_ASSERT_EQUAL_INT(expected[i], *val);
}
/* danach muss NULL kommen */
TEST_ASSERT_NULL(nextTreeData(NULL));
clearTree(root);
}
/* ---------- clearTree ---------- */
void test_clearTree_on_empty_tree_does_not_crash(void)
{
clearTree(NULL);
TEST_PASS();
}
/* ---------- MAIN ---------- */
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_addToTree_adds_first_element);
RUN_TEST(test_addToTree_detects_duplicate);
RUN_TEST(test_treeSize_counts_multiple_elements);
RUN_TEST(test_nextTreeData_returns_sorted_order);
RUN_TEST(test_clearTree_on_empty_tree_does_not_crash);
return UNITY_END();
}
-98
View File
@@ -1,98 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdbool.h>
#include "numbers.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)
{
if (len < 2) {
// Mindestens zwei Elemente nötig, damit ein Duplikat existiert
return NULL;
}
unsigned int *numbers = malloc(len * sizeof(unsigned int));
if (!numbers) return NULL;
bool *used = calloc(2 * len + 1, sizeof(bool));
if (!used) {
free(numbers);
return NULL;
}
static int initialized = 0;
if (!initialized) {
srand((unsigned int)time(NULL));
initialized = 1;
}
// Einzigartige Zufallszahlen generieren
for (unsigned int i = 0; i < len - 1; ) {
unsigned int num = (rand() % (2 * len)) + 1;
if (!used[num]) {
used[num] = true;
numbers[i++] = num;
}
}
// Eine der Zahlen duplizieren
unsigned int duplicateIndex = rand() % (len - 1);
numbers[len - 1] = numbers[duplicateIndex];
// Fisher–Yates shuffle
for (unsigned int i = len - 1; i > 0; i--) {
unsigned int j = rand() % (i + 1);
unsigned int tmp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = tmp;
}
free(used);
return numbers;
}
// 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;
}
unsigned int *sortedNumbers = malloc(len * sizeof(unsigned int));
if (sortedNumbers == NULL) {
return 0;
}
memcpy(sortedNumbers, numbers, len * sizeof(unsigned int));
// Einfacher bubble sort
for (unsigned int i = 0; i < len - 1; i++) {
for (unsigned int j = 0; j < len - i - 1; j++) {
if (sortedNumbers[j] > sortedNumbers[j + 1]) {
unsigned int temp = sortedNumbers[j];
sortedNumbers[j] = sortedNumbers[j + 1];
sortedNumbers[j + 1] = temp;
}
}
}
unsigned int duplicate = 0;
for (unsigned int i = 0; i < len - 1; i++) {
if (sortedNumbers[i] == sortedNumbers[i + 1]) {
duplicate = sortedNumbers[i];
break;
}
}
free(sortedNumbers);
return duplicate;
}
-179
View File
@@ -1,179 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "numbers.h"
#include "unity.h"
#include <stdbool.h>
//Initialisierung
void setUp(void){}
void tearDown(void){}
// Hilfsfunktion: zählt Vorkommen eines Werts
static unsigned int countOccurrences(unsigned int* arr, unsigned int n, unsigned int value)
{
unsigned int count = 0;
for (unsigned int i = 0; i < n; i++)
if (arr[i] == value)
count++;
return count;
}
// ---------------------------------------------------------------------------
// Test 1: createNumbers erzeugt ein Array der richtigen Größe
// ---------------------------------------------------------------------------
void test_createNumbers_returns_valid_array(void)
{
unsigned int n = 50;
unsigned int* arr = createNumbers(n);
TEST_ASSERT_NOT_NULL(arr);
// Ein paar Werte prüfen (dürfen alles sein, nur kein Segfault)
for (unsigned int i = 0; i < n; i++)
TEST_ASSERT_TRUE(arr[i] >= 0);
free(arr);
}
// ---------------------------------------------------------------------------
// Test 2: createNumbers erzeugt GENAU EIN Duplikat
// ---------------------------------------------------------------------------
void test_createNumbers_contains_exactly_one_duplicate(void)
{
unsigned int n = 50;
unsigned int* arr = createNumbers(n);
TEST_ASSERT_NOT_NULL(arr);
// zähle wie viele Werte doppelt vorkommen
unsigned int duplicateValue = 0;
unsigned int totalDuplicateAppearances = 0;
for (unsigned int i = 0; i < n; i++)
{
unsigned int c = countOccurrences(arr, n, arr[i]);
if (c == 2) // genau zweimal → Bestandteil des Duplikats
{
duplicateValue = arr[i];
totalDuplicateAppearances++;
}
}
// Wenn genau eine Zahl doppelt vorkommt,
// finden wir sie zweimal → totalDuplicateAppearances == 2
TEST_ASSERT_EQUAL_UINT(2, totalDuplicateAppearances);
free(arr);
}
// ---------------------------------------------------------------------------
// Test 3: getDuplicated findet genau die richtige doppelte Zahl
// ---------------------------------------------------------------------------
void test_getDuplicated_finds_correct_duplicate(void)
{
unsigned int n = 50;
unsigned int* arr = createNumbers(n);
TEST_ASSERT_NOT_NULL(arr);
// Ermittle das Duplikat manuell
unsigned int expected = 0;
for (unsigned int i = 0; i < n; i++)
{
if (countOccurrences(arr, n, arr[i]) == 2)
{
expected = arr[i];
break;
}
}
unsigned int result = getDuplicate(arr, n);
TEST_ASSERT_EQUAL_UINT(expected, result);
free(arr);
}
// ---------------------------------------------------------------------------
// Hilfsfunktion: prüft ob createNumbers einen Fehlerzustand signalisiert
// Du kannst diese später anpassen (z.B. wenn Fehler-Flags eingebaut werden)
// ---------------------------------------------------------------------------
static bool did_createNumbers_fail(unsigned int* ptr)
{
return (ptr == NULL); // aktuell: NULL bedeutet Fehler
}
// ---------------------------------------------------------------------------
// Test: createNumbers soll bei count < 2 fehlschlagen
// ---------------------------------------------------------------------------
void test_createNumbers_rejects_too_small_counts(void)
{
unsigned int* r1 = createNumbers(0);
unsigned int* r2 = createNumbers(1);
TEST_ASSERT_TRUE(did_createNumbers_fail(r1));
TEST_ASSERT_TRUE(did_createNumbers_fail(r2));
}
// ---------------------------------------------------------------------------
// Test: createNumbers(2) soll funktionieren (Minimum gültiger Input)
// ---------------------------------------------------------------------------
void test_createNumbers_with_two_elements_is_valid(void)
{
unsigned int* arr = createNumbers(2);
TEST_ASSERT_FALSE(did_createNumbers_fail(arr));
TEST_ASSERT_NOT_NULL(arr);
// should contain exactly one duplicate
unsigned int c0 = countOccurrences(arr, 2, arr[0]);
unsigned int c1 = countOccurrences(arr, 2, arr[1]);
TEST_ASSERT_TRUE((c0 == 2) || (c1 == 2));
free(arr);
}
// ---------------------------------------------------------------------------
// Test: getDuplicate() soll Fehler erkennen, wenn arr == NULL
// ---------------------------------------------------------------------------
void test_getDuplicate_handles_null_pointer(void)
{
unsigned int result = getDuplicate(NULL, 10);
// Erwartung: Fehlerzustand → aktuell vermutlich 0 oder UINT_MAX
// Wir prüfen nur, DASS es ein Fehler ist:
TEST_ASSERT_TRUE(result == 0 || result == UINT_MAX);
}
// ---------------------------------------------------------------------------
// Test: getDuplicated) soll Fehler erkennen, wenn count < 2
// ---------------------------------------------------------------------------
void test_getDuplicate_handles_invalid_count(void)
{
unsigned int dummy[1] = { 5 };
unsigned int result = getDuplicate(dummy, 1);
TEST_ASSERT_TRUE(result == 0 || result == UINT_MAX);
}
// ---------------------------------------------------------------------------
// main() für Unity
// ---------------------------------------------------------------------------
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_createNumbers_returns_valid_array);
RUN_TEST(test_createNumbers_contains_exactly_one_duplicate);
RUN_TEST(test_getDuplicated_finds_correct_duplicate);
RUN_TEST(test_createNumbers_rejects_too_small_counts);
RUN_TEST(test_createNumbers_with_two_elements_is_valid);
RUN_TEST(test_getDuplicate_handles_null_pointer);
RUN_TEST(test_getDuplicate_handles_invalid_count);
return UNITY_END();
}
-130
View File
@@ -1,130 +0,0 @@
/*#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#include "unity.h"
//Initialisierung
void setUp(void){}
void tearDown(void){}
void test_push_created_new_stacknode(void)
{
int testdata1 = 111;
StackNode test = {&testdata1,NULL};
int testdata2 = 222;
StackNode *test1 = push(&test,&testdata2);
TEST_ASSERT_NOT_NULL(test1);
TEST_ASSERT_EQUAL_PTR(&testdata2,test1->data);
TEST_ASSERT_EQUAL_PTR(&test,test1->next);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_push_created_new_stacknode);
return UNITY_END();
}*/
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#include "unity.h"
void setUp(void){}
void tearDown(void){}
/* ---------------- PUSH ---------------- */
void test_push_created_new_stacknode(void)
{
int testdata1 = 111;
StackNode test = {&testdata1,NULL};
int testdata2 = 222;
StackNode *test1 = push(&test,&testdata2);
TEST_ASSERT_NOT_NULL(test1);
TEST_ASSERT_EQUAL_PTR(&testdata2,test1->data);
TEST_ASSERT_EQUAL_PTR(&test,test1->next);
}
/* ---------------- TOP ---------------- */
void test_top_on_empty_stack_returns_null(void)
{
TEST_ASSERT_NULL(top(NULL));
}
void test_top_returns_top_element(void)
{
int data = 42;
StackNode node = {&data, NULL};
TEST_ASSERT_EQUAL_PTR(&data, top(&node));
}
/* ---------------- POP ---------------- */
void test_pop_on_empty_stack_returns_null(void)
{
TEST_ASSERT_NULL(pop(NULL));
}
void test_pop_removes_top_element(void)
{
int d1 = 1;
int d2 = 2;
StackNode *s = NULL;
s = push(s, &d1);
s = push(s, &d2);
StackNode *newTop = pop(s);
TEST_ASSERT_NOT_NULL(newTop);
TEST_ASSERT_EQUAL_PTR(&d1, newTop->data);
clearStack(newTop); // Speicher aufräumen
}
/* ---------------- CLEAR ---------------- */
void test_clearStack_on_empty_stack_does_not_crash(void)
{
clearStack(NULL);
TEST_PASS(); // Test besteht, wenn kein Crash
}
void test_clearStack_clears_multiple_elements(void)
{
int d1 = 1, d2 = 2, d3 = 3;
StackNode *s = NULL;
s = push(s, &d1);
s = push(s, &d2);
s = push(s, &d3);
clearStack(s);
TEST_PASS(); // kein Crash = bestanden
}
/* ---------------- MAIN ---------------- */
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_push_created_new_stacknode);
RUN_TEST(test_top_on_empty_stack_returns_null);
RUN_TEST(test_top_returns_top_element);
RUN_TEST(test_pop_on_empty_stack_returns_null);
RUN_TEST(test_pop_removes_top_element);
RUN_TEST(test_clearStack_on_empty_stack_does_not_crash);
RUN_TEST(test_clearStack_clears_multiple_elements);
return UNITY_END();
}