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