diff --git a/20190114/hp-musterloesung-20190114.pdf b/20190114/hp-musterloesung-20190114.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..e2247997752c9b52e1a0a93d5ddb7ee852ad63eb
Binary files /dev/null and b/20190114/hp-musterloesung-20190114.pdf differ
diff --git a/20190114/hp-musterloesung-20190114.tex b/20190114/hp-musterloesung-20190114.tex
new file mode 100644
index 0000000000000000000000000000000000000000..8da621313c63ff5d47af8c481cdcf872bc7efdcf
--- /dev/null
+++ b/20190114/hp-musterloesung-20190114.tex
@@ -0,0 +1,452 @@
+% hp-musterloesung-20190114.pdf - Solutions to the Exercises on Low-Level Programming / Applied Computer Sciences
+% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: Iteratorfunktionen, Objektorientierte Tier-Datenbank
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+\usepackage{sfmath}
+
+\begin{document}
+
+  \section*{Hardwarenahe Programmierung\\
+            Musterlösung zu den Übungsaufgaben -- 14.\ Januar 2019}
+
+  \exercise{Iterationsfunktionen}
+
+  Wir betrachten das folgende Programm (\gitfile{hp}{20190114}{aufgabe-1.c}):
+
+  \begin{minipage}[t]{0.4\textwidth}
+    \begin{lstlisting}[gobble=6]
+      #include <stdio.h>
+
+      void foreach (int *a, void (*fun) (int x))
+      {
+        for (int *p = a; *p >= 0; p++)
+          fun (*p);
+      }
+
+      void even_or_odd (int x)
+      {
+        if (x % 2)
+          printf ("%d ist ungerade.\n", x);
+        else
+          printf ("%d ist gerade.\n", x);
+      }
+    \end{lstlisting}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{0.52\textwidth}
+    \begin{lstlisting}[gobble=6]
+      int main (void)
+      {
+        int numbers[] = { 12, 17, 32, 1, 3, 16, 19, 18, -1 };
+        foreach (numbers, even_or_odd);
+        return 0;
+      }
+    \end{lstlisting}
+    \begin{enumerate}[\quad(a)]
+      \item
+        Was bedeutet \lstinline{void (*fun) (int x)},
+        und welchen Sinn hat seine Verwendung in der Funktion \lstinline{foreach()}?
+        \points{2}
+      \item
+        Schreiben Sie das Hauptprogramm \lstinline{main()} so um,
+        daß es unter Verwendung der Funktion \lstinline{foreach()}
+        die Summe aller positiven Zahlen in dem Array berechnet.
+        Sie dürfen dabei weitere Funktionen sowie globale Variable einführen.
+        \points{4}
+    \end{enumerate}
+  \end{minipage}
+
+  \solution
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      \textbf{Was bedeutet \lstinline{void (*fun) (int x)},
+      und welchen Sinn hat seine Verwendung in der Funktion \lstinline{foreach()}?}
+
+      \lstinline{void (*fun) (int x)} deklariert einen Zeiger \lstinline{fun},
+      der auf Funktionen zeigen kann, die einen Parameter \lstinline{x}
+      vom Typ \lstinline{int} erwarten und keinen Wert zurückgeben (\lstinline{void}).
+
+      Durch die Übergabe eines derartigen Parameters an die Funktion \lstinline{foreach()}
+      lassen wir dem Aufrufer die Wahl,
+      welche Aktion für alle Elemente des Arrays aufgerufen werden soll.
+
+    \item
+      \textbf{Schreiben Sie das Hauptprogramm \lstinline{main()} so um,
+      daß es unter Verwendung der Funktion \lstinline{foreach()}
+      die Summe aller positiven Zahlen in dem Array berechnet.
+      Sie dürfen dabei weitere Funktionen sowie globale Variable einführen.}
+
+      Siehe: \gitfile{hp}{20190114}{loesung-1.c}
+
+      Damit die Funktion \lstinline{add_up()} Zugriff auf die Variable \lstinline{sum} hat,
+      muß diese global sein
+      und vor der Funktion \lstinline{add_up()} deklariert werden.
+
+      Die Bedingung, daß nur positive Zahlen summiert werden sollen,
+      ist durch die Arbeitsweise der Funktion \lstinline{foreach()}
+      bereits gewährleistet, da negative Zahlen als Ende-Markierungen dienen.
+
+      Wichtig ist, daß die Variable \lstinline{sum}
+      vor dem Aufruf der Funktion \lstinline{foreach()}
+      auf den Wert \lstinline{0} gesetzt wird.
+      In \gitfile{hp}{20190114}{loesung-1.c} geschieht dies
+      durch die Initialisierung von \lstinline{sum}.
+      Wenn mehrere Summen berechnet werden sollen,
+      muß dies durch explizite Zuweisungen \lstinline{sum = 0}
+      vor den Aufrufen von \lstinline{foreach()} erfolgen.
+  \end{enumerate}
+
+  \exercise{Objektorientierte Tier-Datenbank}
+
+  Das auf der nächsten Seite in Blau dargestellte Programm (Datei: \gitfile{hp}{20190114}{aufgabe-2a.c})\\
+  soll Daten von Tieren verwalten.
+
+  Beim Compilieren erscheinen die folgende Fehlermeldungen:
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -std=c99 -Wall -O aufgabe-2a.c -o aufgabe-2a¿
+    aufgabe-2a.c: In function 'main':
+    aufgabe-2a.c:31: error: 'animal' has no member named 'wings'
+    aufgabe-2a.c:37: error: 'animal' has no member named 'legs'
+  \end{lstlisting}
+
+  Der Programmierer nimmt die auf der nächsten Seite in Rot dargestellten Ersetzungen vor\\
+  (Datei: \gitfile{hp}{20190114}{aufgabe-2b.c}).
+  Daraufhin gelingt das Compilieren, und die Ausgabe des Programms lautet:
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -std=c99 -Wall -O aufgabe-2b.c -o aufgabe-2b¿
+    $ ¡./aufgabe-2b¿
+    A duck has 2 legs.
+    Error in animal: cow
+  \end{lstlisting}
+
+  \begin{itemize}
+    \item[(a)]
+      Erklären Sie die o.\,a.\ Compiler-Fehlermeldungen.
+      \points{2}
+    \item[(b)]
+      Wieso verschwinden die Fehlermeldungen nach den o.\,a.\ Ersetzungen?
+      \points{3}
+    \item[(c)]
+      Erklären Sie die Ausgabe des Programms.
+      \points{5}
+    \item[(d)]
+      Beschreiben Sie -- in Worten und/oder als C-Quelltext -- einen Weg,
+      das Programm so zu berichtigen, daß es die Eingabedaten
+      (``A duck has 2 wings. A cow has 4 legs.'') korrekt speichert und ausgibt.\\
+      \points{4}
+    \item[(e)]
+      Schreiben Sie das Programm so um,
+      daß es keine expliziten Typumwandlungen mehr benötigt.\par
+      Hinweis: Verwenden Sie \lstinline{union}.
+      \points{4}
+    \item[(f)]
+      Schreiben Sie das Programm weiter um,
+      so daß es die Objektinstanzen \lstinline{duck} und \lstinline{cow}
+      dynamisch erzeugt.\par
+      Hinweis: Verwenden Sie \lstinline{malloc()} und schreiben Sie Konstruktoren.
+      \points{4}
+    \item[(g)]
+      Schreiben Sie das Programm weiter um,
+      so daß die Ausgabe nicht mehr direkt im Hauptprogramm erfolgt,
+      sondern stattdessen eine virtuelle Methode \lstinline{print()}
+      aufgerufen wird.\par
+      Hinweis: Verwenden Sie in den Objekten Zeiger auf Funktionen,
+      und initialisieren Sie diese in den Konstruktoren.
+      \points{4}
+  \end{itemize}
+
+  \begin{minipage}[t]{0.34\textwidth}
+    \begin{lstlisting}[gobble=6,xleftmargin=0pt]
+      #include <stdio.h>
+
+      #define ANIMAL     0
+      #define WITH_WINGS 1
+      #define WITH_LEGS  2
+
+      typedef struct animal
+      {
+        int type;
+        char *name;
+      } animal;
+
+      typedef struct with_wings
+      {
+        int wings;
+      } with_wings;
+
+      typedef struct with_legs
+      {
+        int legs;
+      } with_legs;
+    \end{lstlisting}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{0.65\textwidth}
+    \begin{lstlisting}[gobble=6,xleftmargin=0pt]
+      int main (void)
+      {
+        animal *a[2];
+
+        animal duck;
+        a[0] = &duck;
+        a[0]->type = WITH_WINGS;
+        a[0]->name = "duck";
+        a[0]->wings = 2;
+
+        animal cow;
+        a[1] = &cow;
+        a[1]->type = WITH_LEGS;
+        a[1]->name = "cow";
+        a[1]->legs = 4;
+
+        for (int i = 0; i < 2; i++)
+          if (a[i]->type == WITH_LEGS)
+            printf ("A %s has %d legs.\n", a[i]->name,
+                    ((with_legs *) a[i])-> legs);
+          else if (a[i]->type == WITH_WINGS)
+            printf ("A %s has %d wings.\n", a[i]->name,
+                    ((with_wings *) a[i])-> wings);
+          else
+            printf ("Error in animal: %s\n", a[i]->name);
+
+        return 0;
+      }
+    \end{lstlisting}
+    \begin{picture}(0,0)
+      \color{red}
+      \put(3.7,6.207){\vector(-1,0){0.7}}
+      \put(3.8,6.207){\makebox(0,0)[l]{\lstinline[basicstyle=\color{red}]{((with_legs *) a[1])->legs = 4;}}}
+      \put(4.0,8.735){\vector(-1,0){0.7}}
+      \put(4.1,8.735){\makebox(0,0)[l]{\lstinline[basicstyle=\color{red}]{((with_wings *) a[0])->wings = 2;}}}
+    \end{picture}
+  \end{minipage}
+
+  \solution
+
+  \begin{itemize}
+    \item[(a)]
+      \textbf{Erklären Sie die o.\,a.\ Compiler-Fehlermeldungen.}
+
+      \lstinline{a[0]} und \lstinline{a[1]}
+      sind gemäß der Deklaration \lstinline{animal *a[2]}
+      Zeiger auf Variablen vom Typ \lstinline{animal} (ein \lstinline{struct}).
+      Wenn man diesen Zeiger dereferenziert (\lstinline{->}),
+      erhält man eine \lstinline{animal}-Variable.
+      Diese enthält keine Datenfelder \lstinline{wings} bzw.\ \lstinline{legs}.
+
+    \item[(b)]
+      \textbf{Wieso verschwinden die Fehlermeldungen nach den o.\,a.\ Ersetzungen?}
+
+      Durch die \emph{explizite Typumwandlung des Zeigers\/}
+      erhalten wir einen Zeiger auf eine \lstinline{with_wings}-
+      bzw.\ auf eine \lstinline{with_legs}-Variable.
+      Diese enthalten die Datenfelder \lstinline{wings} bzw.\ lstinline{legs}.
+
+    \item[(c)]
+      \textbf{Erklären Sie die Ausgabe des Programms.}
+
+      Durch die explizite Typumwandlung des Zeigers
+      zeigt \lstinline{a[0]} auf eine \lstinline{with_wings}-Variable.
+      Diese enthält nur ein einziges Datenfeld \lstinline{wings},
+      das an genau derselben Stelle im Speicher liegt
+      wie \lstinline{a[0]->type}, also das Datenfeld \lstinline{type}
+      der \lstinline{animal}-Variable, auf die der Zeiger \lstinline{a[0]} zeigt.
+      Durch die Zuweisung der Zahl \lstinline{2}
+      an \lstinline{((with_wings *) a[0])->wings}
+      überschreiben wir also \lstinline{a[0]->type},
+      so daß das \lstinline{if} in der \lstinline{for}-Schleife
+      \lstinline{a[0]} als \lstinline{WITH_LEGS} erkennt.
+
+      Bei der Ausgabe \lstinline[style=terminal]{A duck has 2 legs.}
+      wird das Datenfeld \lstinline{((with_legs *)a[0])->legs} als Zahl ausgegeben.
+      Dieses Datenfeld befindet sich in denselben Speicherzellen wie
+      \lstinline{a[0]->type} und \lstinline{((with_wings *)} % :-(
+      \lstinline{a[0]->wings}
+      und hat daher ebenfalls den Wert 2.
+
+      Auf die gleiche Weise überschreiben wir durch die Zuweisung der Zahl 4
+      an \lstinline{((with_legs *) a[1])->legs}
+      das Datenfeld \lstinline{a[0]->type},
+      so daß das \lstinline{if} in der \lstinline{for}-Schleife
+      \lstinline{a[1]} als unbekanntes Tier (Nr.\ 4) erkennt und
+      \lstinline[style=terminal]{Error in animal: cow} ausgibt.
+
+    \item[(d)]
+      \textbf{Beschreiben Sie -- in Worten und/oder als C-Quelltext -- einen Weg,
+      das Programm so zu berichtigen, daß es die Eingabedaten
+      (``A duck has 2 wings. A cow has 4 legs.'') korrekt speichert und ausgibt.}
+
+      Damit die \emph{Vererbung\/} zwischen den Objekten
+      \lstinline{animal}, \lstinline{with_wings} und \lstinline{with_legs}
+      funktioniert, müssen die abgeleiteten Klassen \lstinline{with_wings} und \lstinline{with_legs}
+      alle Datenfelder der Basisklasse \lstinline{animal} erben.
+      In C geschieht dies explizit; die Datenfelder müssen in den
+      abgeleiteten Klassen neu angegeben werden
+      (siehe \gitfile{hp}{20190114}{loesung-2d-1.c}):
+
+      \begin{lstlisting}[gobble=8]
+        typedef struct animal
+        {
+          int type;
+          char *name;
+        } animal;
+
+        typedef struct with_wings
+        {
+          int type;
+          char *name;
+          int wings;
+        } with_wings;
+
+        typedef struct with_legs
+        {
+          int type;
+          char *name;
+          int legs;
+        } with_legs;
+      \end{lstlisting}
+
+      Zusätzlich ist es notwendig,
+      die Instanzen \lstinline{duck} und \lstinline{cow}
+      der abgeleiteten Klassen \lstinline{with_wings} und \lstinline{with_legs}
+      auch als solche zu deklarieren,
+      damit für sie genügend Speicher reserviert wird:
+
+      \begin{lstlisting}[gobble=8]
+        animal *a[2];
+
+        with_wings duck;
+        a[0] = (animal *) &duck;
+        a[0]->type = WITH_WINGS;
+        a[0]->name = "duck";
+        ((with_wings *) a[0])->wings = 2;
+
+        with_legs cow;
+        a[1] = (animal *) &cow;
+        a[1]->type = WITH_LEGS;
+        a[1]->name = "cow";
+        ((with_legs *) a[1])->legs = 4;
+      \end{lstlisting}
+
+      Wenn man dies vergißt und sie nur als \lstinline{animal} deklariert,
+      wird auch nur Speicherplatz für (kleinere)
+      \lstinline{animal}-Variable angelegt.
+      Dadurch kommt es zu Speicherzugriffen außerhalb der
+      deklarierten Variablen, was letztlich zu einem Absturz führt
+      (siehe \gitfile{hp}{20190114}{loesung-2d-0f.c}).
+
+      Für die Zuweisung eines Zeigers auf \lstinline{duck}
+      an \lstinline{a[0]}, also an einen Zeiger auf \lstinline{animal}
+      wird eine weitere explizite Typumwandlung notwendig.
+      Entsprechendes gilt für die Zuweisung eines Zeigers auf \lstinline{cow}
+      an \lstinline{a[1]}.
+
+      Es ist sinnvoll, explizite Typumwandlungen so weit wie möglich zu vermeiden.
+      Es ist einfacher und gleichzeitig sicherer,
+      direkt in die Variablen \lstinline{duck} und \lstinline{cow}
+      zu schreiben, anstatt dies über die Zeiger \lstinline{a[0]}
+      und \lstinline{a[1]} zu tun
+      (siehe \gitfile{hp}{20190114}{loesung-2d-2.c}):
+
+      \begin{lstlisting}[gobble=8]
+        animal *a[2];
+
+        with_wings duck;
+        a[0] = (animal *) &duck;
+        duck.type = WITH_WINGS;
+        duck.name = "duck";
+        duck.wings = 2;
+
+        with_legs cow;
+        a[1] = (animal *) &cow;
+        cow.type = WITH_LEGS;
+        cow.name = "cow";
+        cow.legs = 4;
+      \end{lstlisting}
+
+    \item[(e)]
+      \textbf{Schreiben Sie das Programm so um,
+      daß es keine expliziten Typumwandlungen mehr benötigt.}\par
+      \textbf{Hinweis: Verwenden Sie \lstinline{union}.}
+
+      Siehe \gitfile{hp}{20190114}{loesung-2e.c}.
+      
+      Diese Lösung basiert auf \gitfile{hp}{20190114}{loesung-2d-2.c},
+      da diese bereits weniger explizite Typumwandlungen enthält
+      als \gitfile{hp}{20190114}{loesung-2d-1.c}.
+
+      Arbeitsschritte:
+      \begin{itemize}
+        \item
+          Umbenennen des Basistyps \lstinline{animal} in \lstinline{base},
+          damit wir den Bezeichner \lstinline{animal}
+          für die \lstinline{union} verwenden können
+        \item
+          Schreiben einer \lstinline{union animal},
+          die die drei Klassen \lstinline{base},
+          \lstinline{with_wings} und \lstinline{with_legs}
+          als Datenfelder enthält
+        \item
+          Umschreiben der Initialisierungen:
+          Zugriff auf Datenfelder erfolgt nun durch
+          z.\,B.\ \lstinline{a[0]->b.name}.
+          Hierbei ist \lstinline{b} der Name des \lstinline{base}-Datenfelds
+          innerhalb der \lstinline{union animal}.
+        \item
+          Auf gleiche Weise schreiben wir die \lstinline{if}-Bedingungen
+          innerhalb der \lstinline{for}-Schleife
+          sowie die Parameter der \lstinline{printf()}-Aufrufe um.
+      \end{itemize}
+      Explizite Typumwandlungen sind nun nicht mehr nötig.
+
+      Nachteil dieser Lösung:
+      Jede Objekt-Variable belegt nun Speicherplatz
+      für die gesamte \lstinline{union animal},
+      anstatt nur für die benötigte Variable vom Typ
+      \lstinline{with_wings} oder \lstinline{with_legs}.
+      Dies kann zu einer Verschwendung von Speicherplatz führen,
+      auch wenn dies in diesem Beispielprogramm tatsächlich nicht der Fall ist.
+
+    \item[(f)]
+      \textbf{Schreiben Sie das Programm weiter um,
+      so daß es die Objektinstanzen \lstinline{duck} und \lstinline{cow}
+      dynamisch erzeugt.}\par
+      \textbf{Hinweis: Verwenden Sie \lstinline{malloc()} und schreiben Sie Konstruktoren.}
+
+      Siehe \gitfile{hp}{20190114}{loesung-2f.c}.
+
+    \item[(g)]
+      \textbf{Schreiben Sie das Programm weiter um,
+      so daß die Ausgabe nicht mehr direkt im Hauptprogramm erfolgt,
+      sondern stattdessen eine virtuelle Methode \lstinline{print()}
+      aufgerufen wird.}\par
+      \textbf{Hinweis: Verwenden Sie in den Objekten Zeiger auf Funktionen,
+      und initialisieren Sie diese in den Konstruktoren.}
+
+      Siehe \gitfile{hp}{20190114}{loesung-2g.c}.
+
+  \end{itemize}
+
+\end{document}
diff --git a/20190114/loesung-1.c b/20190114/loesung-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a277e7b514d05e3bffbb59cd09fc5f63a18e26a
--- /dev/null
+++ b/20190114/loesung-1.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+
+void foreach (int *a, void (*fun) (int x))
+{
+  for (int *p = a; *p >= 0; p++)
+    fun (*p);
+}
+
+void even_or_odd (int x)
+{
+  if (x % 2)
+    printf ("%d ist ungerade.\n", x);
+  else
+    printf ("%d ist gerade.\n", x);
+}
+
+int sum = 0;
+
+void add_up (int x)
+{
+  sum += x;
+}
+
+int main (void)
+{
+  int numbers[] = { 12, 17, 32, 1, 3, 16, 19, 18, -1 };
+  foreach (numbers, add_up);
+  printf  ("Summe: %d\n", sum);
+  return 0;
+}
diff --git a/20190114/loesung-2d-0f.c b/20190114/loesung-2d-0f.c
new file mode 100644
index 0000000000000000000000000000000000000000..04b2d3e8956f4790b3f2ffdf3a314994c640513e
--- /dev/null
+++ b/20190114/loesung-2d-0f.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct animal
+{
+  int type;
+  char *name;
+} animal;
+
+typedef struct with_wings
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct with_legs
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+int main (void)
+{
+  animal *a[2];
+
+  animal duck;
+  a[0] = &duck;
+  a[0]->type = WITH_WINGS;
+  a[0]->name = "duck";
+  ((with_wings *) a[0])->wings = 2;
+
+  animal cow;
+  a[1] = &cow;
+  a[1]->type = WITH_LEGS;
+  a[1]->name = "cow";
+  ((with_legs *) a[1])->legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->name,
+              ((with_legs *) a[i])-> legs);
+    else if (a[i]->type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->name,
+              ((with_wings *) a[i])-> wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->name);
+
+  return 0;
+}
diff --git a/20190114/loesung-2d-1.c b/20190114/loesung-2d-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..349523a7d99e33ba81094ffbc8907773b5a3a251
--- /dev/null
+++ b/20190114/loesung-2d-1.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct animal
+{
+  int type;
+  char *name;
+} animal;
+
+typedef struct with_wings
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct with_legs
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+int main (void)
+{
+  animal *a[2];
+
+  with_wings duck;
+  a[0] = (animal *) &duck;
+  a[0]->type = WITH_WINGS;
+  a[0]->name = "duck";
+  ((with_wings *) a[0])->wings = 2;
+
+  with_legs cow;
+  a[1] = (animal *) &cow;
+  a[1]->type = WITH_LEGS;
+  a[1]->name = "cow";
+  ((with_legs *) a[1])->legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->name,
+              ((with_legs *) a[i])-> legs);
+    else if (a[i]->type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->name,
+              ((with_wings *) a[i])-> wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->name);
+
+  return 0;
+}
diff --git a/20190114/loesung-2d-2.c b/20190114/loesung-2d-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..f831a75eda1f3e784c8e6c1f24a83d9d6b55ee6c
--- /dev/null
+++ b/20190114/loesung-2d-2.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct animal
+{
+  int type;
+  char *name;
+} animal;
+
+typedef struct with_wings
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct with_legs
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+int main (void)
+{
+  animal *a[2];
+
+  with_wings duck;
+  a[0] = (animal *) &duck;
+  duck.type = WITH_WINGS;
+  duck.name = "duck";
+  duck.wings = 2;
+
+  with_legs cow;
+  a[1] = (animal *) &cow;
+  cow.type = WITH_LEGS;
+  cow.name = "cow";
+  cow.legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->name,
+              ((with_legs *) a[i])-> legs);
+    else if (a[i]->type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->name,
+              ((with_wings *) a[i])-> wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->name);
+
+  return 0;
+}
diff --git a/20190114/loesung-2e.c b/20190114/loesung-2e.c
new file mode 100644
index 0000000000000000000000000000000000000000..b984d9253b9c379a88f0fc0ca130c88c3103f8f3
--- /dev/null
+++ b/20190114/loesung-2e.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct
+{
+  int type;
+  char *name;
+} base;
+
+typedef struct
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+typedef union
+{
+  base b;
+  with_wings w;
+  with_legs l;
+} animal;
+
+int main (void)
+{
+  animal *a[2];
+
+  animal duck;
+  a[0] = &duck;
+  duck.b.type = WITH_WINGS;
+  duck.b.name = "duck";
+  duck.w.wings = 2;
+
+  animal cow;
+  a[1] = &cow;
+  cow.b.type = WITH_LEGS;
+  cow.b.name = "cow";
+  cow.l.legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->b.type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->b.name,
+              a[i]->l.legs);
+    else if (a[i]->b.type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->b.name,
+              a[i]->w.wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->b.name);
+
+  return 0;
+}
diff --git a/20190114/loesung-2f.c b/20190114/loesung-2f.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b949e6365fc3839e6adc7661e0f8b4dd0c059df
--- /dev/null
+++ b/20190114/loesung-2f.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct
+{
+  int type;
+  char *name;
+} base;
+
+typedef struct
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+typedef union
+{
+  base b;
+  with_wings w;
+  with_legs l;
+} animal;
+
+animal *new_with_wings (char *name, int wings)
+{
+  animal *a = malloc (sizeof (with_wings));
+  a->b.type = WITH_WINGS;
+  a->b.name = name;
+  a->w.wings = wings;
+  return a;
+}
+
+animal *new_with_legs (char *name, int legs)
+{
+  animal *a = malloc (sizeof (with_legs));
+  a->b.type = WITH_LEGS;
+  a->b.name = name;
+  a->l.legs = legs;
+  return a;
+}
+
+int main (void)
+{
+  animal *a[2] = { new_with_wings ("duck", 2),
+                   new_with_legs ("cow", 4) };
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->b.type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->b.name,
+              a[i]->l.legs);
+    else if (a[i]->b.type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->b.name,
+              a[i]->w.wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->b.name);
+
+  return 0;
+}
diff --git a/20190114/loesung-2g.c b/20190114/loesung-2g.c
new file mode 100644
index 0000000000000000000000000000000000000000..b453a52dbe0ef27399255819808b3f6e562ba3ef
--- /dev/null
+++ b/20190114/loesung-2g.c
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+union animal;
+
+typedef struct
+{
+  int type;
+  char *name;
+  void (*print) (union animal *this);
+} base;
+
+typedef struct
+{
+  int type;
+  char *name;
+  void (*print) (union animal *this);
+  int wings;
+} with_wings;
+
+typedef struct
+{
+  int type;
+  char *name;
+  void (*print) (union animal *this);
+  int legs;
+} with_legs;
+
+typedef union animal
+{
+  base b;
+  with_wings w;
+  with_legs l;
+} animal;
+
+void print_with_wings (animal *this)
+{
+  printf ("A %s has %d wings.\n", this->b.name, this->w.wings);
+}
+
+void print_with_legs (animal *this)
+{
+  printf ("A %s has %d legs.\n", this->b.name, this->l.legs);
+}
+
+animal *new_with_wings (char *name, int wings)
+{
+  animal *a = malloc (sizeof (with_wings));
+  a->b.type = WITH_WINGS;
+  a->b.name = name;
+  a->b.print = print_with_wings;
+  a->w.wings = wings;
+  return a;
+}
+
+animal *new_with_legs (char *name, int legs)
+{
+  animal *a = malloc (sizeof (with_legs));
+  a->b.type = WITH_LEGS;
+  a->b.name = name;
+  a->b.print = print_with_legs;
+  a->l.legs = legs;
+  return a;
+}
+
+int main (void)
+{
+  animal *a[2] = { new_with_wings ("duck", 2),
+                   new_with_legs ("cow", 4) };
+  for (int i = 0; i < 2; i++)
+    a[i]->b.print (a[i]);
+  return 0;
+}
diff --git a/README.md b/README.md
index dc661ab9e520685db5999b566ac4e7154858dc06..e9ccc9b9b5f9cb007f1c904cb15de6cc4522f471 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,7 @@ Musterlösungen:
  * [10.12.2018: Trickprogrammierung, Thermometer-Baustein an I²C-Bus](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20181210/hp-musterloesung-20181210.pdf)
  * [17.12.2018: Fakultät, Lauflicht, Länge von Strings (Neuauflage)](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20181217/hp-musterloesung-20181217.pdf)
  * [07.01.2019: Speicherformate von Zahlen, Zeigerarithmetik](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20190107/hp-musterloesung-20190107.pdf)
+ * [14.01.2019: Iteratorfunktionen, Objektorientierte Tier-Datenbank](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20190114/hp-musterloesung-20190114.pdf)
 
 Tafelbilder:
 ------------
diff --git a/hp-slides-2018ws.pdf b/hp-slides-2018ws.pdf
index 41345a1d641bf19e544a9b2ef9ea50eed8f0d41a..163389e60ed480441b8a33fcebaa60288b5e063c 100644
Binary files a/hp-slides-2018ws.pdf and b/hp-slides-2018ws.pdf differ