Compare commits

..

45 Commits
main ... RMax

Author SHA1 Message Date
Max-R
4fcaa410fa merge 2025-12-12 10:08:12 +01:00
Max-R
c13d39f60c Merge remote-tracking branch 'origin/Krisp' into RMax 2025-12-12 10:07:09 +01:00
Max-R
f90dc12bd0 neuer rekord 2025-12-12 10:05:14 +01:00
Kristin
9fb140fecf cleartree angepasst, Kommentare vollständig 2025-12-11 16:16:52 +01:00
Kristin
99a974cc9b getduplicate neu 2025-12-10 21:09:03 +01:00
Kristin
799667ed1c numbers.c bintree.c änderungen 2025-12-10 21:05:36 +01:00
Max-R
c3b1cdd3a3 numbers 2025-12-09 10:37:20 +01:00
Max-R
9d32e06f3a highscores kristin geknackt 2025-12-09 10:27:42 +01:00
Kristin
d9222b83b4 highscore zum gitignore hinzugefügt 2025-12-09 10:27:18 +01:00
Max-R
9268113f38 mein clean 2025-12-09 10:21:16 +01:00
Max-R
8f2dfb507c Merge remote-tracking branch 'origin/Krisp' into RMax 2025-12-09 10:19:21 +01:00
Kristin
9bf5e6a541 stacktest clearstack pointer null setzen 2025-12-09 10:10:13 +01:00
Kristin
57f9914e2b stacktest überarbeitet 2025-12-09 09:57:41 +01:00
Kristin
09d7f457dd stacktest überarbeitet 2025-12-09 09:49:46 +01:00
Kristin
13cb5d8c86 push test im teststack verbessert 2025-12-09 09:13:18 +01:00
Kristin
6528686fb0 Fehler bei nichtreservierung von Speicher, stack.c kommentiert 2025-12-07 20:11:40 +01:00
Kristin
a3d0585ac1 stack.c eingebunden 2025-12-07 19:05:11 +01:00
Kristin
68563ec297 erste version 2025-12-07 18:35:22 +01:00
Max-R
8cccbcf441 makefile änderung 2025-12-05 12:08:25 +01:00
Max-R
96a97c07c9 Merge remote-tracking branch 'origin/tobi_experimental' into RMax 2025-12-05 12:05:01 +01:00
74fdcf500f stack.c test laufen alle 2025-12-05 11:54:23 +01:00
Kristin
55532cbb42 makefile mit rm 2025-12-05 11:52:08 +01:00
Kristin
d3904ac6e4 alle tests 2025-12-05 11:50:51 +01:00
Max-R
0575eac07e immer noch ohne clearstak 2025-12-05 11:47:36 +01:00
Kristin
5e96ec050c test_stack mit & 2025-12-05 11:24:35 +01:00
382c36b1b4 Merge remote-tracking branch 'origin/RMax' into tobi_experimental 2025-12-05 11:16:21 +01:00
81de4b3d36 arbeiten an stack.c 2025-12-05 11:13:27 +01:00
Kristin
f42a997683 clearstack mit ** 2025-12-05 11:12:30 +01:00
Max-R
09426ae40a tests bis auf clearstack laufen 2025-12-05 11:10:20 +01:00
Max-R
9443171664 create node 2025-12-05 11:04:09 +01:00
Max-R
b28deeaafb mhm 2025-12-05 10:53:03 +01:00
Max-R
4bb0d7516e stak.c 2025-12-05 10:48:10 +01:00
Max-R
ddd4132e1f erste tests stack.c 2025-12-05 10:41:30 +01:00
624a7d8b41 slight changes to stackNode struct, void func, etc 2025-12-05 10:41:08 +01:00
73ebc36c05 Merge branch 'KrispTobi' into tobi_experimental 2025-12-05 10:31:47 +01:00
Max-R
e7423f0a20 stack.c 2025-12-05 10:26:10 +01:00
Kristin
8b44089f23 Remove object files 2025-12-05 10:25:10 +01:00
Kristin
654fb615a2 Remove object files 2025-12-05 10:24:32 +01:00
Kristin
422ac38d54 gitignore 2025-12-05 10:21:33 +01:00
Max-R
7051134256 stack.h 2025-12-05 10:21:00 +01:00
Kristin
90612e4d04 stack.c 2025-12-05 10:20:17 +01:00
Kristin
17f4155891 stack.c 2025-12-05 10:08:55 +01:00
Max-R
735195460c mein Branch 2025-12-02 10:44:15 +01:00
Kristin
a002901e2f highscore.txt zu gitignore 2025-12-02 10:40:28 +01:00
Kristin
55b25a227b makefile 2025-12-02 10:32:52 +01:00
19 changed files with 967 additions and 237 deletions

