Merge remote-tracking branch 'origin/Krisp' into tobi_experimental

This commit is contained in:
Tobias Kachel 2025-12-09 09:59:34 +01:00
commit 6311aff9d7
10 changed files with 568 additions and 147 deletions

140
bintree.c
View File

@ -1,47 +1,119 @@
#include <string.h>
#include "stack.h"
#include "bintree.h" #include "bintree.h"
#include "stack.h"
#include <string.h>
//TODO: binären Suchbaum implementieren // TODO: binären Suchbaum implementieren
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv), /* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv),
* `clearTree`: gibt den gesamten Baum frei (rekursiv), * `clearTree`: gibt den gesamten Baum frei (rekursiv),
* `treeSize`: zählt die Knoten im Baum (rekursiv), * `treeSize`: zählt die Knoten im Baum (rekursiv),
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */ * `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 // typedef int (*CompareFctType)(const void *arg1, const void *arg2);
// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). // Adds a copy of data's pointer destination to the tree using compareFct for
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) // ordering. Accepts duplicates if isDuplicate is NULL, otherwise ignores
{ // duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added).
} void copyData(void *dest, const void *src, size_t size) {
unsigned char *d = dest;
// 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. const unsigned char *s = src;
// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, for (size_t i = 0; i < size; i++) {
// push the top node and push all its left nodes. d[i] = s[i];
void *nextTreeData(TreeNode *root)
{
}
// Releases all memory resources (including data copies).
void clearTree(TreeNode *root)
{
if(root->right)
clearTree(root->right);
else if (root->left)
clearTree(root->left);
else
{
root->data = 0;
free(root->data);
free(root->right);
free(root->left);
free(root);
} }
} }
// Returns the number of entries in the tree given by root. TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
unsigned int treeSize(const TreeNode *root) CompareFctType compareFct, int *isDuplicate) {
{
// isDuplicate initialisieren (auf 0 setzen)
if (isDuplicate) {
*isDuplicate = 0;
}
// leerer Baum
if (root == NULL) {
TreeNode *node = malloc(sizeof(TreeNode));
node->data = malloc(dataSize);
copyData(node->data, data, dataSize);
node->left = NULL;
node->right = NULL;
return node;
}
// mit compareFct <0 links >0 rechts =0 Duplikat
int cmp = compareFct(data, root->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 {
// isDuplicate auf 1 setzen
if (isDuplicate) {
*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;
// Neue Iteration starten
if (root != NULL) {
clearStack(&stack);
TreeNode *curr = root;
while (curr != NULL) {
StackNode *oldStack = stack;
StackNode *newStack = push(stack, curr);
if (newStack == oldStack)
return NULL; // push fehlgeschlagen
stack = newStack;
curr = curr->left;
}
}
if (stack == NULL)
return NULL; // alles durchlaufen
// Oberstes Element abrufen
TreeNode *node = (TreeNode *)top(stack);
stack = pop(stack);
// Rechten Teilbaum pushen
TreeNode *curr = node->right;
while (curr != NULL) {
StackNode *oldStack = stack;
StackNode *newStack = push(stack, curr);
if (newStack == oldStack)
return NULL; // push fehlgeschlagen
stack = newStack;
curr = curr->left;
}
return node->data;
}
// Releases all memory resources (including data copies).
void clearTree(TreeNode *root) {
if (root == NULL)
return;
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);
} }

View File

@ -5,19 +5,24 @@
typedef int (*CompareFctType)(const void *arg1, const void *arg2); typedef int (*CompareFctType)(const void *arg1, const void *arg2);
typedef struct node typedef struct node {
{
void *data; void *data;
struct node *left; struct node *left;
struct node *right; struct node *right;
} TreeNode; } TreeNode;
// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates void copyData(void *dest, const void *src, size_t size);
// 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); // Adds a copy of data's pointer destination to the tree using compareFct for
// 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. // ordering. Accepts duplicates if isDuplicate is NULL, otherwise ignores
// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, // duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added).
// push the top node and push all its left nodes. 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); void *nextTreeData(TreeNode *root);
// Releases all memory resources (including data copies). // Releases all memory resources (including data copies).
void clearTree(TreeNode *root); void clearTree(TreeNode *root);

View File

@ -1,2 +1,10 @@
Kristin;9944
Kristin;7947
Kristin;6962
Kristin;5987
Kristin;5975
krisp;4986 krisp;4986
krisp;4985
Kristin;4972
player1;3999 player1;3999
Kristin;3992

View File

@ -25,32 +25,49 @@ doble_initial:
# -------------------------- # --------------------------
# Selbst implementiertes Programm bauen # Selbst implementiertes Programm bauen
# -------------------------- # --------------------------
# alle Objektdateien
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
# alle ausführbaren Dateien zu ausführbarem Programm linken
doble : main.o $(program_obj_files) doble : main.o $(program_obj_files)
$(CC) $(FLAGS) $^ -o doble $(CC) $(FLAGS) $^ -o doble
# Regel Kompilieren allgemein
$(program_obj_files): %.o: %.c $(program_obj_files): %.o: %.c
$(CC) -c $(FLAGS) $^ -o $@ $(CC) -c $(FLAGS) $^ -o $@
# -------------------------- # --------------------------
# Unit Tests # Unit Tests
# -------------------------- # --------------------------
unitTests:
TEST_BIN = runTests
unitTests: stack.o test_stack.o STACK_TEST_BIN = runStackTests
$(CC) $(FLAGS) $(ASAN_FLAGS) -I$(unityfolder) -o $(TEST_BIN) stack.o test_stack.o $(unityfolder)/unity.c NUMBERS_TEST_BIN = runNumbersTests
BINARY_TEST_BIN = runBinaryTests
# --- Stack Tests ---
stackTests: stack.o test_stack.o
$(CC) $(FLAGS) -I$(unityfolder) -o $(STACK_TEST_BIN) stack.o test_stack.o $(unityfolder)/unity.c
test_stack.o: test_stack.c test_stack.o: test_stack.c
$(CC) $(FLAGS) -I$(unityfolder) -c test_stack.c -o test_stack.o $(CC) $(FLAGS) -I$(unityfolder) -c test_stack.c -o test_stack.o
# --- Numbers Tests ---
numbersTests: numbers.o bintree.o stack.o test_numbers.o
$(CC) $(FLAGS) -I$(unityfolder) -o $(NUMBERS_TEST_BIN) numbers.o bintree.o stack.o test_numbers.o $(unityfolder)/unity.c
test_numbers.o: test_numbers.c
$(CC) $(FLAGS) -I$(unityfolder) -c test_numbers.c -o test_numbers.o
# --- Binary Tree Tests ---
binaryTests: bintree.o stack.o test_binary.o
$(CC) $(FLAGS) -I$(unityfolder) -o $(BINARY_TEST_BIN) bintree.o stack.o test_binary.o $(unityfolder)/unity.c
test_binary.o: test_binary.c
$(CC) $(FLAGS) -I$(unityfolder) -c test_binary.c -o test_binary.o
# -------------------------- # --------------------------
# Clean # Clean
# -------------------------- # --------------------------
clean: clean:
ifeq ($(OS),Windows_NT) rm -f *.o doble $(STACK_TEST_BIN) $(NUMBERS_TEST_BIN) $(BINARY_TEST_BIN)
rm -f *.o doble
else
rm -f *.o doble
endif

View File

@ -1,26 +1,91 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "numbers.h" #include "numbers.h"
#include "bintree.h" #include "bintree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
//TODO: getDuplicate und createNumbers implementieren int compareUnsignedInt(const void *a, const void *b) {
/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. unsigned int x = *(unsigned int *)a;
* Sicherstellen, dass beim Befüllen keine Duplikate entstehen. unsigned int y = *(unsigned int *)b;
if (x < y)
return -1;
if (x > y)
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. * Duplizieren eines zufälligen Eintrags im Array.
* in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ * 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 len random numbers between 1 and 2x len in random order which are all
// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while // different, except for two entries. Returns NULL on errors. Use your
// creating random numbers. // implementation of the binary search tree to check for possible duplicates
unsigned int *createNumbers(unsigned int len) // while creating random numbers.
{ unsigned int *createNumbers(unsigned int len) {
if (len < 2)
return NULL;
unsigned int *arr = malloc(sizeof(unsigned int) * len);
if (!arr)
return NULL;
TreeNode *root = NULL;
srand((unsigned int)time(NULL));
for (unsigned int i = 0; i < len - 1; i++) {
unsigned int num;
int isDuplicate;
do {
num = (rand() % (2 * len)) + 1;
isDuplicate = 0;
root = addToTree(root, &num, sizeof(unsigned int), compareUnsignedInt,
&isDuplicate);
} while (isDuplicate); // nur akzeptieren, wenn eindeutig
arr[i] = num;
}
// Jetzt gezielt EIN Duplikat erzeugen
unsigned int duplicateIndex = rand() % (len - 1);
arr[len - 1] = arr[duplicateIndex];
clearTree(root);
return arr;
} }
// Returns only the only number in numbers which is present twice. Returns zero on errors. // Returns only the only number in numbers which is present twice. Returns zero
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) // on errors.
{ unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) {
if (!numbers || len < 2)
return 0;
unsigned int *copy = malloc(sizeof(unsigned int) * len);
if (!copy)
return 0;
memcpy(copy, numbers, sizeof(unsigned int) * len);
// Sortierung
qsort(copy, len, sizeof(unsigned int), compareUnsignedInt);
// Duplikat finden: zwei gleiche nebeneinander
unsigned int duplicate = 0;
for (unsigned int i = 0; i < len - 1; i++) {
if (copy[i] == copy[i + 1]) {
duplicate = copy[i];
break;
}
}
free(copy);
return duplicate;
} }

87
stack.c
View File

@ -6,6 +6,7 @@
void *data; void *data;
struct StackNode *next; struct StackNode *next;
struct StackNode *prev;
} StackNode;*/ } StackNode;*/
@ -15,70 +16,80 @@
* `top`: liefert das oberste Element zurück, * `top`: liefert das oberste Element zurück,
* `clearStack`: gibt den gesamten Speicher frei. */ * `clearStack`: gibt den gesamten Speicher frei. */
StackNode *createNode(void *data) // [A] -> [B] -> [C] -> NULL
{ // stack -> stack.next
StackNode *node =
malloc(sizeof(StackNode)); // Speicher reservieren, Speicherplatz für das
// struct StackNode
// Funktion zum erstellen neuer nodes
StackNode *createNode(void *data) {
// Speicher reservieren
StackNode *node = malloc(sizeof(StackNode));
// Speicher konnte nicht reserviert werden
if (node == NULL) if (node == NULL)
return NULL; // Speicher konnte nicht reserviert werden return NULL;
node->data = data; // Zeiger auf data neuer node node->data = data;
node->next = NULL; // nächster Zeiger ist NULL, Ende der Liste node->next = NULL;
node->prev = NULL;
return node; // pointer auf den neuen Knoten zurückgeben return node;
} }
// 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) {
{
StackNode *newNode = createNode(data); // Speicher für neuen Knoten
// reservieren
if (newNode == NULL) StackNode *newNode = createNode(data);
{ // wenn Speicher nicht reserviert werden konnte, wird
// stack unverändert zurückgegeben // Fehler beim Reservieren des Speichers, stack wird unverändert zurückgegeben
if (newNode == NULL) {
return stack; return stack;
} }
newNode->next = stack; // pointer verschieben // der aktuelle Kopf wird der nächste Node
newNode->next = stack;
return newNode; // Zeiger auf neuen Speicherbereich zurückgeben // bisheriger Kopf bekommt Pointer auf oberstes Element
if (stack != NULL) {
stack->prev = newNode;
}
return newNode; // neuer Kopf wird zurückgegeben
} }
// 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
// freed by caller.) // memory. (Pointer to data has to be freed by caller.)
StackNode *pop(StackNode *stack) StackNode *pop(StackNode *stack) {
{
// Stack ohne Elemente
if (stack == NULL) if (stack == NULL)
return NULL; return NULL;
// Element unter Kopf wird als nextNode gespeichert
StackNode *nextNode = stack->next; StackNode *nextNode = stack->next;
if (nextNode != NULL) {
nextNode->prev = NULL; // der Zeiger zum Kopf wird auf NULL gesetzt
}
free(stack); free(stack);
stack = NULL; stack = NULL; // Speicher des Kopfes freigeben
return nextNode; return nextNode; // neuen Kopf zurückgeben
} }
// Returns the data of the top element. // Returns the data of the top element.
void *top(StackNode *stack) { return stack != NULL ? stack->data : NULL; } void *top(StackNode *stack) {
// wenn stack leer ist, wird NULL zurückgegeben
// Zeiger auf Daten des obersten Elements
return stack ? stack->data : NULL;
}
// Clears stack and releases all memory. // Clears stack and releases all memory.
void clearStack(StackNode **stack) void clearStack(StackNode **stack) { // Zeiger auf den Zeiger auf den Stackkopf
{ // verändert den Zeiger selbst, mit *stack lokale Kopie
while (*stack != NULL) // im Aufruf &stack verwenden
{ while (*stack != NULL) {
StackNode *next = (*stack)->next; // nächstes Element speichern
StackNode *next = (*stack)->next; free(*stack); // aktuelles Element freigeben
free(*stack); *stack = next; // Zeiger auf nächsten Knoten setzen
(*stack)->data = NULL;
(*stack)->next = NULL;
(*stack)->prev = NULL;
(*stack) = next;
} }
} }

10
stack.h
View File

@ -19,16 +19,6 @@ typedef struct StackNode {
StackNode *createNode(void *data); StackNode *createNode(void *data);
typedef struct StackNode {
void *data;
struct StackNode *next;
struct StackNode *prev;
} StackNode;
StackNode *createNode(void *data);
// 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);

105
test_binary.c Normal file
View File

@ -0,0 +1,105 @@
#include "unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bintree.h"
int compareUnsignedInt(const void *a, const void *b) {
unsigned int x = *(unsigned int *)a;
unsigned int y = *(unsigned int *)b;
if (x < y)
return -1;
if (x > y)
return 1;
return 0;
}
TreeNode *root = NULL;
void setUp(void) {
root = NULL; // vor jedem Test leeren
}
void tearDown(void) { clearTree(root); }
// Test, ob addToTree Knoten korrekt hinzufügt
void test_addToTree_basic(void) {
int isDup;
unsigned int val = 10;
root = addToTree(root, &val, sizeof(val), compareUnsignedInt, &isDup);
TEST_ASSERT_NOT_NULL(root);
TEST_ASSERT_EQUAL_UINT(10, *(unsigned int *)root->data);
TEST_ASSERT_EQUAL_INT(0, isDup);
TEST_ASSERT_EQUAL_UINT(1, treeSize(root));
}
// Test, dass Duplikate erkannt werden
void test_addToTree_duplicate(void) {
int isDup;
unsigned int val1 = 10, val2 = 10;
root = addToTree(root, &val1, sizeof(val1), compareUnsignedInt, &isDup);
TEST_ASSERT_EQUAL_INT(0, isDup);
root = addToTree(root, &val2, sizeof(val2), compareUnsignedInt, &isDup);
TEST_ASSERT_EQUAL_INT(1, isDup);
TEST_ASSERT_EQUAL_UINT(1, treeSize(root)); // Duplikate nicht hinzufügen
}
// Test nextTreeData Traversierung
void test_nextTreeData_in_order(void) {
unsigned int values[] = {20, 10, 30};
int isDup;
for (int i = 0; i < 3; i++) {
root = addToTree(root, &values[i], sizeof(values[i]), compareUnsignedInt,
&isDup);
}
unsigned int expected[] = {10, 20, 30};
int idx = 0;
void *data;
// **Neue Iteration starten**
data = nextTreeData(root);
while (data != NULL) {
TEST_ASSERT_EQUAL_UINT(expected[idx], *(unsigned int *)data);
idx++;
data = nextTreeData(NULL); // weitere Elemente abrufen
}
TEST_ASSERT_EQUAL_INT(3, idx); // alle 3 Knoten besucht
}
// Test clearTree gibt Speicher frei
void test_clearTree(void) {
unsigned int val = 42;
int isDup;
root = addToTree(root, &val, sizeof(val), compareUnsignedInt, &isDup);
clearTree(root);
root = NULL; // clearTree löscht nicht die root-Variable selbst
TEST_ASSERT_NULL(root);
}
// Test treeSize zählt korrekt
void test_treeSize(void) {
unsigned int vals[] = {10, 20, 5};
int isDup;
for (int i = 0; i < 3; i++) {
root =
addToTree(root, &vals[i], sizeof(vals[i]), compareUnsignedInt, &isDup);
}
TEST_ASSERT_EQUAL_UINT(3, treeSize(root));
}
int main(void) {
UNITY_BEGIN();
printf(
"\n------------------------binarytree test------------------------\n\n");
RUN_TEST(test_addToTree_basic);
RUN_TEST(test_addToTree_duplicate);
RUN_TEST(test_nextTreeData_in_order);
RUN_TEST(test_clearTree);
RUN_TEST(test_treeSize);
return UNITY_END();
}

61
test_numbers.c Normal file
View File

@ -0,0 +1,61 @@
#include "unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "numbers.h"
#define TEST_ARRAY_LEN 100
void test_createNumbers_length(void) {
unsigned int *arr = createNumbers(TEST_ARRAY_LEN);
TEST_ASSERT_NOT_NULL(arr);
free(arr);
}
void test_createNumbers_single_duplicate(void) {
unsigned int *arr = createNumbers(TEST_ARRAY_LEN);
TEST_ASSERT_NOT_NULL(arr);
unsigned int duplicate = getDuplicate(arr, TEST_ARRAY_LEN);
TEST_ASSERT_TRUE(duplicate > 0);
unsigned int count = 0;
for (unsigned int i = 0; i < TEST_ARRAY_LEN; i++) {
if (arr[i] == duplicate) {
count++;
}
}
TEST_ASSERT_EQUAL_UINT(2, count);
free(arr);
}
void test_getDuplicate_manual_array(void) {
unsigned int numbers[5] = {10, 20, 30, 40, 20};
unsigned int dup = getDuplicate(numbers, 5);
TEST_ASSERT_EQUAL_UINT(20, dup);
}
void test_getDuplicate_invalid_input(void) {
TEST_ASSERT_EQUAL_UINT(0, getDuplicate(NULL, 5));
unsigned int arr[1] = {42};
TEST_ASSERT_EQUAL_UINT(0, getDuplicate(arr, 1));
}
void setUp(void) {}
void tearDown(void) {}
int main(void) {
UNITY_BEGIN();
printf("\n------------------------numbers test------------------------\n\n");
RUN_TEST(test_createNumbers_length);
RUN_TEST(test_createNumbers_single_duplicate);
RUN_TEST(test_getDuplicate_manual_array);
RUN_TEST(test_getDuplicate_invalid_input);
return UNITY_END();
}

View File

@ -5,39 +5,126 @@
#include "stack.h" #include "stack.h"
// StackNode *createNode(void *data) testen
void test_createNode(void) { void test_createNode(void) {
int testInt = 26; int testInt = 26;
StackNode *testNode = createNode(&testInt); // Adresse des testInts
StackNode *testNode = createNode(&testInt); TEST_ASSERT_NOT_NULL(
testNode); // Speicher konnte reserviert werden, malloc ist nicht NULL
TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data); // data pointer gesetzt
TEST_ASSERT_NULL(testNode->next); // vorheriger und nächster Eintrag NULL
TEST_ASSERT_NULL(testNode->prev);
TEST_ASSERT_NOT_NULL(testNode); free(testNode); // Speicher freigeben
TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data);
TEST_ASSERT_NULL(testNode->next);
free(testNode);
} }
void test_pushDataToStack(void) {} // StackNode *push(StackNode *stack, void *data) testen
void test_pushDataToStack(void) {
void test_deleteTopElement(void) {} int testInts[] = {27, 28};
void test_returnData(void) {} StackNode *testStack = NULL; // leeren testStack initialisieren
void test_clearStack(void) { testStack =
push(testStack, &testInts[0]); // leerer Stack mit Adresse des testInts
int testInts[] = {1, 2, 3, 4, 5}; TEST_ASSERT_NOT_NULL(testStack); // im Fehlerfall wird testStack unverändert
StackNode *testStack = NULL; // zurückgegeben -> bei Fehler NULL
TEST_ASSERT_EQUAL_PTR(&testInts[0], testStack->data); // data pointer gesetzt
TEST_ASSERT_NULL(testStack->next); // vorheriger und nächster pointer auf NULL
// gesetzt, da es nur einen Knoten gibt
TEST_ASSERT_NULL(testStack->prev);
for (int i = 0; i < 5; i++) { // zweiter Push
StackNode *oldHead = testStack; // bisherigen head speichern
testStack = push(testStack, &testInts[1]);
testStack = push(testStack, &testInts[i]); TEST_ASSERT_NOT_NULL(testStack);
TEST_ASSERT_NOT_EQUAL(
oldHead,
testStack); // bei malloc Fehler wird der head unverändert zurückgegeben
TEST_ASSERT_EQUAL_PTR(&testInts[0],
oldHead->data); // data pointer wurden richtig gesetzt
TEST_ASSERT_EQUAL_PTR(&testInts[1], testStack->data);
// richtige Verkettung: NULL <- testStack -> testStack->next -> oldHead ->
// NULL
TEST_ASSERT_EQUAL_PTR(oldHead, testStack->next);
TEST_ASSERT_EQUAL_PTR(testStack, oldHead->prev);
TEST_ASSERT_NULL(testStack->prev);
// Speicherfreigabe
testStack->next = NULL; // pointer ungültig machen, damit nicht ausversehen
// später aufgerufen
oldHead->prev = NULL;
free(oldHead);
free(testStack);
}
void test_deleteTopElement(void) {
int testInts[] = {10, 20, 30};
StackNode *stack = NULL;
for (int i = 0; i < 3;
i++) { // Stack mit drei Elementen, oberestes Element mit data 30
stack = push(stack, &testInts[i]);
} }
clearStack(&testStack); TEST_ASSERT_EQUAL_PTR(&testInts[2], stack->data);
TEST_ASSERT_NULL(testStack);
stack = pop(stack);
TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->data);
TEST_ASSERT_NULL(stack->prev);
stack = pop(stack);
TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->data);
TEST_ASSERT_NULL(stack->prev);
stack = pop(stack); // bei leerem Stack wird NULL zurückgegeben
TEST_ASSERT_NULL(stack);
}
void test_returnData(void) {
int testInts[] = {10, 20, 30};
StackNode *stack = NULL;
for (int i = 0; i < 3; i++) {
stack = push(stack, &testInts[i]);
}
TEST_ASSERT_EQUAL_PTR(&testInts[2], top(stack));
if (stack->next != NULL) {
TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->next->data);
if (stack->next->next != NULL) {
TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->next->next->data);
}
}
StackNode *last = stack;
while (last->next != NULL) {
last = last->next;
}
TEST_ASSERT_NULL(last->next);
}
void test_clearStack(void) {
int testInts[] = {1, 2, 3, 4, 5};
StackNode *stack = NULL;
for (int i = 0; i < 5; i++) {
stack = push(stack, &testInts[i]);
}
clearStack(&stack);
TEST_ASSERT_NULL(stack);
} }
void setUp(void) {} void setUp(void) {}
@ -47,13 +134,13 @@ int main(void) {
UNITY_BEGIN(); UNITY_BEGIN();
printf("------------------------stack test------------------------\n"); printf("\n------------------------stack test------------------------\n\n");
RUN_TEST(test_createNode); RUN_TEST(test_createNode);
RUN_TEST(test_pushDataToStack); RUN_TEST(test_pushDataToStack);
RUN_TEST(test_deleteTopElement); RUN_TEST(test_deleteTopElement);
RUN_TEST(test_returnData); RUN_TEST(test_returnData);
RUN_TEST(test_clearStack); RUN_TEST(test_clearStack);
RUN_TEST(test_clearStack);
return UNITY_END(); return UNITY_END();
} }