This commit is contained in:
stsh
2022-02-17 14:55:47 +01:00
parent 36c8653382
commit 32ac505a9c
54 changed files with 0 additions and 3477 deletions
@@ -1,13 +0,0 @@
SNP_SHARED_MAKEFILE := $(if $(SNP_SHARED_MAKEFILE),$(SNP_SHARED_MAKEFILE),"~/snp/shared.mk")
TARGET := bin/personen-verwaltung
# BEGIN-STUDENTS-TO-ADD-CODE
MODULES := src/person.c src/list.c
# END-STUDENTS-TO-ADD-CODE
SOURCES := src/main.c $(MODULES)
TSTSOURCES := tests/tests.c $(MODULES)
include $(SNP_SHARED_MAKEFILE)
# CFLAGS += -Werror
@@ -1,8 +0,0 @@
/**
* @mainpage SNP - P07 Linked List
*
* @section Purpose
*
* This is a lab on usage of arrays.
*
*/
@@ -1,103 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "list.h"
static node_t anchor;
static int is_anchor(const node_t *node)
{
return node == &anchor;
}
static void remove_next(node_t *at)
{
assert(at);
assert(at->next);
if (!is_anchor(at->next)) {
node_t *next = at->next->next;
free(at->next);
at->next = next;
}
}
static node_t *find_insert(const person_t *p)
{
assert(p);
node_t *last = &anchor;
for(node_t *n = anchor.next; !is_anchor(n); last = n, n = n->next) {
int res = person_compare(&(n->content), p);
if (res == 0) {
return NULL; // *** EARLY RETURN ***// // already part of the list
} else if (res > 0) {
break; // the predecessor is the insert point
}
}
return last;
}
static node_t *find_remove(const person_t *p)
{
assert(p);
node_t *last = &anchor;
for(node_t *n = anchor.next; !is_anchor(n); last = n, n = n->next) {
int res = person_compare(&(n->content), p);
if (res == 0) {
break; // the predecessor is the remove point
}
}
return is_anchor(last->next) ? NULL : last;
}
const node_t *list_anchor(void)
{
return &anchor;
}
const node_t *list_init()
{
anchor.next = &anchor;
return &anchor;
}
int list_insert(const person_t *p)
{
node_t *at = find_insert(p);
node_t *insert = NULL;
if (at) {
insert = malloc(sizeof(node_t));
if (insert) {
insert->content = *p;
insert->next = at->next;
at->next = insert;
}
}
return at && insert;
}
int list_remove(const person_t *p)
{
node_t *at = find_remove(p);
if (at) {
remove_next(at);
}
return at != NULL;
}
void list_clear(void)
{
node_t *n = &anchor;
do {
remove_next(n);
} while (!is_anchor(n->next));
}
void list_show(void)
{
node_t *n = &anchor;
do {
if (!is_anchor(n)) printf("%20s %20s %u\n", n->content.name, n->content.first_name, n->content.age);
n = n->next;
} while(!is_anchor(n));
}
@@ -1,17 +0,0 @@
#ifndef _LIST_H_
#define _LIST_H_
#include "person.h"
typedef struct node {
person_t content; // in diesem Knoten gespeicherte Person
struct node *next; // Pointer auf den nächsten Knoten in der Liste
} node_t;
const node_t *list_init();
int list_insert(const person_t *p);
int list_remove(const person_t *p);
void list_clear(void);
void list_show(void);
#endif // _LIST_H_
@@ -1,68 +0,0 @@
/* ----------------------------------------------------------------------------
* -- _____ ______ _____ -
* -- |_ _| | ____|/ ____| -
* -- | | _ __ | |__ | (___ Institute of Embedded Systems -
* -- | | | '_ \| __| \___ \ Zuercher Hochschule Winterthur -
* -- _| |_| | | | |____ ____) | (University of Applied Sciences) -
* -- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland -
* ----------------------------------------------------------------------------
*/
/**
* @file
* @brief Lab implementation
*/
#include <stdio.h>
#include <stdlib.h>
#include "person.h"
#include "list.h"
/**
* @brief Main entry point.
* @param[in] argc The size of the argv array.
* @param[in] argv The command line arguments...
* @returns Returns EXIT_SUCCESS (=0) on success, EXIT_FAILURE (=1) there is an expression syntax error.
*/
int main(int argc, char* argv[])
{
// BEGIN-STUDENTS-TO-ADD-CODE
list_init();
person_t p;
int show_menu = 1;
while(1) {
if (show_menu) printf("I(nsert), R(emove), S(how), C(lear), E(nd)\n");
show_menu = 1;
int op = getchar();
switch(op) {
case 'I': case 'i':
if (!person_read(&p) || !list_insert(&p)) {
printf("failed to insert person\n");
}
break;
case 'R': case 'r':
if (!person_read(&p) || !list_remove(&p)) {
printf("failed to remove person\n");
}
break;
case 'S': case 's':
list_show();
break;
case 'C': case 'c':
list_clear();
break;
case EOF:
case 'E': case 'e':
return EXIT_SUCCESS; // *** EARLY RETURN *** //
break;
case ' ': case '\n':
show_menu = 0;
break;
default:
printf("Unknown command: %c\n", op);
break;
}
}
// END-STUDENTS-TO-ADD-CODE
return EXIT_SUCCESS;
}
@@ -1,22 +0,0 @@
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "person.h"
int person_compare(const person_t *a, const person_t *b)
{
assert(a);
assert(b);
int res = strncmp(a->name, b->name, NAME_LEN);
if (res == 0) res = strncmp(a->first_name, b->first_name, NAME_LEN);
if (res == 0) res = a->age - b->age;
return res;
}
int person_read(person_t *p)
{
assert(p);
assert(NAME_LEN == 20);
return scanf("%19s %19s %u", p->name, p->first_name, &(p->age)) == 3;
}
@@ -1,26 +0,0 @@
#ifndef _PERSON_H_
#define _PERSON_H_
#define NAME_LEN 20
typedef struct {
char name[NAME_LEN];
char first_name[NAME_LEN];
unsigned int age;
} person_t;
/**
* @brief Compares two persons in this sequence: 1st=name, 2nd=first_name, 3rd=age
* @param a [IN] const reference to 1st person in the comparison
* @param b [IN] const reference to 2nd person in the comparison
* @return =0 if all record fields are the same
* >0 if all previous fields are the same, but for this field, a is greater
* <0 if all previous fields are the same, but for this field, b is greater
* @remark strncmp() is used for producing the result of string field comparisons
* @remark a->age b->age is used for producing the result of age comparison
*/
int person_compare(const person_t *a, const person_t *b);
int person_read(person_t *p);
#endif // _PERSON_H_
@@ -1,299 +0,0 @@
/* ----------------------------------------------------------------------------
* -- _____ ______ _____ -
* -- |_ _| | ____|/ ____| -
* -- | | _ __ | |__ | (___ Institute of Embedded Systems -
* -- | | | '_ \| __| \___ \ Zuercher Hochschule Winterthur -
* -- _| |_| | | | |____ ____) | (University of Applied Sciences) -
* -- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland -
* ----------------------------------------------------------------------------
*/
/**
* @file
* @brief Test suite for the given package.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <assert.h>
#include <CUnit/Basic.h>
#include "test_utils.h"
#include "person.h"
#include "list.h"
#ifndef TARGET // must be given by the make file --> see test target
#error missing TARGET define
#endif
/// @brief alias for EXIT_SUCCESS
#define OK EXIT_SUCCESS
/// @brief alias for EXIT_FAILURE
#define FAIL EXIT_FAILURE
/// @brief The name of the STDOUT text file.
#define OUTFILE "stdout.txt"
/// @brief The name of the STDERR text file.
#define ERRFILE "stderr.txt"
#define TRACE_INDENT "\n " ///< allow for better stdout formatting in case of error
// setup & cleanup
static int setup(void)
{
remove_file_if_exists(OUTFILE);
remove_file_if_exists(ERRFILE);
return 0; // success
}
static int teardown(void)
{
// Do nothing.
// Especially: do not remove result files - they are removed in int setup(void) *before* running a test.
return 0; // success
}
// tests
static void test_person_compare(void)
{
// BEGIN-STUDENTS-TO-ADD-CODE
// arrange
person_t a = { "a", "a", 1 };
person_t b = { "a", "a", 2 };
person_t c = { "a", "b", 1 };
person_t d = { "a", "b", 2 };
person_t e = { "b", "a", 1 };
person_t f = { "b", "a", 2 };
person_t g = { "b", "b", 1 };
person_t h = { "b", "b", 2 };
// act & assert
CU_ASSERT_TRUE(person_compare(&a, &a) == 0);
CU_ASSERT_TRUE(person_compare(&a, &b) < 0);
CU_ASSERT_TRUE(person_compare(&a, &c) < 0);
CU_ASSERT_TRUE(person_compare(&a, &d) < 0);
CU_ASSERT_TRUE(person_compare(&a, &e) < 0);
CU_ASSERT_TRUE(person_compare(&a, &f) < 0);
CU_ASSERT_TRUE(person_compare(&a, &g) < 0);
CU_ASSERT_TRUE(person_compare(&a, &h) < 0);
CU_ASSERT_TRUE(person_compare(&b, &a) > 0);
CU_ASSERT_TRUE(person_compare(&b, &b) == 0);
CU_ASSERT_TRUE(person_compare(&b, &c) < 0);
CU_ASSERT_TRUE(person_compare(&b, &d) < 0);
CU_ASSERT_TRUE(person_compare(&b, &e) < 0);
CU_ASSERT_TRUE(person_compare(&b, &f) < 0);
CU_ASSERT_TRUE(person_compare(&b, &g) < 0);
CU_ASSERT_TRUE(person_compare(&b, &h) < 0);
CU_ASSERT_TRUE(person_compare(&c, &a) > 0);
CU_ASSERT_TRUE(person_compare(&c, &b) > 0);
CU_ASSERT_TRUE(person_compare(&c, &c) == 0);
CU_ASSERT_TRUE(person_compare(&c, &d) < 0);
CU_ASSERT_TRUE(person_compare(&c, &e) < 0);
CU_ASSERT_TRUE(person_compare(&c, &f) < 0);
CU_ASSERT_TRUE(person_compare(&c, &g) < 0);
CU_ASSERT_TRUE(person_compare(&c, &h) < 0);
CU_ASSERT_TRUE(person_compare(&d, &a) > 0);
CU_ASSERT_TRUE(person_compare(&d, &b) > 0);
CU_ASSERT_TRUE(person_compare(&d, &c) > 0);
CU_ASSERT_TRUE(person_compare(&d, &d) == 0);
CU_ASSERT_TRUE(person_compare(&d, &e) < 0);
CU_ASSERT_TRUE(person_compare(&d, &f) < 0);
CU_ASSERT_TRUE(person_compare(&d, &g) < 0);
CU_ASSERT_TRUE(person_compare(&d, &h) < 0);
CU_ASSERT_TRUE(person_compare(&e, &a) > 0);
CU_ASSERT_TRUE(person_compare(&e, &b) > 0);
CU_ASSERT_TRUE(person_compare(&e, &c) > 0);
CU_ASSERT_TRUE(person_compare(&e, &d) > 0);
CU_ASSERT_TRUE(person_compare(&e, &e) == 0);
CU_ASSERT_TRUE(person_compare(&e, &f) < 0);
CU_ASSERT_TRUE(person_compare(&e, &g) < 0);
CU_ASSERT_TRUE(person_compare(&e, &h) < 0);
CU_ASSERT_TRUE(person_compare(&f, &a) > 0);
CU_ASSERT_TRUE(person_compare(&f, &b) > 0);
CU_ASSERT_TRUE(person_compare(&f, &c) > 0);
CU_ASSERT_TRUE(person_compare(&f, &d) > 0);
CU_ASSERT_TRUE(person_compare(&f, &e) > 0);
CU_ASSERT_TRUE(person_compare(&f, &f) == 0);
CU_ASSERT_TRUE(person_compare(&f, &g) < 0);
CU_ASSERT_TRUE(person_compare(&f, &h) < 0);
CU_ASSERT_TRUE(person_compare(&g, &a) > 0);
CU_ASSERT_TRUE(person_compare(&g, &b) > 0);
CU_ASSERT_TRUE(person_compare(&g, &c) > 0);
CU_ASSERT_TRUE(person_compare(&g, &d) > 0);
CU_ASSERT_TRUE(person_compare(&g, &e) > 0);
CU_ASSERT_TRUE(person_compare(&g, &f) > 0);
CU_ASSERT_TRUE(person_compare(&g, &g) == 0);
CU_ASSERT_TRUE(person_compare(&g, &h) < 0);
CU_ASSERT_TRUE(person_compare(&h, &a) > 0);
CU_ASSERT_TRUE(person_compare(&h, &b) > 0);
CU_ASSERT_TRUE(person_compare(&h, &c) > 0);
CU_ASSERT_TRUE(person_compare(&h, &d) > 0);
CU_ASSERT_TRUE(person_compare(&h, &e) > 0);
CU_ASSERT_TRUE(person_compare(&h, &f) > 0);
CU_ASSERT_TRUE(person_compare(&h, &g) > 0);
CU_ASSERT_TRUE(person_compare(&h, &h) == 0);
// END-STUDENTS-TO-ADD-CODE
}
static void test_list_insert(void)
{
// BEGIN-STUDENTS-TO-ADD-CODE
// arrange
const node_t *anchor = list_init();
CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
// act & assert: insert one
person_t p1 = { "a", "b", 123 };
CU_ASSERT_TRUE(list_insert(&p1));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
// act & assert: insert a second after first
person_t p2 = { "a", "b", 124 };
CU_ASSERT_TRUE(list_insert(&p2));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p2) == 0);
// act & assert: insert a second before first
person_t p3 = { "a", "b", 122 };
CU_ASSERT_TRUE(list_insert(&p3));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p3) == 0);
CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p1) == 0);
CU_ASSERT_TRUE(person_compare(&(anchor->next->next->next->content), &p2) == 0);
// act & assert: reject inserting same
CU_ASSERT_FALSE(list_insert(&p1));
// unchanged
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next->next);
// unchanged
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p3) == 0);
CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p1) == 0);
CU_ASSERT_TRUE(person_compare(&(anchor->next->next->next->content), &p2) == 0);
// END-STUDENTS-TO-ADD-CODE
}
static void test_list_remove(void)
{
// BEGIN-STUDENTS-TO-ADD-CODE
// arrange
const node_t *anchor = list_init();
CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
// act & assert: remove one
person_t p1 = { "a", "b", 123 };
CU_ASSERT_TRUE(list_insert(&p1));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
// remove same
CU_ASSERT_TRUE_FATAL(list_remove(&p1));
CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
// act & assert: failed to remove
CU_ASSERT_TRUE(list_insert(&p1));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
// remove not found
person_t p2 = { "a", "b", 124 };
CU_ASSERT_FALSE_FATAL(list_remove(&p2));
// unchanged
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
// act & assert: remove last
CU_ASSERT_TRUE(list_insert(&p2));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p2) == 0);
CU_ASSERT_TRUE_FATAL(list_remove(&p2));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
// act & assert: remove first
CU_ASSERT_TRUE(list_insert(&p2));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p2) == 0);
CU_ASSERT_TRUE_FATAL(list_remove(&p1));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p2) == 0);
// END-STUDENTS-TO-ADD-CODE
}
static void test_list_clear(void)
{
// BEGIN-STUDENTS-TO-ADD-CODE
// arrange
const node_t *anchor = list_init();
CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
// act & assert: empty list
list_clear();
CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
// act & assert: clear list of one
person_t p1 = { "a", "b", 123 };
CU_ASSERT_TRUE(list_insert(&p1));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
list_clear();
CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
// act & assert: clear list of two
person_t p2 = { "a", "b", 124 };
CU_ASSERT_TRUE(list_insert(&p1));
CU_ASSERT_TRUE(list_insert(&p2));
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next);
CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p2) == 0);
list_clear();
CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
// END-STUDENTS-TO-ADD-CODE
}
/**
* @brief Registers and runs the tests.
* @returns success (0) or one of the CU_ErrorCode (>0)
*/
int main(void)
{
// setup, run, teardown
TestMainBasic("lab test", setup, teardown
, test_person_compare
, test_list_insert
, test_list_remove
, test_list_clear
);
}