5
.gitignore vendored
View File

@ -1 +1,4 @@
highscores.txt doble_initial.exe
*.o
*.exe
highscore.txt

18
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -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
}

24
.vscode/launch.json vendored Normal file
View File

@ -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
}
]
}
]
}

59
.vscode/settings.json vendored Normal file
View File

@ -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
}

126
bintree.c
View File

@ -1,6 +1,6 @@
#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),
@ -8,29 +8,125 @@
* `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).
TreeNode *createTreeNode(const void *data, size_t dataSize) {
TreeNode *node =
malloc(sizeof(TreeNode)); // Speicher für neuen Knoten reservieren
if (node == NULL)
return NULL; // Abbrechen bei Fehler
node->data = malloc(dataSize); // Speicher für Daten reservieren
if (node->data == NULL) {
free(node);
return NULL;
} }
// 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. memcpy(node->data, data, dataSize); // Standardfunktion string.h, kopiert
// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, // size bytes von data nach node->data,
// push the top node and push all its left nodes. // daten dürfen sich nicht überschneiden
void *nextTreeData(TreeNode *root) // speichern der Daten in node->data
{ node->left = NULL; // Kinder sind NULL
node->right = NULL;
return node;
}
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
CompareFctType compareFct, int *isDuplicate) {
// isDuplicate initialisieren (auf 0 setzen), verhindert Änderung am Baum
if (isDuplicate) {
*isDuplicate = 0;
} // bei 0: neuer Wert wurde eingefügt, bei 1: Wert war bereits im Baum
// leerer Baum
if (root == NULL) {
return createTreeNode(data, dataSize);
}
// mit compareFct <0 links >0 rechts =0 Duplikat
int compare = compareFct(data, root->data);
if (compare < 0) { // Eintrag links
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
} else if (compare > 0) { // Eintrag rechts
root->right =
addToTree(root->right, data, dataSize, compareFct, isDuplicate);
} else { // Duplikat
// isDuplicate auf 1 setzen, keine Änderung am Baum
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; // static -> behält Wert bei mehreren Aufrufen
// Neue Iteration starten
if (root != NULL) {
clearStack(&stack); // alte Stack-Inhalte werden gelöscht
TreeNode *currentNode = root;
while (currentNode !=
NULL) { // alle linken Knoten werden vom root an auf den Stack gelegt
StackNode *oldStack = stack;
StackNode *newStack = push(stack, currentNode);
if (newStack == oldStack)
return NULL; // push fehlgeschlagen
stack = newStack;
currentNode = currentNode->left;
}
}
if (stack == NULL)
return NULL; // wenn Stack leer ist sind keine Elemente mehr vorhanden,
// Iteration beendet
// oberster Knoten vom Stack
TreeNode *node = top(stack);
stack = pop(stack);
// Rechten Teilbaum pushen
TreeNode *currentNode = node->right;
while (currentNode != NULL) {
StackNode *oldStack = stack;
StackNode *newStack = push(stack, currentNode);
if (newStack == oldStack)
return NULL; // push fehlgeschlagen
stack = newStack;
currentNode = currentNode->left;
}
return node->data; // Pointer auf Daten
} }
// Releases all memory resources (including data copies). // Releases all memory resources (including data copies).
void clearTree(TreeNode *root) void clearTree(TreeNode **root) { // rekursive Funktion zum freigeben des
{ // Speichers und Nullsetzen der Pointer
if (root == NULL || *root == NULL)
return;
clearTree(&(*root)->left); // linken Teilbaum löschen
clearTree(&(*root)->right); // rechten Teilbaum löschen
free((*root)->data); // Daten freigeben
(*root)->data = NULL;
free(*root); // Knoten freigeben
*root = NULL; // Zeiger auf NULL setzen
} }
// 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,22 +5,27 @@
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 TreeNode *createTreeNode(const void *data, size_t dataSize);
// 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);
// 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);

BIN
doble_initial.exe Normal file

Binary file not shown.

View File

@ -1,23 +1,22 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "highscore.h" #include "highscore.h"
#include "bintree.h" #include "bintree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LEN 100 #define MAX_LINE_LEN 100
#define MAX_PLAYER_NAME_LEN 20 #define MAX_PLAYER_NAME_LEN 20
typedef struct typedef struct {
{
char name[MAX_PLAYER_NAME_LEN]; char name[MAX_PLAYER_NAME_LEN];
int score; int score;
} HighscoreEntry; } HighscoreEntry;
static TreeNode *highscoreTree = NULL; static TreeNode *highscoreTree = NULL;
// Compare two highscore entries by score (descending), then by name (ascending). // Compare two highscore entries by score (descending), then by name
static int compareHighscoreEntries(const void *arg1, const void *arg2) // (ascending).
{ static int compareHighscoreEntries(const void *arg1, const void *arg2) {
const HighscoreEntry *entry1 = (const HighscoreEntry *)arg1; const HighscoreEntry *entry1 = (const HighscoreEntry *)arg1;
const HighscoreEntry *entry2 = (const HighscoreEntry *)arg2; const HighscoreEntry *entry2 = (const HighscoreEntry *)arg2;
@ -30,12 +29,10 @@ static int compareHighscoreEntries(const void *arg1, const void *arg2)
} }
// Create a new highscore entry from name and score. // Create a new highscore entry from name and score.
static HighscoreEntry createHighscoreEntry(const char *name, int score) static HighscoreEntry createHighscoreEntry(const char *name, int score) {
{
HighscoreEntry entry = {"", score}; HighscoreEntry entry = {"", score};
if(name != NULL) if (name != NULL) {
{
strncpy(entry.name, name, MAX_PLAYER_NAME_LEN); strncpy(entry.name, name, MAX_PLAYER_NAME_LEN);
entry.name[MAX_PLAYER_NAME_LEN - 1] = '\0'; entry.name[MAX_PLAYER_NAME_LEN - 1] = '\0';
} }
@ -44,29 +41,26 @@ static HighscoreEntry createHighscoreEntry(const char *name, int score)
} }
// Calculate score based on time used and number of shown numbers. // Calculate score based on time used and number of shown numbers.
static int calculateScore(double timeInSeconds, unsigned int len) static int calculateScore(double timeInSeconds, unsigned int len) {
{
return (1000.0 - timeInSeconds) * len; return (1000.0 - timeInSeconds) * len;
} }
// Load highscores from file into memory. // Load highscores from file into memory.
void loadHighscores(const char *path) void loadHighscores(const char *path) {
{
FILE *file = fopen(path, "r"); FILE *file = fopen(path, "r");
if(file != NULL) if (file != NULL) {
{
char buffer[MAX_LINE_LEN + 1]; char buffer[MAX_LINE_LEN + 1];
while(fgets(buffer, MAX_LINE_LEN+1, file) != NULL) while (fgets(buffer, MAX_LINE_LEN + 1, file) != NULL) {
{
char *name = strtok(buffer, ";\n"); char *name = strtok(buffer, ";\n");
char *scoreStr = strtok(NULL, ";\n"); char *scoreStr = strtok(NULL, ";\n");
if(name != NULL && scoreStr != NULL) if (name != NULL && scoreStr != NULL) {
{ HighscoreEntry entry =
HighscoreEntry entry = createHighscoreEntry(name, strtol(scoreStr, NULL, 10)); createHighscoreEntry(name, strtol(scoreStr, NULL, 10));
highscoreTree = addToTree(highscoreTree, &entry, sizeof(entry), compareHighscoreEntries, NULL); highscoreTree = addToTree(highscoreTree, &entry, sizeof(entry),
compareHighscoreEntries, NULL);
} }
} }
@ -75,19 +69,23 @@ void loadHighscores(const char *path)
} }
// Add a new highscore entry and return the calculated score. // Add a new highscore entry and return the calculated score.
int addHighscore(const char *name, double timeInSeconds, unsigned int len) int addHighscore(const char *name, double timeInSeconds, unsigned int len) {
{ HighscoreEntry entry =
HighscoreEntry entry = createHighscoreEntry(name, calculateScore(timeInSeconds, len)); createHighscoreEntry(name, calculateScore(timeInSeconds, len));
highscoreTree = addToTree(highscoreTree, &entry, sizeof(entry), compareHighscoreEntries, NULL); highscoreTree = addToTree(highscoreTree, &entry, sizeof(entry),
compareHighscoreEntries, NULL);
return entry.score; return entry.score;
} }
// Print highscores (up to NUMBER_OF_SHOWN_HIGHSCORES) in a formatted table. // Print highscores (up to NUMBER_OF_SHOWN_HIGHSCORES) in a formatted table.
void showHighscores() void showHighscores() {
{ const char *blanks =
const char *blanks = " "; " "
const char *stripes = "------------------------------------------------------------------------------------------------------------------------"; " ";
const char *stripes =
"------------------------------------------------------------------------"
"------------------------------------------------";
const char *header = "H I G H S C O R E S"; const char *header = "H I G H S C O R E S";
const int lineWidth = MAX_PLAYER_NAME_LEN + MAX_PLAYER_NAME_LEN + 5; const int lineWidth = MAX_PLAYER_NAME_LEN + MAX_PLAYER_NAME_LEN + 5;
@ -96,28 +94,26 @@ void showHighscores()
HighscoreEntry *entry = nextTreeData(highscoreTree); HighscoreEntry *entry = nextTreeData(highscoreTree);
printf("+%*.*s+\n", lineWidth, lineWidth, stripes); printf("+%*.*s+\n", lineWidth, lineWidth, stripes);
printf("|%*.*s%s%*.*s|\n", blankSpace, blankSpace, blanks, header, blankSpace, blankSpace, blanks); printf("|%*.*s%s%*.*s|\n", blankSpace, blankSpace, blanks, header, blankSpace,
blankSpace, blanks);
printf("+%*.*s+\n", lineWidth, lineWidth, stripes); printf("+%*.*s+\n", lineWidth, lineWidth, stripes);
for(int i = 0; i < NUMBER_OF_SHOWN_HIGHSCORES && entry != NULL; i++) for (int i = 0; i < NUMBER_OF_SHOWN_HIGHSCORES && entry != NULL; i++) {
{ printf("| %-*s | %*d |\n", MAX_PLAYER_NAME_LEN, entry->name,
printf("| %-*s | %*d |\n", MAX_PLAYER_NAME_LEN, entry->name, MAX_PLAYER_NAME_LEN, entry->score); MAX_PLAYER_NAME_LEN, entry->score);
printf("+%*.*s+\n", lineWidth, lineWidth, stripes); printf("+%*.*s+\n", lineWidth, lineWidth, stripes);
entry = nextTreeData(NULL); entry = nextTreeData(NULL);
} }
} }
// Save highscores to file (up to NUMBER_OF_SHOWN_HIGHSCORES). // Save highscores to file (up to NUMBER_OF_SHOWN_HIGHSCORES).
void saveHighscores(const char *path) void saveHighscores(const char *path) {
{
FILE *file = fopen(path, "w"); FILE *file = fopen(path, "w");
if(file != NULL) if (file != NULL) {
{
HighscoreEntry *entry = nextTreeData(highscoreTree); HighscoreEntry *entry = nextTreeData(highscoreTree);
for(int i = 0; i < NUMBER_OF_SHOWN_HIGHSCORES && entry != NULL; i++) for (int i = 0; i < NUMBER_OF_SHOWN_HIGHSCORES && entry != NULL; i++) {
{
fprintf(file, "%s;%d\n", entry->name, entry->score); fprintf(file, "%s;%d\n", entry->name, entry->score);
entry = nextTreeData(NULL); entry = nextTreeData(NULL);
} }
@ -127,8 +123,7 @@ void saveHighscores(const char *path)
} }
// Free all memory used for highscores. // Free all memory used for highscores.
void clearHighscores() void clearHighscores() {
{ clearTree(&highscoreTree);
clearTree(highscoreTree);
highscoreTree = NULL; highscoreTree = NULL;
} }

View File

@ -1 +1,10 @@
player1;3999 max20;19879
max10;9970
max;9965
Kristin;9944
Kristin;7947
Kristin;6962
Kristin;5987
Kristin;5975
krisp;4986
krisp;4985

52
main.c
View File

@ -1,30 +1,28 @@
#include <stdlib.h> #include "highscore.h"
#include <stdio.h>
#include "numbers.h" #include "numbers.h"
#include "timer.h" #include "timer.h"
#include "highscore.h" #include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Read an unsigned integer from stdin with prompt (retries until valid). // Read an unsigned integer from stdin with prompt (retries until valid).
int inputNumber(const char *promptText) int inputNumber(const char *promptText) {
{
unsigned int number; unsigned int number;
int numberOfInputs = 0; int numberOfInputs = 0;
while(numberOfInputs != 1) while (numberOfInputs != 1) {
{
printf("%s", promptText); printf("%s", promptText);
numberOfInputs = scanf("%u", &number); numberOfInputs = scanf("%u", &number);
while(getchar() != '\n') {} // clear input buffer while (getchar() != '\n') {
} // clear input buffer
} }
return number; return number;
} }
// Print an array of numbers. // Print an array of numbers.
void showNumbers(const unsigned int *numbers, unsigned int len) void showNumbers(const unsigned int *numbers, unsigned int len) {
{ if (numbers != NULL) {
if(numbers != NULL)
{
printf("Numbers:"); printf("Numbers:");
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
@ -34,18 +32,16 @@ void showNumbers(const unsigned int *numbers, unsigned int len)
} }
} }
// Main game loop: generate numbers, ask user for duplicate, measure time, update highscores. // Main game loop: generate numbers, ask user for duplicate, measure time,
int main(int argc, char *argv[]) // update highscores.
{ int main(int argc, char *argv[]) {
srand(time(NULL)); // seed für srand
int exitCode = EXIT_FAILURE; int exitCode = EXIT_FAILURE;
if(argc != 2) if (argc != 2) {
{
fprintf(stderr, "Usage: %s <player name>\n", argv[0]); fprintf(stderr, "Usage: %s <player name>\n", argv[0]);
exitCode = EXIT_FAILURE; exitCode = EXIT_FAILURE;
} } else {
else
{
const char *highscorePath = "highscores.txt"; const char *highscorePath = "highscores.txt";
const char *playerName = argv[1]; const char *playerName = argv[1];
unsigned int *numbers = NULL; unsigned int *numbers = NULL;
@ -56,7 +52,8 @@ int main(int argc, char *argv[])
// ask until valid number of elements (3..1000) // ask until valid number of elements (3..1000)
while (numberOfElements < 3 || numberOfElements > 1000) while (numberOfElements < 3 || numberOfElements > 1000)
numberOfElements = inputNumber("Wie viele Zahlen sollen gezeigt werden: "); numberOfElements =
inputNumber("Wie viele Zahlen sollen gezeigt werden: ");
// create numbers and show them // create numbers and show them
numbers = createNumbers(numberOfElements); numbers = createNumbers(numberOfElements);
@ -70,13 +67,14 @@ int main(int argc, char *argv[])
duplicate = getDuplicate(numbers, numberOfElements); duplicate = getDuplicate(numbers, numberOfElements);
// check result and update highscores // check result and update highscores
if(userInput == duplicate) if (userInput == duplicate) {
{
int score = addHighscore(playerName, measuredSeconds, numberOfElements); int score = addHighscore(playerName, measuredSeconds, numberOfElements);
printf("Sie haben die korrekte Zahl in %.6lf Sekunde(n) gefunden und %u Punkte erzielt.\n", measuredSeconds, score); printf("Sie haben die korrekte Zahl in %.6lf Sekunde(n) gefunden und %u "
} "Punkte erzielt.\n",
else measuredSeconds, score);
printf("Leider ist %u nicht korrekt. Richtig waere %u gewesen.\n", userInput, duplicate); } else
printf("Leider ist %u nicht korrekt. Richtig waere %u gewesen.\n",
userInput, duplicate);
loadHighscores(highscorePath); loadHighscores(highscorePath);
showHighscores(); showHighscores();

View File

@ -1,5 +1,6 @@
CC = gcc CC = gcc
FLAGS = -g -Wall -lm FLAGS = -g -Wall -lm
ASAN_FLAGS = -fsanitize=address
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
include makefile_windows.variables include makefile_windows.variables
@ -24,19 +25,46 @@ 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_filesobj_files): %.o: %.c $(program_obj_files): %.o: %.c
$(CC) -c $(FLAGS) $^ -o $@ $(CC) -c $(FLAGS) $^ -o $@
# -------------------------- # --------------------------
# Unit Tests # Unit Tests
# -------------------------- # --------------------------
unitTests:
echo "needs to be implemented" 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
@ -47,3 +75,4 @@ ifeq ($(OS),Windows_NT)
else else
rm -f *.o doble rm -f *.o doble
endif endif

100
numbers.c
View File

@ -1,26 +1,96 @@
#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>
// TODO: getDuplicate und createNumbers implementieren // TODO: getDuplicate und createNumbers implementieren
/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. /**Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an
* Sicherstellen, dass beim Befüllen keine Duplikate entstehen. * 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.
{
// vergleicht zwei Werte: a<b: -1 a>b: 1 a=b: 0
int compareUnsignedInt(const void *a, const void *b) {
unsigned int x = *(unsigned int *)a;
unsigned int y = *(unsigned int *)b;
return (x < y) ? -1 : (x > y);
} }
// Returns only the only number in numbers which is present twice. Returns zero on errors. unsigned int *createNumbers(unsigned int len) {
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) if (len < 2) // Duplikat bei zwei Einträgen sinnlos
{ return NULL;
unsigned int *numbersArray = malloc(
sizeof(unsigned int) * len); // Speicher für das Ausgabearray reservieren:
// Größe eines Eintrags * Größe des Arrays
if (!numbersArray) // Speicher konnte nicht reserviert werden
return NULL;
TreeNode *root =
NULL; // Binärbaum zum Generieren der Zufallszahlen ohne Duplikate
for (unsigned int i = 0; i < len; i++) {
unsigned int currentNumber;
int isDuplicate;
do { // mindestens eine Zufallszahl erzeugen
currentNumber = (rand() % (2 * len)) + 1; // Zahlenbereich 1 bis 2*len
isDuplicate = 0;
root = addToTree(root, &currentNumber, sizeof(unsigned int),
compareUnsignedInt,
&isDuplicate); // compareUnsignedInt wird zum Verwenden
// bei Vergleichen übergeben
} while (isDuplicate); // wenn isDuplicate gesetzt wird, muss eine neue Zahl
// erzeugt werden, die Schleife wird wiederholt
numbersArray[i] = currentNumber;
}
// Ein zufälliges Duplikat erzeugen
unsigned int duplicateIndex =
rand() % len; // Index des Duplikats per Zufall bestimmen
unsigned int newIndex;
do {
newIndex = rand() % len;
} while (newIndex == duplicateIndex); // zweiten Index bestimmen, der nicht
// mit dem ersten übereinstimmt
numbersArray[newIndex] =
numbersArray[duplicateIndex]; // Wert vom ersten Index kopieren
clearTree(&root); // Speicher wieder freigeben, wird nicht mehr benötigt
return numbersArray;
}
// 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) { // array numbers, sowie die Länge wird übergeben
if (!numbers || len < 2)
return 0; // fehlerhaftes Array
TreeNode *root = NULL; // leerer Baum
unsigned int duplicateValue = 0; // Wert des Duplikats
for (unsigned int i = 0; i < len && duplicateValue == 0; i++) { // Schleife
int isDuplicate = 0;
// Zahl in den Baum einfügen
root = addToTree(root, &numbers[i], sizeof(unsigned int),
compareUnsignedInt, &isDuplicate);
// Duplikat erkannt
if (isDuplicate && duplicateValue == 0) {
duplicateValue = numbers[i]; // Duplikat merken, for-Schleife wird beendet
}
}
clearTree(&root); // Baum freigeben
return duplicateValue; // 0, falls kein Duplikat
} }

View File

@ -1,12 +1,16 @@
#ifndef NUMBERS_H #ifndef NUMBERS_H
#define NUMBERS_H #define NUMBERS_H
// Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries. int compareUnsignedInt(const void *a, const void *b);
// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while
// creating random numbers. // 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); unsigned int *createNumbers(unsigned int len);
// 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
// on errors.
unsigned int getDuplicate(const unsigned int *numbers, unsigned int len); unsigned int getDuplicate(const unsigned int *numbers, unsigned int len);
#endif #endif

BIN
runTests.exe Normal file

Binary file not shown.

93
stack.c
View File

@ -1,5 +1,14 @@
#include <stdlib.h>
#include "stack.h" #include "stack.h"
#include <stdio.h>
#include <stdlib.h>
/*typedef struct {
void *data;
struct StackNode *next;
struct StackNode *prev;
} StackNode;*/
// TODO: grundlegende Stackfunktionen implementieren: // TODO: grundlegende Stackfunktionen implementieren:
/* * `push`: legt ein Element oben auf den Stack, /* * `push`: legt ein Element oben auf den Stack,
@ -7,27 +16,85 @@
* `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. */
// Pushes data as pointer onto the stack. // [A] -> [B] -> [C] -> NULL
StackNode *push(StackNode *stack, void *data) // 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;
} }
// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be // Pushes data as pointer onto the stack.
// freed by caller.) StackNode *push(StackNode *stack, void *data) {
StackNode *pop(StackNode *stack)
{
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. // Returns the data of the top element.
void *top(StackNode *stack) 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
// im Aufruf &stack verwenden
while (*stack != NULL) {
(*stack)->prev = NULL; // späteren Pointerzugriff verhindern
StackNode *next = (*stack)->next; // nächstes Element speichern
(*stack)->next = NULL; // späteren Pointerzugriff verhindern
free(*stack); // aktuelles Element freigeben
*stack = next; // Zeiger auf nächsten Knoten setzen
}
} }

