Fertig
This commit is contained in:
parent
c325131503
commit
d56c77d77a
113
bintree.c
113
bintree.c
@ -2,35 +2,126 @@
|
||||
#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)
|
||||
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
|
||||
CompareFctType compareFct, int *isDuplicate)
|
||||
{
|
||||
if (data == NULL || compareFct == NULL)
|
||||
return root;
|
||||
|
||||
if (root == NULL)
|
||||
{
|
||||
// neuer Knoten
|
||||
TreeNode *node = malloc(sizeof(TreeNode));
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
node->data = malloc(dataSize);
|
||||
if (node->data == NULL)
|
||||
{
|
||||
free(node);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(node->data, data, dataSize);
|
||||
node->left = NULL;
|
||||
node->right = NULL;
|
||||
|
||||
if (isDuplicate != NULL)
|
||||
*isDuplicate = 0;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
// Element bereits vorhanden
|
||||
if (isDuplicate != NULL)
|
||||
{
|
||||
*isDuplicate = 1;
|
||||
// Duplikate werden ignoriert
|
||||
}
|
||||
else
|
||||
{
|
||||
// Duplikate dürfen eingefügt werden -> wir hängen sie z.B. links an
|
||||
root->left = addToTree(root->left, data, dataSize, compareFct, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
// Interner Stack für die Traversierung (strtok-ähnliches Verhalten)
|
||||
static StackNode *iterStack = NULL;
|
||||
|
||||
// Hilfsfunktion: legt ab start alle linken Knoten auf den Stack
|
||||
static void pushLeftPath(TreeNode *start)
|
||||
{
|
||||
while (start != NULL)
|
||||
{
|
||||
iterStack = push(iterStack, start);
|
||||
start = start->left;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (root != NULL)
|
||||
{
|
||||
// neue Traversierung starten: alten Stack aufräumen
|
||||
if (iterStack != NULL)
|
||||
{
|
||||
clearStack(iterStack);
|
||||
iterStack = NULL;
|
||||
}
|
||||
pushLeftPath(root);
|
||||
}
|
||||
|
||||
if (iterStack == NULL)
|
||||
return NULL;
|
||||
|
||||
// Nächsten Knoten holen
|
||||
TreeNode *node = (TreeNode *)top(iterStack);
|
||||
iterStack = pop(iterStack);
|
||||
|
||||
// rechten Teilbaum dieses Knotens auf den Stack bringen
|
||||
if (node->right != NULL)
|
||||
pushLeftPath(node->right);
|
||||
|
||||
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 1u + treeSize(root->left) + treeSize(root->right);
|
||||
}
|
||||
|
||||
BIN
doble_initial.exe
Normal file
BIN
doble_initial.exe
Normal file
Binary file not shown.
BIN
highscore.o
Normal file
BIN
highscore.o
Normal file
Binary file not shown.
@ -1 +1,3 @@
|
||||
Kilian;9927
|
||||
Kilian;4975
|
||||
player1;3999
|
||||
|
||||
70
makefile
70
makefile
@ -1,4 +1,4 @@
|
||||
CC = gcc
|
||||
CC = gcc
|
||||
FLAGS = -g -Wall -lm
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
@ -13,10 +13,18 @@ else
|
||||
endif
|
||||
|
||||
raylibfolder = ./raylib
|
||||
unityfolder = ./unity
|
||||
unityfolder = ./unity
|
||||
|
||||
# --------------------------
|
||||
# Initiales Programm bauen (zum ausprobieren)
|
||||
# Phony Targets
|
||||
# --------------------------
|
||||
.PHONY: all doble doble_initial unitTests test_stack test_numbers clean vorbereitungen prepare
|
||||
|
||||
# Standard-Target
|
||||
all: doble
|
||||
|
||||
# --------------------------
|
||||
# Initiales Programm bauen (zum Ausprobieren)
|
||||
# --------------------------
|
||||
doble_initial:
|
||||
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
|
||||
@ -26,24 +34,66 @@ doble_initial:
|
||||
# --------------------------
|
||||
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
|
||||
|
||||
$(program_obj_filesobj_files): %.o: %.c
|
||||
$(CC) -c $(FLAGS) $^ -o $@
|
||||
# Generische Regel zum Bauen von .o aus .c
|
||||
%.o: %.c
|
||||
$(CC) $(FLAGS) -c $< -o $@
|
||||
|
||||
# Abhängigkeiten (optional, aber hilfreich für inkrementelles Bauen)
|
||||
main.o: main.c numbers.h stack.h bintree.h timer.h highscore.h
|
||||
numbers.o: numbers.c numbers.h bintree.h
|
||||
bintree.o: bintree.c bintree.h stack.h
|
||||
stack.o: stack.c stack.h
|
||||
timer.o: timer.c timer.h
|
||||
highscore.o: highscore.c highscore.h
|
||||
|
||||
test_stack.o: test_stack.c stack.h
|
||||
test_numbers.o: test_numbers.c numbers.h bintree.h stack.h
|
||||
|
||||
# --------------------------
|
||||
# Unit Tests
|
||||
# --------------------------
|
||||
unitTests:
|
||||
echo "needs to be implemented"
|
||||
test_stack: test_stack.o stack.o
|
||||
$(CC) $(FLAGS) $^ -o test_stack
|
||||
|
||||
test_numbers: test_numbers.o numbers.o stack.o bintree.o
|
||||
$(CC) $(FLAGS) $^ -o test_numbers
|
||||
|
||||
unitTests: test_stack test_numbers
|
||||
./test_stack
|
||||
./test_numbers
|
||||
|
||||
# --------------------------
|
||||
# Vorbereitungen zum Bauen des Programms
|
||||
# --------------------------
|
||||
vorbereitungen:
|
||||
@echo "== Vorbereitungen zum Bauen des Programms =="
|
||||
@echo "Prüfe benötigte Dateien..."
|
||||
@test -f numbers.c || (echo "FEHLT: numbers.c" && exit 1)
|
||||
@test -f numbers.h || (echo "FEHLT: numbers.h" && exit 1)
|
||||
@test -f bintree.c || (echo "FEHLT: bintree.c" && exit 1)
|
||||
@test -f bintree.h || (echo "FEHLT: bintree.h" && exit 1)
|
||||
@test -f stack.c || (echo "FEHLT: stack.c" && exit 1)
|
||||
@test -f stack.h || (echo "FEHLT: stack.h" && exit 1)
|
||||
@test -f timer.c || (echo "FEHLT: timer.c" && exit 1)
|
||||
@test -f timer.h || (echo "FEHLT: timer.h" && exit 1)
|
||||
@test -f highscore.c || (echo "FEHLT: highscore.c" && exit 1)
|
||||
@test -f highscore.h || (echo "FEHLT: highscore.h" && exit 1)
|
||||
@test -f main.c || (echo "FEHLT: main.c" && exit 1)
|
||||
@echo "Alle Dateien vorhanden."
|
||||
@echo "Vorbereitung abgeschlossen!"
|
||||
|
||||
# englischer Alias
|
||||
prepare: vorbereitungen
|
||||
|
||||
# --------------------------
|
||||
# Clean
|
||||
# --------------------------
|
||||
clean:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
del /f *.o doble
|
||||
del /f *.o doble doble_initial test_stack test_numbers
|
||||
else
|
||||
rm -f *.o doble
|
||||
rm -f *.o doble doble_initial test_stack test_numbers
|
||||
endif
|
||||
99
numbers.c
99
numbers.c
@ -5,22 +5,109 @@
|
||||
#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. */
|
||||
// Hilfsfunktion für qsort und den Binärbaum: Vergleich von unsigned int
|
||||
static int compareUnsignedInt(const void *a, const void *b)
|
||||
{
|
||||
const unsigned int *ua = (const unsigned int *)a;
|
||||
const unsigned int *ub = (const unsigned int *)b;
|
||||
|
||||
if (*ua < *ub)
|
||||
return -1;
|
||||
else if (*ua > *ub)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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 = malloc(len * sizeof(unsigned int));
|
||||
if (numbers == NULL)
|
||||
return NULL;
|
||||
|
||||
// Zufall initialisieren
|
||||
srand((unsigned int)time(NULL));
|
||||
|
||||
TreeNode *root = NULL;
|
||||
unsigned int i = 0;
|
||||
|
||||
// len-1 verschiedene Zufallszahlen im Bereich [1, 2*len] erzeugen
|
||||
while (i < len - 1)
|
||||
{
|
||||
unsigned int candidate = (unsigned int)(rand() % (2 * len)) + 1;
|
||||
int isDuplicate = 0;
|
||||
|
||||
TreeNode *newRoot = addToTree(root, &candidate, sizeof(unsigned int),
|
||||
compareUnsignedInt, &isDuplicate);
|
||||
if (newRoot == NULL && root == NULL)
|
||||
{
|
||||
// Speicherfehler beim ersten Einfügen
|
||||
clearTree(root);
|
||||
free(numbers);
|
||||
return NULL;
|
||||
}
|
||||
root = newRoot;
|
||||
|
||||
if (!isDuplicate)
|
||||
{
|
||||
numbers[i] = candidate;
|
||||
++i;
|
||||
}
|
||||
// bei Duplikat wird einfach eine neue Zufallszahl generiert
|
||||
}
|
||||
|
||||
// Einen zufälligen Eintrag aus den ersten len-1 duplizieren
|
||||
unsigned int duplicateIndex = (unsigned int)(rand() % (len - 1));
|
||||
numbers[len - 1] = numbers[duplicateIndex];
|
||||
|
||||
// Baum wird nicht mehr benötigt
|
||||
clearTree(root);
|
||||
|
||||
// Das Array durchmischen (Fisher-Yates-Shuffle), damit das Duplikat an zufälliger Position steht
|
||||
for (unsigned int j = len - 1; j > 0; --j)
|
||||
{
|
||||
unsigned int k = (unsigned int)(rand() % (j + 1));
|
||||
unsigned int tmp = numbers[j];
|
||||
numbers[j] = numbers[k];
|
||||
numbers[k] = tmp;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
// Kopie des Arrays anlegen, da qsort in-place sortiert
|
||||
unsigned int *copy = malloc(len * sizeof(unsigned int));
|
||||
if (copy == NULL)
|
||||
return 0;
|
||||
|
||||
memcpy(copy, numbers, len * sizeof(unsigned int));
|
||||
|
||||
// Sortieren mit qsort
|
||||
qsort(copy, len, sizeof(unsigned int), compareUnsignedInt);
|
||||
|
||||
// Benachbarte Elemente vergleichen, um das Duplikat zu finden
|
||||
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; // 0 falls kein Duplikat gefunden (Fehlerfall)
|
||||
}
|
||||
|
||||
29
stack.c
29
stack.c
@ -1,33 +1,46 @@
|
||||
#include <stdlib.h>
|
||||
#include "stack.h"
|
||||
|
||||
//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 = (StackNode *)malloc(sizeof(StackNode));
|
||||
if (node == NULL)
|
||||
return stack; // keine Änderung bei Speicherfehler
|
||||
|
||||
node->data = data;
|
||||
node->next = 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
8
stack.h
8
stack.h
@ -7,7 +7,12 @@ The latest element is taken from the stack. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
//TODO: passenden Datentyp als struct anlegen
|
||||
// einfacher verketteter Stack
|
||||
typedef struct StackNode
|
||||
{
|
||||
void *data;
|
||||
struct StackNode *next;
|
||||
} StackNode;
|
||||
|
||||
// Pushes data as pointer onto the stack.
|
||||
StackNode *push(StackNode *stack, void *data);
|
||||
@ -23,3 +28,4 @@ void *top(StackNode *stack);
|
||||
void clearStack(StackNode *stack);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
121
test_numbers.c
Normal file
121
test_numbers.c
Normal file
@ -0,0 +1,121 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "numbers.h"
|
||||
|
||||
/*
|
||||
* Unit-Tests für createNumbers und getDuplicate:
|
||||
* - createNumbers liefert ein gültiges Array
|
||||
* - alle Zahlen liegen im Bereich [1, 2*len]
|
||||
* - genau eine Zahl kommt doppelt vor
|
||||
* - getDuplicate findet genau diese doppelte Zahl
|
||||
* - Fehlerfälle (NULL-Pointer, zu kleine Länge)
|
||||
*/
|
||||
|
||||
static void check_numbers_array(unsigned int *numbers, unsigned int len)
|
||||
{
|
||||
unsigned int maxValue = 2 * len;
|
||||
unsigned int *counts;
|
||||
unsigned int i;
|
||||
unsigned int duplicatesCount = 0;
|
||||
|
||||
assert(numbers != NULL);
|
||||
|
||||
counts = (unsigned int *)calloc(maxValue + 1, sizeof(unsigned int));
|
||||
assert(counts != NULL);
|
||||
|
||||
// Werte zählen und Bereich prüfen
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
unsigned int v = numbers[i];
|
||||
assert(v >= 1 && v <= maxValue);
|
||||
counts[v]++;
|
||||
}
|
||||
|
||||
// Prüfen: genau eine Zahl kommt zweimal vor, alle anderen höchstens einmal
|
||||
for (i = 1; i <= maxValue; ++i)
|
||||
{
|
||||
if (counts[i] == 2)
|
||||
duplicatesCount++;
|
||||
else
|
||||
assert(counts[i] == 0 || counts[i] == 1);
|
||||
}
|
||||
|
||||
assert(duplicatesCount == 1);
|
||||
|
||||
free(counts);
|
||||
}
|
||||
|
||||
static void test_createNumbers_and_getDuplicate(unsigned int len)
|
||||
{
|
||||
printf("test_createNumbers_and_getDuplicate(len=%u)...\n", len);
|
||||
|
||||
unsigned int *numbers = createNumbers(len);
|
||||
assert(numbers != NULL);
|
||||
|
||||
// Arraystruktur überprüfen
|
||||
check_numbers_array(numbers, len);
|
||||
|
||||
// Nochmal zählen, um das Duplikat zu kennen
|
||||
unsigned int maxValue = 2 * len;
|
||||
unsigned int *counts = (unsigned int *)calloc(maxValue + 1, sizeof(unsigned int));
|
||||
assert(counts != NULL);
|
||||
|
||||
for (unsigned int i = 0; i < len; ++i)
|
||||
{
|
||||
unsigned int v = numbers[i];
|
||||
counts[v]++;
|
||||
}
|
||||
|
||||
unsigned int expectedDuplicate = 0;
|
||||
for (unsigned int v = 1; v <= maxValue; ++v)
|
||||
{
|
||||
if (counts[v] == 2)
|
||||
{
|
||||
expectedDuplicate = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(expectedDuplicate != 0);
|
||||
|
||||
// getDuplicate testen
|
||||
unsigned int found = getDuplicate(numbers, len);
|
||||
assert(found == expectedDuplicate);
|
||||
|
||||
free(counts);
|
||||
free(numbers);
|
||||
|
||||
printf("...OK\n");
|
||||
}
|
||||
|
||||
static void test_getDuplicate_error_cases(void)
|
||||
{
|
||||
printf("test_getDuplicate_error_cases...\n");
|
||||
|
||||
// NULL-Array
|
||||
unsigned int dup = getDuplicate(NULL, 10);
|
||||
assert(dup == 0);
|
||||
|
||||
// Länge < 2
|
||||
unsigned int dummy[1] = {42};
|
||||
dup = getDuplicate(dummy, 1);
|
||||
assert(dup == 0);
|
||||
|
||||
printf("...OK\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Running numbers unit tests...\n\n");
|
||||
|
||||
// Typische Testfälle mit verschiedenen Längen
|
||||
test_createNumbers_and_getDuplicate(5);
|
||||
test_createNumbers_and_getDuplicate(10);
|
||||
test_createNumbers_and_getDuplicate(20);
|
||||
|
||||
// Fehlerfälle
|
||||
test_getDuplicate_error_cases();
|
||||
|
||||
printf("\nAll numbers tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
BIN
test_numbers.exe
Normal file
BIN
test_numbers.exe
Normal file
Binary file not shown.
BIN
test_numbers.o
Normal file
BIN
test_numbers.o
Normal file
Binary file not shown.
102
test_stack.c
Normal file
102
test_stack.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "stack.h"
|
||||
|
||||
/*
|
||||
* Einfache Unit-Tests für den Stack:
|
||||
* - push/pop: LIFO-Verhalten
|
||||
* - top: richtiges Element
|
||||
* - Verhalten bei leerem Stack
|
||||
*/
|
||||
|
||||
static void test_push_pop_lifo(void)
|
||||
{
|
||||
printf("test_push_pop_lifo...\n");
|
||||
|
||||
StackNode *stack = NULL;
|
||||
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
int c = 3;
|
||||
|
||||
stack = push(stack, &a);
|
||||
stack = push(stack, &b);
|
||||
stack = push(stack, &c);
|
||||
|
||||
// LIFO: zuerst c
|
||||
assert(top(stack) == &c);
|
||||
stack = pop(stack);
|
||||
|
||||
// dann b
|
||||
assert(top(stack) == &b);
|
||||
stack = pop(stack);
|
||||
|
||||
// dann a
|
||||
assert(top(stack) == &a);
|
||||
stack = pop(stack);
|
||||
|
||||
// jetzt leer
|
||||
assert(stack == NULL);
|
||||
assert(top(stack) == NULL);
|
||||
|
||||
printf("...OK\n");
|
||||
}
|
||||
|
||||
static void test_empty_stack_operations(void)
|
||||
{
|
||||
printf("test_empty_stack_operations...\n");
|
||||
|
||||
StackNode *stack = NULL;
|
||||
|
||||
// pop auf leerem Stack sollte einfach NULL liefern
|
||||
stack = pop(stack);
|
||||
assert(stack == NULL);
|
||||
|
||||
// top auf leerem Stack sollte NULL liefern
|
||||
assert(top(stack) == NULL);
|
||||
|
||||
// clearStack auf leerem Stack darf nicht crashen
|
||||
clearStack(stack);
|
||||
|
||||
printf("...OK\n");
|
||||
}
|
||||
|
||||
static void test_clearStack(void)
|
||||
{
|
||||
printf("test_clearStack...\n");
|
||||
|
||||
StackNode *stack = NULL;
|
||||
int values[10];
|
||||
int i;
|
||||
|
||||
// Wir legen 10 Elemente auf den Stack
|
||||
for (i = 0; i < 10; ++i)
|
||||
{
|
||||
values[i] = i;
|
||||
stack = push(stack, &values[i]);
|
||||
}
|
||||
|
||||
// Stack leeren – clearStack muss alle StackNodes freigeben
|
||||
clearStack(stack);
|
||||
stack = NULL; // Pointer selbst auf NULL setzen
|
||||
|
||||
// Auf leerem Stack dürfen die Operationen nicht crashen
|
||||
assert(top(stack) == NULL);
|
||||
stack = pop(stack);
|
||||
assert(stack == NULL);
|
||||
|
||||
printf("...OK\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Running stack unit tests...\n\n");
|
||||
|
||||
test_push_pop_lifo();
|
||||
test_empty_stack_operations();
|
||||
test_clearStack();
|
||||
|
||||
printf("\nAll stack tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
BIN
test_stack.exe
Normal file
BIN
test_stack.exe
Normal file
Binary file not shown.
BIN
test_stack.o
Normal file
BIN
test_stack.o
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user