Compare commits
46
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b042ba608c | ||
|
|
275d5d2dc7 | ||
|
|
4359714d09 | ||
|
|
c3def11852 | ||
|
|
c8edc1a619 | ||
|
|
d88da21423 | ||
|
|
d4df9b6770 | ||
|
|
6343097fc1 | ||
|
|
b37cc088d8 | ||
|
|
22d8fd6043 | ||
|
|
271eedd37c | ||
|
|
c3ce82150e | ||
|
|
6dd9514f80 | ||
|
|
2f3fee4cb2 | ||
|
|
0a30e04157 | ||
|
|
e4a7f9ac28 | ||
|
|
42243120eb | ||
|
|
5857955dc0 | ||
|
|
3fdc249d86 | ||
|
|
a6850b83c3 | ||
|
|
36e85dd4f4 | ||
|
|
df9dedb1ad | ||
|
|
cc318031be | ||
|
|
179965193e | ||
|
|
99477d3b58 | ||
|
|
d4f6132544 | ||
|
|
782ff596bd | ||
|
|
eb868c356a | ||
|
|
8151f21b38 | ||
|
|
7d54dac71a | ||
|
|
0e7802fb30 | ||
|
|
ef8340ba6b | ||
|
|
9a8a346a1e | ||
|
|
40a6501fde | ||
|
|
52e83f52a2 | ||
|
|
2c10463852 | ||
|
|
7780bddc53 | ||
|
|
0d561c0175 | ||
|
|
2950b10931 | ||
|
|
adc3ebc8be | ||
|
|
85b5c181a0 | ||
|
|
b0826ec057 | ||
|
|
12742b46fe | ||
|
|
cd13bbea4e | ||
|
|
0c075ea18c | ||
|
|
d6a439f85a |
+2
-1
@@ -5,4 +5,5 @@
|
|||||||
!**/*.c
|
!**/*.c
|
||||||
!**/*.h
|
!**/*.h
|
||||||
!**/*Makefile
|
!**/*Makefile
|
||||||
!**/*.md
|
!**/*.md
|
||||||
|
I2_Dobble/highscores.txt
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# stack.h
|
||||||
|
*Aufgabe: passender Datentyp für ein Listenelement als struct anlegen*
|
||||||
|
|
||||||
|
``` c
|
||||||
|
typedef struct Node
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
struct Node* next;
|
||||||
|
} StackNode;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **typedef** nicht zwingend notwendig, aber erleichtert später den Aufruf: `StackNode` vs `struct stackNode`
|
||||||
|
* **Zeiger data** zeigt auf in Liste gespeicherten Wert
|
||||||
|
* **Zeiger auf Node struct**, der auf das folgende Node zeiget (oder NULL ist, wenn kein folgendes vorhanden)
|
||||||
|
* für jedes struct dieses Typs, dass wir später in den Stack.c Funktionen erstellen muss Speicher manuell zugewiesen werden!
|
||||||
|
|
||||||
|
|
||||||
|
# stack.c
|
||||||
|
|
||||||
|
### push:
|
||||||
|
*neues Element oben auf die Liste legen*
|
||||||
|
* Sicherheits-Überprüfung: falls übergebener Pointer für Daten kein Ziel hat (data = NULL) => alle unten beschriebenen Schritte werden übersprungen, Stack- Pointer wird unverändert zurück gegeben
|
||||||
|
* Listenelement erstellen: (Standard Ablauf für Structs)
|
||||||
|
* Pointer initialisieren
|
||||||
|
* mit malloc an diesem Ort im Speicher in der richtigen Größe reservieren (hier Größe eines Listenelements)
|
||||||
|
* Speicher kann genutzt werden
|
||||||
|
* data wird gespeichert
|
||||||
|
* next passend setzen, entweder zuvor oberstes Element oder keines, wenn Liste leer war
|
||||||
|
* stack-Pointer auf neues, oberstes Listetenelement zeigen lassen
|
||||||
|
|
||||||
|
### pop:
|
||||||
|
*oberstes Element von Liste löschen*
|
||||||
|
* Sicherheits-Überprüfung: wenn Stack schon leer ist wird nichts entfernt (Stack = NULL bedeutet kein erstes Element existiert) - sonst würde nicht reservierter Speicher freigegeben
|
||||||
|
* müssen alle Zeiger auf das Element ändern und den Speicher Freigeben - damit ist alles entfernt:
|
||||||
|
* zum Löschen wird Speicher am Ort des stack-Zeigers freigegeben - damit ist das oberste Element weg
|
||||||
|
* zuletzt wird der Stack-Zeiger neu gesetzt, um auch alle Pointer, die noch auf das gelöschte Element zeigen zu aktuallisieren
|
||||||
|
|
||||||
|
### top:
|
||||||
|
*gibt Daten-Zeiger des obersten Elements zurück*
|
||||||
|
* Sicherheits-Überprüfung: existiert ein oberstes Element überhaupt? sonst würde man beim Versuch data auszulesen auf überhaupt nicht bzw anders zugewiesenen Speicher zugreifen!
|
||||||
|
* zur normalen Ausgabe wird einfach der Zeigerwert der data-Variable des oberster Stackelements zurückgegeben
|
||||||
|
|
||||||
|
### clear stack:
|
||||||
|
*die Liste leeren inklusive Speicherfreigabe*
|
||||||
|
* Funktionsprinzip: so lange das oberste Element mit pop-funktion entfernen, bis die Liste leer ist
|
||||||
|
* da pop erkennt, wenn Liste leer und dann den Stack-Pointer NULL setzt dient das als Schleifenvariable
|
||||||
@@ -8,11 +8,51 @@
|
|||||||
* `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. */
|
||||||
|
|
||||||
|
static StackNode *iteratorStack = NULL;
|
||||||
|
|
||||||
// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates
|
// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates
|
||||||
// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added).
|
// 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 (root == NULL)
|
||||||
|
{
|
||||||
|
// Neue Node anlegen
|
||||||
|
TreeNode *newNode = malloc(sizeof(TreeNode));
|
||||||
|
if (!newNode) return NULL;
|
||||||
|
|
||||||
|
newNode->data = malloc(dataSize);
|
||||||
|
if(!newNode->data)
|
||||||
|
{
|
||||||
|
free(newNode);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(newNode->data, data, dataSize);
|
||||||
|
|
||||||
|
newNode->left = NULL;
|
||||||
|
newNode->right = NULL;
|
||||||
|
|
||||||
|
if (isDuplicate)
|
||||||
|
*isDuplicate = 0;
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmp = compareFct(data, root->data);
|
||||||
|
|
||||||
|
if (cmp == 0)
|
||||||
|
{
|
||||||
|
if (isDuplicate)
|
||||||
|
*isDuplicate = 1;
|
||||||
|
return root; // Einfügen verhindern
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmp < 0)
|
||||||
|
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
|
||||||
|
else
|
||||||
|
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
|
||||||
|
|
||||||
|
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.
|
// 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.
|
||||||
@@ -20,17 +60,57 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFc
|
|||||||
// push the top node and push all its left nodes.
|
// push the top node and push all its left nodes.
|
||||||
void *nextTreeData(TreeNode *root)
|
void *nextTreeData(TreeNode *root)
|
||||||
{
|
{
|
||||||
|
if (root != NULL)
|
||||||
|
{
|
||||||
|
clearStack(iteratorStack);
|
||||||
|
iteratorStack = NULL;
|
||||||
|
|
||||||
|
// Root + alle linken Nachfolger pushen
|
||||||
|
TreeNode *current = root;
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
iteratorStack = push(iteratorStack, current);
|
||||||
|
current = current->left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wenn Stack leer -> fertig
|
||||||
|
if (iteratorStack == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Top-Node holen
|
||||||
|
TreeNode *node = (TreeNode *)top(iteratorStack);
|
||||||
|
iteratorStack = pop(iteratorStack);
|
||||||
|
|
||||||
|
// rechten Teilbaum + linke Kette pushen
|
||||||
|
TreeNode *right = node->right;
|
||||||
|
while (right != NULL)
|
||||||
|
{
|
||||||
|
iteratorStack = push(iteratorStack, right);
|
||||||
|
right = right->left;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Releases all memory resources (including data copies).
|
// Releases all memory resources (including data copies).
|
||||||
void clearTree(TreeNode *root)
|
void clearTree(TreeNode *root)
|
||||||
{
|
{
|
||||||
|
if (root != NULL)
|
||||||
|
{
|
||||||
|
clearTree(root->left);
|
||||||
|
clearTree(root->right);
|
||||||
|
|
||||||
|
free(root->data);
|
||||||
|
free(root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of entries in the tree given by root.
|
// Returns the number of entries in the tree given by root.
|
||||||
unsigned int treeSize(const TreeNode *root)
|
unsigned int treeSize(const TreeNode *root)
|
||||||
{
|
{
|
||||||
|
if (root == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1 + treeSize(root->left) + treeSize(root->right);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
1) static StackNode *iteratorStack = NULL
|
||||||
|
-> Stack für nextTreeData
|
||||||
|
-> wird verwendet um nach und nach die Zahlen von klein nach groß auszugeben
|
||||||
|
-> muss da so stehen, weil ansonsten nextTreeData immer von vorne anfängt
|
||||||
|
|
||||||
|
2) addToTree -> soll ein Element an die richtige Stelle im Baum hinzufügen
|
||||||
|
-> wenn keine root angegeben ist (wenn entweder kein Baum vorhanden ist, oder die richtige Stelle gefunden wurde) soll ein neue Node erstellt werden.
|
||||||
|
-> Speicher reservieren
|
||||||
|
-> data nach newNode.data kopieren (memcpy) kopiert einfach nur den Inhalt ohne ihn zu interpretieren
|
||||||
|
-> pointer links und rechts werden NULL gesetzt, da keine anderen Datan vorhanden sind
|
||||||
|
-> isDublicate = 0, da kein Dublikat vorhanden sein kann
|
||||||
|
|
||||||
|
-> root.data wird mit data verglichen (größer, kleiner, gleich), um zu entscheiden, ob rechts oder links eingefügt werden soll
|
||||||
|
-> gleich -> Dublikat -> einfügen verhindern
|
||||||
|
-> größer -> rechts einfügen
|
||||||
|
-> kleiner -> links einfügen
|
||||||
|
|
||||||
|
-> eingefügt wird, in dem addToTree erneut aufgerufen wird, aber jetzt als root root.left/root.right übergeben wird
|
||||||
|
-> es wird erneut verglichen und wieder in den rechten, bzw. linken Teilbaum eingefügt, solange bis richtige Stelle im Baum erreicht ist -> einfügen des Wertes
|
||||||
|
|
||||||
|
3) nextTreeData
|
||||||
|
-> soll nacheinander die Werte des Binärbaums der größe nach ausgeben
|
||||||
|
-> Diese Funktion beruht auf einem richtigen Binär Baum (werte stehen an der richtigen Stelle)
|
||||||
|
-> dabei wird der iteratorStack verwendet, auf diesem sind immer Teilbereiche unseres Binärbaums vorhanden (in sortierter Reihenfolge), allerdings ist er nie vollständig, sondern wird im laufe des Programms immer durch fehlende Werte ergänzt
|
||||||
|
|
||||||
|
-> wenn root != NULL -> neuer Beginn bei einem ggf. anderen Baum
|
||||||
|
-> iteratorStack wird gelöscht um eventuelle "Rückstände" zu beseitigen
|
||||||
|
-> danach werden erstmal immer die jeweils linken Nodes in den Stack gepusht
|
||||||
|
-> im Stack liegt nun die kleinste Node ganz oben, danach werden die Werte immer größer, allerdings fehlen noch Werte dazwischen
|
||||||
|
|
||||||
|
-> anschließend wird sich die oberste Node aus dem Stack geholt und aus dem Stack entfernt -> Die ist der kleinste Wert im Baum und soll somit auch als erste zurückgegeben werden
|
||||||
|
-> jetzt wird auf dem Stack der rechte Teilbaum von unseren kleinsten Wert im Baum auf den Stack gepusht -> diese Werte sind alle größer als unsere Node, jedoch kleiner als die davor vorletzte Node im Stack -> DER STACK IST ALSO IMMER NOCH NACH DER GRÖßE SORTIERT
|
||||||
|
-> unser Stack hat jetzt den nächst größeren Wert im Baum als top Node -> ausgangssituation für nächsten Aufruf
|
||||||
|
-> gepeicherte node wird verwendet um node.data auszugeben
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Beispiel Baum:
|
||||||
|
|
||||||
|
12
|
||||||
|
/ \
|
||||||
|
8 15
|
||||||
|
/ \ \
|
||||||
|
5 9 17
|
||||||
|
/ \
|
||||||
|
16 20
|
||||||
|
|
||||||
|
1) erst alle linken Nodes pushen -> 5
|
||||||
|
8
|
||||||
|
12
|
||||||
|
|
||||||
|
2) top Node (5) speichern und aus Stack entfernen -> 8
|
||||||
|
12
|
||||||
|
|
||||||
|
3) rechte Node und alle jeweils linken Nodes pushen -> 8
|
||||||
|
12
|
||||||
|
4) -> 5 wird ausgegeben (gepeicherte Node)
|
||||||
|
5) neuer Aufruf
|
||||||
|
6) top Node speichern (8) und aus Stack entfernen -> 12
|
||||||
|
7) rechte Node und alle jeweils linken Nodes pushen -> 9
|
||||||
|
12
|
||||||
|
8) -> 8 wird ausgegeben (gespeicherte Node)
|
||||||
|
9) neuer Aufruf
|
||||||
|
10) top Node speichern (9) und aus Stack entfernen -> 12
|
||||||
|
11) rechte Node und alle jeweils linken Nodes pushen -> 12
|
||||||
|
12) -> 9 wird ausgegeben (gespeicherte Node)
|
||||||
|
13) neuer Aufruf
|
||||||
|
14) top Node speichern (12) und aus Stack entfernen -> NULL
|
||||||
|
15) rechte Node und alle jeweils linken Nodes pushen -> 15
|
||||||
|
16) -> 12 wird ausgegeben (gespeicherte Node)
|
||||||
|
17) neuer Aufruf
|
||||||
|
18) top Node speichern (15) und aus Stack entfernen -> NULL
|
||||||
|
19) rechte Node und alle jeweils linken Nodes pushen -> 16
|
||||||
|
17
|
||||||
|
20) -> 15 wird ausgegeben (gespeicherte Node)
|
||||||
|
21) neuer Aufruf
|
||||||
|
22) top Node speichern (16) und aus Stack entfernen -> 17
|
||||||
|
23) rechte Node und alle jeweils linken Nodes pushen -> 17
|
||||||
|
24) -> 16 wird ausgegeben (gespeicherte Node)
|
||||||
|
25) neuer Aufruf
|
||||||
|
26) top Node speichern (17) und aus Stack entfernen -> NULL
|
||||||
|
27) rechte Node und alle jeweils linken Nodes pushen -> 20
|
||||||
|
28) -> 17 wird ausgegeben (gespeicherte Node)
|
||||||
|
29) neuer Aufruf
|
||||||
|
30) top Node speichern (20) und aus Stack entfernen -> NULL
|
||||||
|
31) rechte Node und alle jeweils linken Nodes pushen -> NULL
|
||||||
|
32) -> 20 wird ausgegeben (gespeicherte Node)
|
||||||
|
33) neuer Aufruf -> Stack = NULL -> fertig
|
||||||
|
|
||||||
|
|
||||||
|
4) treeSize
|
||||||
|
-> rekursiver Aufruf der Funktion
|
||||||
|
|
||||||
|
-> es wird jeweils die jeweils linke und rechte Node als neue root genommen
|
||||||
|
-> aufruf mit treeSize(root->left / root -> right)
|
||||||
|
-> es wird pro aufruf +1 gerechnet
|
||||||
|
-> am Ende wird die Node Anzahl zurückgegeben
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
#include "unity.h"
|
||||||
|
#include "bintree.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static int compare(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUp(void) { }
|
||||||
|
void tearDown(void) { }
|
||||||
|
|
||||||
|
void test_addToTree_single_element(void)
|
||||||
|
{
|
||||||
|
TreeNode *root = NULL;
|
||||||
|
int value = 10;
|
||||||
|
int dup;
|
||||||
|
|
||||||
|
root = addToTree(root, &value, sizeof(int), compare, &dup);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(root);
|
||||||
|
TEST_ASSERT_EQUAL_INT(10, *(int*)root->data);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, dup); // neuer Eintrag
|
||||||
|
|
||||||
|
clearTree(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_addToTree_multiple_elements_and_size(void)
|
||||||
|
{
|
||||||
|
TreeNode *root = NULL;
|
||||||
|
int values[] = {5, 3, 7, 1, 4};
|
||||||
|
int dup;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
root = addToTree(root, &values[i], sizeof(int), compare, &dup);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT(5, treeSize(root));
|
||||||
|
|
||||||
|
clearTree(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_addToTree_duplicate_detection(void)
|
||||||
|
{
|
||||||
|
TreeNode *root = NULL;
|
||||||
|
int val = 42;
|
||||||
|
int dup;
|
||||||
|
|
||||||
|
root = addToTree(root, &val, sizeof(int), compare, &dup);
|
||||||
|
TEST_ASSERT_EQUAL(0, dup);
|
||||||
|
|
||||||
|
addToTree(root, &val, sizeof(int), compare, &dup);
|
||||||
|
TEST_ASSERT_EQUAL(1, dup);
|
||||||
|
|
||||||
|
clearTree(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_treeSize_empty_tree_detection(void)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_UINT(0, treeSize(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_nextTreeData_returns_inorder(void)
|
||||||
|
{
|
||||||
|
TreeNode *root = NULL;
|
||||||
|
int values[] = {5, 3, 7, 2, 4, 6, 8};
|
||||||
|
|
||||||
|
// Einfügen
|
||||||
|
for (int i = 0; i < 7; i++)
|
||||||
|
root = addToTree(root, &values[i], sizeof(int), compare, NULL);
|
||||||
|
|
||||||
|
/* Erwartete Reihenfolge (inorder): 2,3,4,5,6,7,8 */
|
||||||
|
int expected[] = {2,3,4,5,6,7,8};
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
void *p = nextTreeData(root); // Iterator starten
|
||||||
|
|
||||||
|
while (p != NULL)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_INT(expected[idx], *(int*)p);
|
||||||
|
idx++;
|
||||||
|
p = nextTreeData(NULL); // Fortsetzen mit NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(7, idx); //alle Einträge geprüft
|
||||||
|
|
||||||
|
clearTree(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_treeSize_returns_correct_size()
|
||||||
|
{
|
||||||
|
TreeNode *root = NULL;
|
||||||
|
int values[] = {8, 3, 10, 1, 6, 14};
|
||||||
|
|
||||||
|
//Baum aufbauen
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
root = addToTree(root, &values[i], sizeof(int), compare, NULL);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT(6, treeSize(root));
|
||||||
|
|
||||||
|
// Baum löschen
|
||||||
|
clearTree(root);
|
||||||
|
root = NULL;
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT(0, treeSize(root));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(test_addToTree_single_element);
|
||||||
|
RUN_TEST(test_addToTree_multiple_elements_and_size);
|
||||||
|
RUN_TEST(test_addToTree_duplicate_detection);
|
||||||
|
RUN_TEST(test_treeSize_empty_tree_detection);
|
||||||
|
RUN_TEST(test_nextTreeData_returns_inorder);
|
||||||
|
RUN_TEST(test_treeSize_returns_correct_size);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
+18
-10
@@ -1,6 +1,5 @@
|
|||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -g -Wall
|
CFLAGS = -g -Wall
|
||||||
LDFLAGS = -lm
|
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
include makefile_windows.variables
|
include makefile_windows.variables
|
||||||
@@ -28,29 +27,38 @@ doble_initial:
|
|||||||
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
|
||||||
|
|
||||||
doble : main.o $(program_obj_files)
|
doble : main.o $(program_obj_files)
|
||||||
$(CC) $(FLAGS) $(LDFLAGS) $^ -o doble
|
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o doble
|
||||||
|
|
||||||
$(program_obj_filesobj_files): %.o: %.c
|
$(program_obj_files): %.o: %.c
|
||||||
$(CC) -c $(FLAGS) $^ -o $@
|
$(CC) -c $(CFLAGS) $^ -o $@
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Unit Tests
|
# Unit Tests
|
||||||
# --------------------------
|
# --------------------------
|
||||||
unitTests: numbersTest
|
unity_src = $(unityfolder)/unity.c
|
||||||
|
|
||||||
|
unitTests: numbersTest stackTest bintreeTest
|
||||||
./runNumbersTest
|
./runNumbersTest
|
||||||
|
./runStackTest
|
||||||
|
./runBintreeTest
|
||||||
|
|
||||||
numbersTest: numbers.o bintree.o numbersTest.o $($(unityfolder)/unity.c)
|
numbersTest: numbers.o bintree.o stack.o numbersTest.c $(unity_src) stack.o
|
||||||
$(CC) $(FLAGS) $(LDFLAGS) $^ -o $@
|
$(CC) $(CFLAGS) $(LDFLAGS) -I$(unityfolder) $^ -o runNumbersTest
|
||||||
|
|
||||||
|
stackTest: stack.o stackTest.c $(unity_src)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -I$(unityfolder) $^ -o runStackTest
|
||||||
|
|
||||||
|
bintreeTest: bintree.o bintreeTest.c $(unity_src) stack.o
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -I$(unityfolder) $^ -o runBintreeTest
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) -c $(FLAGS) $< -o $@
|
$(CC) -c $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Clean
|
# Clean
|
||||||
# --------------------------
|
# --------------------------
|
||||||
clean:
|
clean:
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
del /f *.o doble runNumbersTest
|
del /f *.o doble doble_initial runNumbersTest runStackTest runBintreeTest
|
||||||
else
|
else
|
||||||
rm -f *.o doble runNumbersTest
|
rm -f *.o doble doble_initial runNumbersTest runStackTest runBintreeTest
|
||||||
endif
|
endif
|
||||||
+6
-3
@@ -1,4 +1,4 @@
|
|||||||
*createNumbers:
|
*createNumbers: -> numbers array gets filled with random entry with only one dublicate
|
||||||
|
|
||||||
-> check if len is greater than 2
|
-> check if len is greater than 2
|
||||||
-> create new array numbers, use malloc and check if correct
|
-> create new array numbers, use malloc and check if correct
|
||||||
@@ -7,7 +7,10 @@
|
|||||||
-> add new value to tree using addToTree and rand()
|
-> add new value to tree using addToTree and rand()
|
||||||
-> addToTree sets isDup to 1, if value already exists
|
-> addToTree sets isDup to 1, if value already exists
|
||||||
-> if value does not already exist -> add to numbers[]
|
-> if value does not already exist -> add to numbers[]
|
||||||
->
|
-> stops at numbers[len -2]
|
||||||
|
static dublicateRandomEntry:
|
||||||
|
-> numbers[len-1] is filled with random already existing number
|
||||||
|
-> numbers[len -1] gets switched with other random entry -> dublicate is placed randwom in entry; without the switch, dublicate would always be at the end
|
||||||
|
|
||||||
|
|
||||||
getDublicate:
|
getDublicate:
|
||||||
@@ -15,7 +18,7 @@ getDublicate:
|
|||||||
-> numbers (Zeiger != NULL) und len (min. 2) check
|
-> numbers (Zeiger != NULL) und len (min. 2) check
|
||||||
-> define new array numbersCopy
|
-> define new array numbersCopy
|
||||||
-> copy numbers to numbersCopy
|
-> copy numbers to numbersCopy
|
||||||
-> simple loop to copy each element number -> numbersCopy
|
-> simple loop to copy each element from numbers to numbersCopy
|
||||||
-> sort numbersCopy with qsort
|
-> sort numbersCopy with qsort
|
||||||
-> compare each element of numbersCopy with next element (if numbersCopy[i] == numbersCopy[i+1] -> dublicate was found, because same values are right next to each other)
|
-> compare each element of numbersCopy with next element (if numbersCopy[i] == numbersCopy[i+1] -> dublicate was found, because same values are right next to each other)
|
||||||
-> return found dublicate
|
-> return found dublicate
|
||||||
|
|||||||
+23
-5
@@ -11,14 +11,33 @@
|
|||||||
* 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.
|
static void dublicateRandomEntry (unsigned int *numbers, unsigned int len)
|
||||||
// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while
|
{
|
||||||
// creating random numbers.
|
if (numbers && len > 2)
|
||||||
|
{
|
||||||
|
unsigned int dubIndx = rand() % (len - 1);
|
||||||
|
unsigned int copyIndx;
|
||||||
|
|
||||||
|
copyIndx = rand() % len;
|
||||||
|
|
||||||
|
numbers[len - 1] = numbers[dubIndx];
|
||||||
|
|
||||||
|
//switching last entry with random other entry
|
||||||
|
unsigned int temp;
|
||||||
|
temp = numbers[copyIndx];
|
||||||
|
numbers[copyIndx] = numbers[len - 1];
|
||||||
|
numbers[len - 1] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int compare(const void *a, const void *b)
|
static int compare(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
|
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
{
|
{
|
||||||
if (len < 2)
|
if (len < 2)
|
||||||
@@ -48,8 +67,7 @@ unsigned int *createNumbers(unsigned int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Duplicate one random entry
|
// Duplicate one random entry
|
||||||
unsigned int dupIndex = rand() % (len - 1);
|
dublicateRandomEntry(numbers, len);
|
||||||
numbers[len - 1] = numbers[dupIndex];
|
|
||||||
|
|
||||||
clearTree(root); //Notwendigkeit muss noch restlichem Code entnommen werden
|
clearTree(root); //Notwendigkeit muss noch restlichem Code entnommen werden
|
||||||
return numbers;
|
return numbers;
|
||||||
|
|||||||
+3
-22
@@ -1,3 +1,4 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
#include "numbers.h"
|
#include "numbers.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "unity_internals.h"
|
#include "unity_internals.h"
|
||||||
@@ -53,27 +54,8 @@ void test_getDuplicate_returns_correct_value(void)
|
|||||||
TEST_ASSERT_EQUAL_UINT(7, d);
|
TEST_ASSERT_EQUAL_UINT(7, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_complete_function_of_numbers(void)
|
void setUp(void) { }
|
||||||
{
|
void tearDown(void) { }
|
||||||
unsigned int len = 50;
|
|
||||||
unsigned int *arr = createNumbers(len);
|
|
||||||
TEST_ASSERT_NOT_NULL(arr);
|
|
||||||
|
|
||||||
unsigned int d1 = getDuplicate(arr, len);
|
|
||||||
TEST_ASSERT_NOT_EQUAL(0, d1);
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
if (arr[i] == d1)
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(2, count);
|
|
||||||
|
|
||||||
free(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@@ -83,7 +65,6 @@ int main(void)
|
|||||||
RUN_TEST(test_createNumbers_has_exactly_one_duplicate);
|
RUN_TEST(test_createNumbers_has_exactly_one_duplicate);
|
||||||
RUN_TEST(test_createNumbers_has_correct_value_range);
|
RUN_TEST(test_createNumbers_has_correct_value_range);
|
||||||
RUN_TEST(test_getDuplicate_returns_correct_value);
|
RUN_TEST(test_getDuplicate_returns_correct_value);
|
||||||
RUN_TEST(test_complete_function_of_numbers);
|
|
||||||
|
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
+36
-8
@@ -1,7 +1,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
|
|
||||||
//TODO: grundlegende Stackfunktionen implementieren:
|
//DONE: grundlegende Stackfunktionen implementieren:
|
||||||
/* * `push`: legt ein Element oben auf den Stack,
|
/* * `push`: legt ein Element oben auf den Stack,
|
||||||
* `pop`: entfernt das oberste Element,
|
* `pop`: entfernt das oberste Element,
|
||||||
* `top`: liefert das oberste Element zurück,
|
* `top`: liefert das oberste Element zurück,
|
||||||
@@ -10,24 +10,52 @@
|
|||||||
// 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)
|
||||||
{
|
{
|
||||||
|
// ,-→ Wenn keine Daten angegeben wird die Liste unverändert zurückgegeben
|
||||||
|
if (data != NULL)
|
||||||
|
{
|
||||||
|
StackNode *newNode;
|
||||||
|
newNode = (StackNode *)malloc(sizeof(StackNode));
|
||||||
|
newNode->data = data;
|
||||||
|
|
||||||
|
// ,-→ bedeutet Liste war leer - das neue Element hat keinen Nachfolger (next = NULL)
|
||||||
|
if (stack == NULL) {
|
||||||
|
newNode->next = NULL;
|
||||||
|
} else {
|
||||||
|
newNode->next = stack;
|
||||||
|
}
|
||||||
|
stack = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 memory.
|
||||||
// freed by caller.)
|
// (Pointer to data has to be freed by caller.)
|
||||||
StackNode *pop(StackNode *stack)
|
StackNode *pop(StackNode *stack)
|
||||||
{
|
{
|
||||||
|
if(stack != NULL)
|
||||||
|
{
|
||||||
|
StackNode *nextNode = stack->next;
|
||||||
|
free(stack);
|
||||||
|
stack = nextNode;
|
||||||
|
}
|
||||||
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the data of the top element.
|
// Returns the data of the top element.
|
||||||
void *top(StackNode *stack)
|
void *top(StackNode *stack)
|
||||||
{
|
{
|
||||||
|
if (stack != NULL) {
|
||||||
|
return stack->data;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears stack and releases all memory.
|
// Clears stack and releases all memory.
|
||||||
void clearStack(StackNode *stack)
|
void clearStack(StackNode *stack)
|
||||||
{
|
{
|
||||||
|
while (stack != NULL) {
|
||||||
}
|
stack = pop(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+6
-1
@@ -7,7 +7,12 @@ The latest element is taken from the stack. */
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
//TODO: passenden Datentyp als struct anlegen
|
//DONE: passenden Datentyp als struct anlegen
|
||||||
|
typedef struct Node
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
struct Node* next;
|
||||||
|
} StackNode;
|
||||||
|
|
||||||
// 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);
|
||||||
|
|||||||
@@ -0,0 +1,260 @@
|
|||||||
|
#include "stack.h"
|
||||||
|
#include "unity/unity.h"
|
||||||
|
#include "unity/unity_internals.h"
|
||||||
|
|
||||||
|
/* wird nicht mehr gebraucht
|
||||||
|
|
||||||
|
// Ein Blick in den Stack - listet den Stack-Inhalt der Reihe nach auf
|
||||||
|
void inspectStack(StackNode *stack)
|
||||||
|
{
|
||||||
|
if (stack != NULL)
|
||||||
|
{
|
||||||
|
printf("Der Stack enthält die folgenden Elemente: %d", *(int*)stack->data);
|
||||||
|
while (stack->next != NULL)
|
||||||
|
{
|
||||||
|
printf(" %d", *(int*)stack->next->data);
|
||||||
|
stack = stack->next;
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Der Stack ist leer\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Setup-Funktionen von Unity, die zumindest als Platzhalter definiert sein müssen
|
||||||
|
void setUp(void) {};
|
||||||
|
void tearDown(void) {};
|
||||||
|
|
||||||
|
void test_createNodeAbortsOnZeroData(void)
|
||||||
|
{
|
||||||
|
void *data = NULL;
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
stack = push(stack, data);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(stack, NULL);
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_createdNodeIsFirstInList(void)
|
||||||
|
{
|
||||||
|
int data = 42;
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
stack = push(stack, &data);
|
||||||
|
TEST_ASSERT_NOT_NULL(stack);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(&data, stack->data);
|
||||||
|
TEST_ASSERT_NULL(stack->next);
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_createNodeCorrectOrder(void)
|
||||||
|
{
|
||||||
|
int data[3] = {0, 1, 2};
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
stack = push(stack, &data[2]);
|
||||||
|
stack = push(stack, &data[1]);
|
||||||
|
stack = push(stack, &data[0]);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(stack);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(&data[0], stack->data);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(&data[1], stack->next->data);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(&data[2], stack->next->next->data);
|
||||||
|
TEST_ASSERT_NULL(stack->next->next->next);
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_removeNodeAbortsOnZero(void)
|
||||||
|
{
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
TEST_ASSERT_NULL(pop(stack));
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_removeOnlyNodeEmptysList(void)
|
||||||
|
{
|
||||||
|
int data = 42;
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
stack = pop(push(stack, &data));
|
||||||
|
|
||||||
|
TEST_ASSERT_NULL(stack);
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_removeNodeRemovesFirst(void)
|
||||||
|
{
|
||||||
|
int data[2] = {0, 1};
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
stack = push(stack, &data[1]);
|
||||||
|
stack = push(stack, &data[0]);
|
||||||
|
stack = pop(stack);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(stack);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(&data[1], stack->data);
|
||||||
|
TEST_ASSERT_NULL(stack->next);
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_outputTopFailsOnZero(void)
|
||||||
|
{
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
|
||||||
|
TEST_ASSERT_NULL(top(stack));
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_outputTopCorrect(void)
|
||||||
|
{
|
||||||
|
int data[2] = {0, 1};
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
stack = push(stack, &data[1]);
|
||||||
|
stack = push(stack, &data[0]);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(stack);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(top(stack), stack->data);
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Speicher freigabe lässt sich nicht mit Unity testen, am besten Programm mit valgrind ausführen
|
||||||
|
void test_clearStackFreesMemory(void)
|
||||||
|
{
|
||||||
|
int data[2] = {22, 17};
|
||||||
|
StackNode *lowNode = (StackNode *)malloc(sizeof(StackNode));
|
||||||
|
lowNode->next = NULL;
|
||||||
|
lowNode->data = &data[0];
|
||||||
|
StackNode *highNode = (StackNode *)malloc(sizeof(StackNode));
|
||||||
|
highNode->next = lowNode;
|
||||||
|
highNode->data = &data[1];
|
||||||
|
StackNode *stack = highNode;
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
|
||||||
|
TEST_ASSERT_NULL(lowNode);
|
||||||
|
TEST_ASSERT_NULL(highNode);
|
||||||
|
TEST_ASSERT_NULL(stack);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void test_push_should_add_new_node_at_top(void)
|
||||||
|
{
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
|
||||||
|
int value = 42;
|
||||||
|
stack = push(stack, &value);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(stack);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(&value, stack->data);
|
||||||
|
TEST_ASSERT_NULL(stack->next);
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_push_multiple_should_chain_nodes_correctly(void)
|
||||||
|
{
|
||||||
|
int a = 1, b = 2;
|
||||||
|
|
||||||
|
StackNode *first = push(NULL, &a);
|
||||||
|
|
||||||
|
StackNode *second = push(first, &b);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_PTR(&b, second->data);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(first, second->next);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(&a, first->data);
|
||||||
|
|
||||||
|
clearStack(second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_top_should_return_null_on_empty_stack(void)
|
||||||
|
{
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
TEST_ASSERT_NULL(top(stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_top_should_return_data_of_existing_node(void)
|
||||||
|
{
|
||||||
|
StackNode node;
|
||||||
|
int x = 99;
|
||||||
|
|
||||||
|
node.data = &x;
|
||||||
|
node.next = NULL;
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_PTR(&x, top(&node));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_pop_should_return_null_when_stack_empty(void)
|
||||||
|
{
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
TEST_ASSERT_NULL(pop(stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_pop_should_remove_single_element(void)
|
||||||
|
{
|
||||||
|
StackNode *stack = malloc(sizeof(StackNode));
|
||||||
|
int x = 7;
|
||||||
|
|
||||||
|
stack->data = &x;
|
||||||
|
stack->next = NULL;
|
||||||
|
|
||||||
|
StackNode *result = pop(stack);
|
||||||
|
|
||||||
|
TEST_ASSERT_NULL(result); // Kein Element mehr übrig
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_pop_should_remove_top_node_only(void)
|
||||||
|
{
|
||||||
|
// Manuell verkettete Liste aufbauen
|
||||||
|
StackNode *n1 = malloc(sizeof(StackNode));
|
||||||
|
StackNode *n2 = malloc(sizeof(StackNode));
|
||||||
|
int a = 1, b = 2;
|
||||||
|
|
||||||
|
n1->data = &a;
|
||||||
|
n1->next = NULL;
|
||||||
|
|
||||||
|
n2->data = &b;
|
||||||
|
n2->next = n1;
|
||||||
|
|
||||||
|
StackNode *result = pop(n2);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_PTR(n1, result);
|
||||||
|
|
||||||
|
clearStack(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
printf("\n============================\n Stack tests\n============================\n");
|
||||||
|
printf("-> Create Nodes (push)\n");
|
||||||
|
RUN_TEST(test_createNodeAbortsOnZeroData);
|
||||||
|
RUN_TEST(test_createdNodeIsFirstInList);
|
||||||
|
RUN_TEST(test_createNodeCorrectOrder);
|
||||||
|
|
||||||
|
printf("\n-> Remove Nodes (pop)\n");
|
||||||
|
RUN_TEST(test_removeNodeAbortsOnZero);
|
||||||
|
RUN_TEST(test_removeOnlyNodeEmptysList);
|
||||||
|
RUN_TEST(test_removeNodeRemovesFirst);
|
||||||
|
|
||||||
|
printf("\n-> Output Top (top)\n");
|
||||||
|
RUN_TEST(test_outputTopFailsOnZero);
|
||||||
|
RUN_TEST(test_outputTopCorrect);
|
||||||
|
|
||||||
|
RUN_TEST(test_push_should_add_new_node_at_top);
|
||||||
|
RUN_TEST(test_push_multiple_should_chain_nodes_correctly);
|
||||||
|
RUN_TEST(test_top_should_return_null_on_empty_stack);
|
||||||
|
RUN_TEST(test_top_should_return_data_of_existing_node);
|
||||||
|
RUN_TEST(test_pop_should_return_null_when_stack_empty);
|
||||||
|
RUN_TEST(test_pop_should_remove_single_element);
|
||||||
|
RUN_TEST(test_pop_should_remove_top_node_only);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
#include <bits/types/stack_t.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
void inspectStack(StackNode *stack)
|
||||||
|
{
|
||||||
|
if (stack != NULL)
|
||||||
|
{
|
||||||
|
printf("Der Stack enthält die folgenden Elemente: %d", *(int*)stack->value);
|
||||||
|
while (stack->next != NULL)
|
||||||
|
{
|
||||||
|
printf(" %d", *(int*)stack->next->value);
|
||||||
|
stack = stack->next;
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Der Stack ist leer\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
StackNode *stack;
|
||||||
|
stack = NULL; // initialisierung mit NULL -> leere Liste
|
||||||
|
|
||||||
|
printf("...ein Element wird eingefügt...\n");
|
||||||
|
int toBeRemoved = 42;
|
||||||
|
stack = push(stack, &toBeRemoved);
|
||||||
|
|
||||||
|
inspectStack(stack);
|
||||||
|
|
||||||
|
printf("...das Element wird wieder entfernt...\n");
|
||||||
|
stack = pop(stack);
|
||||||
|
|
||||||
|
inspectStack(stack);
|
||||||
|
|
||||||
|
printf("...pop auf leeren Stack...\n");
|
||||||
|
stack = pop(stack);
|
||||||
|
|
||||||
|
inspectStack(stack);
|
||||||
|
putchar('\n');
|
||||||
|
|
||||||
|
int data[5] = {1, 2, 3, 4, 5};
|
||||||
|
|
||||||
|
// alle 5 werte der reihe nach auf den Satck legen - 1 unten ... 5 oben
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
stack = push(stack, &data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//alle Elemente mit Test-Funktion ausgeben
|
||||||
|
inspectStack(stack);
|
||||||
|
|
||||||
|
// Elemente stück für Stück ausgeben und entfernen
|
||||||
|
printf("1. Element war: %d\n", *(int*)top(stack));
|
||||||
|
stack = pop(stack);
|
||||||
|
printf("2. Element war: %d\n", *(int*)top(stack));
|
||||||
|
stack = pop(stack);
|
||||||
|
printf("3. Element war: %d\n", *(int*)top(stack));
|
||||||
|
stack = pop(stack);
|
||||||
|
printf("4. Element war: %d\n", *(int*)top(stack));
|
||||||
|
stack = pop(stack);
|
||||||
|
printf("5. Element war: %d\n", *(int*)top(stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
printf("============================\n Stack tests\n============================\n");
|
||||||
|
RUN_TEST(test_createNodeFailsOnZeroData);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
|
*/
|
||||||
+11
-4
@@ -1,6 +1,12 @@
|
|||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
#if __APPLE__
|
#ifdef __linux__
|
||||||
|
// Defines strict posix compliance for CLOCK_MONOTONIC
|
||||||
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __APPLE__ || __linux__
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
static struct timespec start = {0, 0};
|
static struct timespec start = {0, 0};
|
||||||
|
|
||||||
@@ -14,14 +20,15 @@ void startTimer()
|
|||||||
double stopTimer()
|
double stopTimer()
|
||||||
{
|
{
|
||||||
struct timespec end;
|
struct timespec end;
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &end);
|
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||||
|
|
||||||
unsigned long long delta_us = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000;
|
unsigned long long delta_us = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000;
|
||||||
|
|
||||||
double measuredSeconds = (double)delta_us / 1000000.;
|
double measuredSeconds = (double)delta_us / 1000000.;
|
||||||
|
|
||||||
if(start.tv_nsec > 0) {
|
if (start.tv_nsec > 0)
|
||||||
|
{
|
||||||
start.tv_nsec = 0;
|
start.tv_nsec = 0;
|
||||||
start.tv_sec = 0;
|
start.tv_sec = 0;
|
||||||
}
|
}
|
||||||
@@ -45,7 +52,7 @@ double stopTimer()
|
|||||||
{
|
{
|
||||||
double measuredSeconds = (clock() - (double)startClocks) / CLOCKS_PER_SEC;
|
double measuredSeconds = (clock() - (double)startClocks) / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
if(startClocks > 0)
|
if (startClocks > 0)
|
||||||
startClocks = 0;
|
startClocks = 0;
|
||||||
else
|
else
|
||||||
measuredSeconds = -1;
|
measuredSeconds = -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user