22
stack.h
View File

@ -1,25 +1,35 @@
#ifndef STACK_H #ifndef STACK_H
#define STACK_H #define STACK_H
/* A stack is a special type of queue which uses the LIFO (last in, first out) principle. /* A stack is a special type of queue which uses the LIFO (last in, first out)
This means that with each new element all other elements are pushed deeper into the stack. principle. This means that with each new element all other elements are pushed
The latest element is taken from the stack. */ deeper into the stack. The latest element is taken from the stack. */
#include <stdlib.h> #include <stdlib.h>
// TODO: passenden Datentyp als struct anlegen // 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. // Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data); 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 // 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);
// Returns the data of the top element. // Returns the data of the top element.
void *top(StackNode *stack); void *top(StackNode *stack);
// Clears stack and releases all memory. // Clears stack and releases all memory.
void clearStack(StackNode *stack); void clearStack(StackNode **stack);
#endif #endif

126
test_binary.c Normal file
View File

@ -0,0 +1,126 @@
#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
/*TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
CompareFctType compareFct, int *isDuplicate) */
void test_addToTree_basic(void) {
int isDuplicate;
unsigned int testInt = 10;
root = addToTree(root, &testInt, sizeof(testInt), compareUnsignedInt,
&isDuplicate);
TEST_ASSERT_NOT_NULL(root); // Knoten wurde erfolgreich erzeugt
TEST_ASSERT_EQUAL_UINT(
10,
*(unsigned int *)root
->data); // Datenzeiger wurde richtig gesetzt, void pointer auf
// unsigned int pointer casten, mit *wird der Wert abgerufen
TEST_ASSERT_EQUAL_INT(0, isDuplicate); // kein Duplikat
TEST_ASSERT_EQUAL_UINT(1, treeSize(root)); // der tree hat einen Eintrag
}
// Test, dass Duplikate erkannt werden
void test_addToTree_duplicate(void) {
int isDuplicate;
unsigned int val1 = 10, val2 = 10; // Duplikate
root = addToTree(root, &val1, sizeof(val1), compareUnsignedInt,
&isDuplicate); // val 1 zum leeren Baum hinzufügen
TEST_ASSERT_EQUAL_INT(0, isDuplicate); // erster Knoten->kein Duplikat
root = addToTree(root, &val2, sizeof(val2), compareUnsignedInt,
&isDuplicate); // val 2 hinzufügen
TEST_ASSERT_EQUAL_INT(1, isDuplicate); // Duplikat erkannt
TEST_ASSERT_EQUAL_UINT(1,
treeSize(root)); // Duplikate wurde nicht hinzugefügt
}
// Test nextTreeData Traversierung
void test_nextTreeData_in_order(void) {
unsigned int values[] = {20, 10, 30}; // erwartete Ausgabe: 10 -> 20 -> 30
int isDuplicate;
for (int i = 0; i < 3; i++) {
root = addToTree(root, &values[i], sizeof(values[i]), compareUnsignedInt,
&isDuplicate); // Baum füllen
}
unsigned int expected[] = {10, 20, 30}; // erwartet in Order Reihenfolge
int valueID = 0;
void *data;
// Neue Iteration starten
data = nextTreeData(root);
while (data != NULL) {
TEST_ASSERT_EQUAL_UINT(expected[valueID],
*(unsigned int *)data); // entspricht erwartetem Wert
valueID++;
data = nextTreeData(NULL); // weitere Elemente abrufen
}
TEST_ASSERT_EQUAL_INT(3, valueID); // alle 3 Knoten besucht
}
// Testet, dass clearTree Speicher freigibt und Root auf NULL setzt
void test_clearTree_sets_root_null(void) {
int isDuplicate;
unsigned int val1 = 10, val2 = 20;
root = addToTree(root, &val1, sizeof(val1), compareUnsignedInt, &isDuplicate);
root = addToTree(root, &val2, sizeof(val2), compareUnsignedInt, &isDuplicate);
// Vor dem Clear prüfen, dass Root nicht NULL ist
TEST_ASSERT_NOT_NULL(root);
clearTree(&root);
// Nach dem Clear muss Root auf NULL gesetzt sein
TEST_ASSERT_NULL(root);
}
// Test treeSize zählt korrekt
void test_treeSize(void) {
unsigned int testInts[] = {10, 20, 5};
int isDuplicate;
for (int i = 0; i < 3; i++) {
root = addToTree(root, &testInts[i], sizeof(testInts[i]),
compareUnsignedInt, &isDuplicate);
}
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_sets_root_null);
RUN_TEST(test_treeSize);
return UNITY_END();
}

