Compare commits

..

No commits in common. "6311aff9d721499bd493fcef76ebee97fd3f22e6" and "e7a9f798cb43c262dd5ac6def04912ce620ecc56" have entirely different histories.

10 changed files with 146 additions and 567 deletions

134
bintree.c
View File

@ -1,119 +1,47 @@
#include "bintree.h"
#include "stack.h"
#include <string.h> #include <string.h>
#include "stack.h"
#include "bintree.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. */
// typedef int (*CompareFctType)(const void *arg1, const void *arg2); // Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates
// Adds a copy of data's pointer destination to the tree using compareFct for // if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added).
// ordering. Accepts duplicates if isDuplicate is NULL, otherwise ignores TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
// 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;
const unsigned char *s = src;
for (size_t i = 0; i < size; i++) {
d[i] = s[i];
}
} }
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, // 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.
CompareFctType compareFct, int *isDuplicate) { // 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)
{
// 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). // Releases all memory resources (including data copies).
void clearTree(TreeNode *root) { void clearTree(TreeNode *root)
if (root == NULL) {
return; if(root->right)
clearTree(root->right);
clearTree(root->left); else if (root->left)
clearTree(root->right); clearTree(root->left);
else
free(root->data); {
free(root); 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. // Returns the number of entries in the tree given by root.
unsigned int treeSize(const TreeNode *root) { unsigned int treeSize(const TreeNode *root)
{
if (root == NULL)
return 0;
return 1 + treeSize(root->left) + treeSize(root->right);
} }

View File

@ -5,24 +5,19 @@
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; {
struct node *left; void *data;
struct node *right; struct node *left;
struct node *right;
} TreeNode; } TreeNode;
void copyData(void *dest, const void *src, size_t size); // 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).
// 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 // 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.
// duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). // Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element,
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, // push the top node and push all its left nodes.
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,10 +1,2 @@
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,49 +25,32 @@ 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
STACK_TEST_BIN = runStackTests unitTests: stack.o test_stack.o
NUMBERS_TEST_BIN = runNumbersTests $(CC) $(FLAGS) $(ASAN_FLAGS) -I$(unityfolder) -o $(TEST_BIN) stack.o test_stack.o $(unityfolder)/unity.c
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:
rm -f *.o doble $(STACK_TEST_BIN) $(NUMBERS_TEST_BIN) $(BINARY_TEST_BIN) ifeq ($(OS),Windows_NT)
rm -f *.o doble
else
rm -f *.o doble
endif

103
numbers.c
View File

@ -1,91 +1,26 @@
#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>
int compareUnsignedInt(const void *a, const void *b) { //TODO: getDuplicate und createNumbers implementieren
unsigned int x = *(unsigned int *)a; /* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen.
unsigned int y = *(unsigned int *)b; * 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 (x < y)
return -1;
if (x > y)
return 1;
return 0;
} }
// TODO: getDuplicate und createNumbers implementieren // Returns only the only number in numbers which is present twice. Returns zero on errors.
/**Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
* 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)
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.
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;
}

101
stack.c
View File

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

10
stack.h
View File

@ -19,6 +19,16 @@ 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);

View File

@ -1,105 +0,0 @@
#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();
}

View File

@ -1,61 +0,0 @@
#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,126 +5,39 @@
#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
TEST_ASSERT_NOT_NULL( StackNode *testNode = createNode(&testInt);
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);
free(testNode); // Speicher freigeben TEST_ASSERT_NOT_NULL(testNode);
TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data);
TEST_ASSERT_NULL(testNode->next);
free(testNode);
} }
// StackNode *push(StackNode *stack, void *data) testen void test_pushDataToStack(void) {}
void test_pushDataToStack(void) {
int testInts[] = {27, 28}; void test_deleteTopElement(void) {}
StackNode *testStack = NULL; // leeren testStack initialisieren void test_returnData(void) {}
testStack =
push(testStack, &testInts[0]); // leerer Stack mit Adresse des testInts
TEST_ASSERT_NOT_NULL(testStack); // im Fehlerfall wird testStack unverändert
// 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);
// zweiter Push
StackNode *oldHead = testStack; // bisherigen head speichern
testStack = push(testStack, &testInts[1]);
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]);
}
TEST_ASSERT_EQUAL_PTR(&testInts[2], stack->data);
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) { void test_clearStack(void) {
int testInts[] = {1, 2, 3, 4, 5}; int testInts[] = {1, 2, 3, 4, 5};
StackNode *stack = NULL; StackNode *testStack = NULL;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
stack = push(stack, &testInts[i]);
testStack = push(testStack, &testInts[i]);
} }
clearStack(&stack); clearStack(&testStack);
TEST_ASSERT_NULL(testStack);
TEST_ASSERT_NULL(stack);
} }
void setUp(void) {} void setUp(void) {}
@ -134,13 +47,13 @@ int main(void) {
UNITY_BEGIN(); UNITY_BEGIN();
printf("\n------------------------stack test------------------------\n\n"); printf("------------------------stack test------------------------\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();
} }