Template
Compare commits
33
Commits
main
..
6311aff9d7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6311aff9d7 | ||
|
|
e7a9f798cb | ||
|
|
09d7f457dd | ||
|
|
13cb5d8c86 | ||
|
|
6528686fb0 | ||
|
|
a3d0585ac1 | ||
|
|
68563ec297 | ||
|
|
3a078e9dea | ||
|
|
74fdcf500f | ||
|
|
55532cbb42 | ||
|
|
d3904ac6e4 | ||
|
|
5e96ec050c | ||
|
|
382c36b1b4 | ||
|
|
81de4b3d36 | ||
|
|
f42a997683 | ||
|
|
09426ae40a | ||
|
|
9443171664 | ||
|
|
b28deeaafb | ||
|
|
4bb0d7516e | ||
|
|
ddd4132e1f | ||
|
|
624a7d8b41 | ||
|
|
73ebc36c05 | ||
|
|
e7423f0a20 | ||
|
|
8b44089f23 | ||
|
|
654fb615a2 | ||
|
|
422ac38d54 | ||
|
|
7051134256 | ||
|
|
90612e4d04 | ||
|
|
17f4155891 | ||
|
|
735195460c | ||
|
|
a002901e2f | ||
|
|
ecb5f360e3 | ||
|
|
55b25a227b |
No files matched your search
+4
-60
@@ -1,62 +1,6 @@
|
||||
# ---> C
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
doble_initial.exe
|
||||
*.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
|
||||
runTests
|
||||
stack.o
|
||||
test_stack.o
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "windows-gcc-x64",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"compilerPath": "C:/ProgramData/mingw64/mingw64/bin/gcc.exe",
|
||||
"cStandard": "${default}",
|
||||
"cppStandard": "${default}",
|
||||
"intelliSenseMode": "windows-gcc-x64",
|
||||
"compilerArgs": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "C/C++ Runner: Debug Session",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"externalConsole": true,
|
||||
"cwd": "c:/Users/Max-R/I2Pr/info2Praktikum-DobleSpiel",
|
||||
"program": "c:/Users/Max-R/I2Pr/info2Praktikum-DobleSpiel/build/Debug/outDebug",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+59
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"C_Cpp_Runner.cCompilerPath": "gcc",
|
||||
"C_Cpp_Runner.cppCompilerPath": "g++",
|
||||
"C_Cpp_Runner.debuggerPath": "gdb",
|
||||
"C_Cpp_Runner.cStandard": "",
|
||||
"C_Cpp_Runner.cppStandard": "",
|
||||
"C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat",
|
||||
"C_Cpp_Runner.useMsvc": false,
|
||||
"C_Cpp_Runner.warnings": [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wpedantic",
|
||||
"-Wshadow",
|
||||
"-Wformat=2",
|
||||
"-Wcast-align",
|
||||
"-Wconversion",
|
||||
"-Wsign-conversion",
|
||||
"-Wnull-dereference"
|
||||
],
|
||||
"C_Cpp_Runner.msvcWarnings": [
|
||||
"/W4",
|
||||
"/permissive-",
|
||||
"/w14242",
|
||||
"/w14287",
|
||||
"/w14296",
|
||||
"/w14311",
|
||||
"/w14826",
|
||||
"/w44062",
|
||||
"/w44242",
|
||||
"/w14905",
|
||||
"/w14906",
|
||||
"/w14263",
|
||||
"/w44265",
|
||||
"/w14928"
|
||||
],
|
||||
"C_Cpp_Runner.enableWarnings": true,
|
||||
"C_Cpp_Runner.warningsAsError": false,
|
||||
"C_Cpp_Runner.compilerArgs": [],
|
||||
"C_Cpp_Runner.linkerArgs": [],
|
||||
"C_Cpp_Runner.includePaths": [],
|
||||
"C_Cpp_Runner.includeSearch": [
|
||||
"*",
|
||||
"**/*"
|
||||
],
|
||||
"C_Cpp_Runner.excludeSearch": [
|
||||
"**/build",
|
||||
"**/build/**",
|
||||
"**/.*",
|
||||
"**/.*/**",
|
||||
"**/.vscode",
|
||||
"**/.vscode/**"
|
||||
],
|
||||
"C_Cpp_Runner.useAddressSanitizer": false,
|
||||
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
||||
"C_Cpp_Runner.useLeakSanitizer": false,
|
||||
"C_Cpp_Runner.showCompilationTime": false,
|
||||
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||
"C_Cpp_Runner.msvcSecureNoWarnings": false
|
||||
}
|
||||
Binary file not shown.
@@ -1,36 +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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef BINTREE_H
|
||||
#define BINTREE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef int (*CompareFctType)(const void *arg1, const void *arg2);
|
||||
|
||||
typedef struct node
|
||||
{
|
||||
void *data;
|
||||
struct node *left;
|
||||
struct node *right;
|
||||
} TreeNode;
|
||||
|
||||
// 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);
|
||||
|
||||
#endif
|
||||
@@ -1 +0,0 @@
|
||||
player1;3999
|
||||
@@ -1,49 +0,0 @@
|
||||
CC = gcc
|
||||
FLAGS = -g -Wall -lm
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
include makefile_windows.variables
|
||||
else
|
||||
UNAME = $(shell uname)
|
||||
ifeq ($(UNAME),Linux)
|
||||
include makefile_linux.variables
|
||||
else
|
||||
include makefile_mac.variables
|
||||
endif
|
||||
endif
|
||||
|
||||
raylibfolder = ./raylib
|
||||
unityfolder = ./unity
|
||||
|
||||
# --------------------------
|
||||
# Initiales Programm bauen (zum ausprobieren)
|
||||
# --------------------------
|
||||
doble_initial:
|
||||
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
|
||||
|
||||
# --------------------------
|
||||
# Selbst implementiertes Programm bauen
|
||||
# --------------------------
|
||||
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
|
||||
|
||||
doble : main.o $(program_obj_files)
|
||||
$(CC) $(FLAGS) $^ -o doble
|
||||
|
||||
$(program_obj_files): %.o: %.c
|
||||
$(CC) -c $(FLAGS) $^ -o $@
|
||||
|
||||
# --------------------------
|
||||
# Unit Tests
|
||||
# --------------------------
|
||||
unitTests:
|
||||
echo "needs to be implemented"
|
||||
|
||||
# --------------------------
|
||||
# Clean
|
||||
# --------------------------
|
||||
clean:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
del /f *.o doble
|
||||
else
|
||||
rm -f *.o doble
|
||||
endif
|
||||
@@ -1,26 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "numbers.h"
|
||||
#include "bintree.h"
|
||||
|
||||
//TODO: getDuplicate und createNumbers implementieren
|
||||
/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen.
|
||||
* Sicherstellen, dass beim Befüllen keine Duplikate entstehen.
|
||||
* Duplizieren eines zufälligen Eintrags im Array.
|
||||
* in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
#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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Returns the data of the top element.
|
||||
void *top(StackNode *stack)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Clears stack and releases all memory.
|
||||
void clearStack(StackNode *stack)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef STACK_H
|
||||
#define STACK_H
|
||||
|
||||
/* A stack is a special type of queue which uses the LIFO (last in, first out) principle.
|
||||
This means that with each new element all other elements are pushed deeper into the stack.
|
||||
The latest element is taken from the stack. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
//TODO: passenden Datentyp als struct anlegen
|
||||
|
||||
// Pushes data as pointer onto the stack.
|
||||
StackNode *push(StackNode *stack, void *data);
|
||||
|
||||
// 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);
|
||||
|
||||
// Returns the data of the top element.
|
||||
void *top(StackNode *stack);
|
||||
|
||||
// Clears stack and releases all memory.
|
||||
void clearStack(StackNode *stack);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,119 @@
|
||||
#include "bintree.h"
|
||||
#include "stack.h"
|
||||
#include <string.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. */
|
||||
|
||||
// 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 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;
|
||||
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,
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef BINTREE_H
|
||||
#define BINTREE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef int (*CompareFctType)(const void *arg1, const void *arg2);
|
||||
|
||||
typedef struct node {
|
||||
void *data;
|
||||
struct node *left;
|
||||
struct node *right;
|
||||
} 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).
|
||||
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);
|
||||
|
||||
#endif
|
||||
Binary file not shown.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,10 @@
|
||||
Kristin;9944
|
||||
Kristin;7947
|
||||
Kristin;6962
|
||||
Kristin;5987
|
||||
Kristin;5975
|
||||
krisp;4986
|
||||
krisp;4985
|
||||
Kristin;4972
|
||||
player1;3999
|
||||
Kristin;3992
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,73 @@
|
||||
CC = gcc
|
||||
FLAGS = -g -Wall -lm
|
||||
ASAN_FLAGS = -fsanitize=address
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
include makefile_windows.variables
|
||||
else
|
||||
UNAME = $(shell uname)
|
||||
ifeq ($(UNAME),Linux)
|
||||
include makefile_linux.variables
|
||||
else
|
||||
include makefile_mac.variables
|
||||
endif
|
||||
endif
|
||||
|
||||
raylibfolder = ./raylib
|
||||
unityfolder = ./unity
|
||||
|
||||
# --------------------------
|
||||
# Initiales Programm bauen (zum ausprobieren)
|
||||
# --------------------------
|
||||
doble_initial:
|
||||
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
|
||||
|
||||
# --------------------------
|
||||
# Selbst implementiertes Programm bauen
|
||||
# --------------------------
|
||||
# alle Objektdateien
|
||||
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)
|
||||
$(CC) $(FLAGS) $^ -o doble
|
||||
# Regel Kompilieren allgemein
|
||||
$(program_obj_files): %.o: %.c
|
||||
$(CC) -c $(FLAGS) $^ -o $@
|
||||
|
||||
# --------------------------
|
||||
# Unit Tests
|
||||
# --------------------------
|
||||
|
||||
STACK_TEST_BIN = runStackTests
|
||||
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
|
||||
$(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:
|
||||
rm -f *.o doble $(STACK_TEST_BIN) $(NUMBERS_TEST_BIN) $(BINARY_TEST_BIN)
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,91 @@
|
||||
#include "numbers.h"
|
||||
#include "bintree.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
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;
|
||||
}
|
||||
File renamed without changes.
Binary file not shown.
@@ -0,0 +1,95 @@
|
||||
#include "stack.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*typedef struct {
|
||||
|
||||
void *data;
|
||||
struct StackNode *next;
|
||||
struct StackNode *prev;
|
||||
|
||||
} StackNode;*/
|
||||
|
||||
// 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. */
|
||||
|
||||
// [A] -> [B] -> [C] -> NULL
|
||||
// stack -> stack.next
|
||||
|
||||
// Funktion zum erstellen neuer nodes
|
||||
StackNode *createNode(void *data) {
|
||||
// Speicher reservieren
|
||||
StackNode *node = malloc(sizeof(StackNode));
|
||||
// Speicher konnte nicht reserviert werden
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
node->data = data;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// Pushes data as pointer onto the stack.
|
||||
StackNode *push(StackNode *stack, void *data) {
|
||||
|
||||
StackNode *newNode = createNode(data);
|
||||
|
||||
// Fehler beim Reservieren des Speichers, stack wird unverändert zurückgegeben
|
||||
if (newNode == NULL) {
|
||||
return stack;
|
||||
}
|
||||
|
||||
// der aktuelle Kopf wird der nächste Node
|
||||
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
|
||||
// memory. (Pointer to data has to be freed by caller.)
|
||||
StackNode *pop(StackNode *stack) {
|
||||
|
||||
// Stack ohne Elemente
|
||||
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);
|
||||
|
||||
stack = NULL; // Speicher des Kopfes freigeben
|
||||
|
||||
return nextNode; // neuen Kopf zurückgeben
|
||||
}
|
||||
|
||||
// Returns the data of the top element.
|
||||
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.
|
||||
void clearStack(StackNode **stack) { // Zeiger auf den Zeiger auf den Stackkopf
|
||||
// verändert den Zeiger selbst, mit *stack lokale Kopie
|
||||
// im Aufruf &stack verwenden
|
||||
while (*stack != NULL) {
|
||||
StackNode *next = (*stack)->next; // nächstes Element speichern
|
||||
free(*stack); // aktuelles Element freigeben
|
||||
*stack = next; // Zeiger auf nächsten Knoten setzen
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef STACK_H
|
||||
#define STACK_H
|
||||
|
||||
/* A stack is a special type of queue which uses the LIFO (last in, first out)
|
||||
principle. This means that with each new element all other elements are pushed
|
||||
deeper into the stack. 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;
|
||||
struct StackNode *prev;
|
||||
|
||||
} StackNode;
|
||||
|
||||
StackNode *createNode(void *data);
|
||||
|
||||
// Pushes data as pointer onto the stack.
|
||||
StackNode *push(StackNode *stack, void *data);
|
||||
|
||||
// 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);
|
||||
|
||||
// Returns the data of the top element.
|
||||
void *top(StackNode *stack);
|
||||
|
||||
// Clears stack and releases all memory.
|
||||
void clearStack(StackNode **stack);
|
||||
|
||||
#endif
|
||||
+105
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
#include "unity.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stack.h"
|
||||
|
||||
// StackNode *createNode(void *data) testen
|
||||
void test_createNode(void) {
|
||||
|
||||
int testInt = 26;
|
||||
StackNode *testNode = createNode(&testInt); // Adresse des testInts
|
||||
|
||||
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);
|
||||
|
||||
free(testNode); // Speicher freigeben
|
||||
}
|
||||
|
||||
// StackNode *push(StackNode *stack, void *data) testen
|
||||
void test_pushDataToStack(void) {
|
||||
|
||||
int testInts[] = {27, 28};
|
||||
|
||||
StackNode *testStack = NULL; // leeren testStack initialisieren
|
||||
|
||||
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) {
|
||||
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 tearDown(void) {}
|
||||
|
||||
int main(void) {
|
||||
|
||||
UNITY_BEGIN();
|
||||
|
||||
printf("\n------------------------stack test------------------------\n\n");
|
||||
|
||||
RUN_TEST(test_createNode);
|
||||
RUN_TEST(test_pushDataToStack);
|
||||
RUN_TEST(test_deleteTopElement);
|
||||
RUN_TEST(test_returnData);
|
||||
RUN_TEST(test_clearStack);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
Binary file not shown.
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.
Reference in new issue
Block a user