73
test_numbers.c Normal file
View File

@ -0,0 +1,73 @@
#include "unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "numbers.h"
#define TEST_ARRAY_LEN 100
// Speicher für ein Array wird reserviert
void test_createNumbers_length(void) { // erstellt ein Array der Länge hundert
unsigned int *testArray = createNumbers(TEST_ARRAY_LEN);
TEST_ASSERT_NOT_NULL(testArray);
free(testArray);
}
// Duplikat ist genau einmal vorhanden
void test_createNumbers_single_duplicate(void) {
unsigned int *testArray = createNumbers(TEST_ARRAY_LEN); // Array erstellen
TEST_ASSERT_NOT_NULL(testArray); // Speicher konnte reserviert werden
unsigned int duplicate =
getDuplicate(testArray, TEST_ARRAY_LEN); // Duplikat holen
TEST_ASSERT_TRUE(duplicate > 0); // Duplikat ist größer als 0
TEST_ASSERT_TRUE(
duplicate <
(2 * TEST_ARRAY_LEN)); // Duplikat liegt im vorgegebenen Zahlenbereich
unsigned int count = 0; // Anzahl der Duplikate
for (unsigned int i = 0; i < TEST_ARRAY_LEN;
i++) { // Einträge des testArrays auf Duplikate prüfen
if (testArray[i] == duplicate) {
count++;
}
}
TEST_ASSERT_EQUAL_UINT(2, count); // Duplikat zwei mal vorhanden
free(testArray); // Speicher freigeben
}
// getDuplicate testen
void test_getDuplicate_manual_array(
void) { // duplikat in fremden array wird gefunden
unsigned int numbers[5] = {10, 20, 30, 40, 20};
unsigned int duplicate = getDuplicate(numbers, 5);
TEST_ASSERT_EQUAL_UINT(20, duplicate);
}
// getDuplicate erkennt fehlerhaftes Array
void test_getDuplicate_invalid_input(void) {
TEST_ASSERT_EQUAL_UINT(
0, getDuplicate(NULL, 5)); // unsigned int getDuplicate(const unsigned int
// *numbers, unsigned int len)
unsigned int testArray[1] = {2};
TEST_ASSERT_EQUAL_UINT(0, getDuplicate(testArray, 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();
}

144
test_stack.c Normal file
View File

@ -0,0 +1,144 @@
#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); // oberstes Element ist 30
stack = pop(stack); // oberstes Element löschen
TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->data);
TEST_ASSERT_NULL(
stack->prev); // pointer zum alten head wurde auf NULL gesetzt
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)); // top gibt richtige Adresse zurück
stack = pop(stack); // oberstes Element löschen
TEST_ASSERT_EQUAL_PTR(&testInts[1], top(stack));
stack = pop(stack);
TEST_ASSERT_EQUAL_PTR(&testInts[0], top(stack));
stack = pop(stack); // bei leerem Stack wird NULL zurückgegeben
TEST_ASSERT_NULL(stack);
}
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]);
}
//printf("testints: %d,%d,%d,%d,%d",testInts[0],testInts[1],testInts[2],testInts[3],testInts[4]);
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();
}