diff --git a/20210204/aufgabe-1a.c b/20210204/aufgabe-1a.c new file mode 100644 index 0000000000000000000000000000000000000000..61b6e79400afbb8ac0609eb1b72c04b83a0fce41 --- /dev/null +++ b/20210204/aufgabe-1a.c @@ -0,0 +1,50 @@ +#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; + +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; +} diff --git a/20210204/aufgabe-1b.c b/20210204/aufgabe-1b.c new file mode 100644 index 0000000000000000000000000000000000000000..2cf3b56f4540f399d3761b0de929d80a1f1de611 --- /dev/null +++ b/20210204/aufgabe-1b.c @@ -0,0 +1,50 @@ +#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; + +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/20210204/aufgabe-2.c b/20210204/aufgabe-2.c new file mode 100644 index 0000000000000000000000000000000000000000..a1054f2b601850a402dccb6f4878437d1bb6909c --- /dev/null +++ b/20210204/aufgabe-2.c @@ -0,0 +1,22 @@ +#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 main (void) +{ + int numbers[] = { 12, 17, 32, 1, 3, 16, 19, 18, -1 }; + foreach (numbers, even_or_odd); + return 0; +} diff --git a/20210204/hello-gtk.png b/20210204/hello-gtk.png new file mode 120000 index 0000000000000000000000000000000000000000..cca99209d86683a9a3b0f70bbc149780bae10ba6 --- /dev/null +++ b/20210204/hello-gtk.png @@ -0,0 +1 @@ +../common/hello-gtk.png \ No newline at end of file diff --git a/20210204/hp-2020ws-p4.pdf b/20210204/hp-2020ws-p4.pdf new file mode 100644 index 0000000000000000000000000000000000000000..21bff505fd5fa6ca5d8913a694261a19ac6f55fd Binary files /dev/null and b/20210204/hp-2020ws-p4.pdf differ diff --git a/20210204/hp-2020ws-p4.tex b/20210204/hp-2020ws-p4.tex new file mode 100644 index 0000000000000000000000000000000000000000..c5eb30c709d75fa9925470f9ad9b8ac1eb6c3cb0 --- /dev/null +++ b/20210204/hp-2020ws-p4.tex @@ -0,0 +1,193 @@ +% hp-2020ws-p4.pdf - Labor Notes on Low-Level Programming +% Copyright (C) 2014, 2015, 2016, 2018, 2019, 2020, 2021 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: Versuch 4: Objektorientiertes Grafik-Programm + +\documentclass[a4paper]{article} + +\usepackage{pgscript} +\usepackage{multicol} +\usepackage{amsmath} +\usepackage{sfmath} + +\sloppy +%\pagestyle{empty} +\newcommand{\sep}{~$\cdot$~} +\newcommand{\mylicense}{CC-by-sa (Version 3.0) oder GNU GPL (Version 3 oder höher)} + +\begin{document} + + \makebox(0,0.005)[tl]{\includegraphics[scale=0.72]{logo-hochschule-bochum-cvh-text-v2.pdf}}\hfill + \makebox(0,0)[tr]{\includegraphics[scale=0.5]{logo-hochschule-bochum.pdf}} + \par\bigskip\bigskip + \begin{center} + \Large\textbf{Praktikumsversuch 4: Objektorientiertes Grafik-Programm} + \par\medskip + \normalsize Hardwarenahe Programmierung\sep + Wintersemester 2020/21\sep + Prof.~Dr.~Peter Gerwinski + \end{center} + + Aufgabe: Schreiben Sie ein GTK+-Programm, + mit dem man verschiedene Objekte (z.\,B.\ Rechtecke, Kreise, Dreiecke) + in eine Grafik einfügen und nachträglich verändern kann + (z.\,B.\ Position, Größe, Farbe). + + (Beispiel: Ich füge zunächst zwei Rechtecke und einen Kreis in eine Grafik ein, + wähle anschließend das erste Rechteck aus und ändere dessen Farbe.) + + \bigskip + + Hinweise: + \vspace*{-\medskipamount} + + \begin{itemize} + \item + Das Beispielprogramm \gitfile{hp}{2020ws/20210128}{objects-9.c} zeigt, + wie man in C verschiedenartige Objekte + in einem Array von Zeigern verwaltet. + \item + Das Beispielprogramm \gitfile{hp}{2020ws/script}{gtk-6.c} zeigt, + wie man mit Hilfe der GUI-Bibliothek GTK+ + verschiedene Objekte in ein Fenster zeichnet. + \item + Das Beispielprogramm \gitfile{hp}{2020ws/script}{gtk-7.c} zeigt, + wie man in der GUI-Bibliothek GTK+ + Tastatur- und Maus-Eingaben entgegennimmt und verarbeitet. + \item + Das Auswählen eines bereits vorhandenen Objekts geht am einfachsten + mittels Tastatur-Eingaben (z.\,B.\ Ziffer 1 für das erste Objekt usw.). + Auswahl mit der Maus ist auch möglich, aber schwieriger. + \item + Mit Hilfe der Funktion \lstinline{gtk_widget_queue_draw()} + teilen Sie GTK+ mit, daß Sie ein \lstinline{GtkWidget} + neu zeichnen lassen möchten. + \item + Das Compilieren eines GTK+-Programms + (z.\,B.\ \gitfile{hp}{2020ws/script}{gtk-7.c}) geschieht wie folgt: + \begin{lstlisting}[style=cmd,gobble=8] + gcc $(pkg-config --cflags gtk+-3.0) -Wall -O gtk-7.c \ + $(pkg-config --libs gtk+-3.0) -o gtk-7 + \end{lstlisting} + (Den Backslash am Ende der ersten Zeile entfällt, + wenn Sie den ganzen Befehl in eine einzige Zeile schreiben.) + \end{itemize} + + \bigskip + \textbf{GTK+ unter GNU/Linux} + \begin{itemize} + \item + Installieren Sie das Entwickler-Paket für GTK+-3,\\ + z.\,B.\ unter Debian GNU/Linux und darauf basierenden Systemen: + \begin{lstlisting}[style=cmd,gobble=8] + apt-get install libgtk-3-dev + \end{lstlisting} + \end{itemize} + + \bigskip + \goodbreak + \textbf{GTK+ unter MacOS X} + \begin{itemize} + \item + Zuerst den Paketmanager "`Homebrew"' installieren: + \begin{lstlisting}[style=cmd,gobble=8] + ruby -e "$(curl -fsSL https://raw.githubusercontent.com/ + Homebrew/install/2020ws/install)" + \end{lstlisting} + (Die URL nicht trennen, sondern in einer Zeile schreiben.) + \item + Danach mit Hilfe von \lstinline[style=cmd]{brew} GTK+ installieren: + \begin{lstlisting}[style=cmd,gobble=8] + brew install gtk+3 + \end{lstlisting} + \end{itemize} + + \bigskip + \goodbreak + \textbf{GTK+ unter Microsoft Windows: Cygwin} + \begin{itemize} + \item + Im Cygwin-Setup-Programm die Pakete \file{libgtk3-devel}, + \file{xorg-server} und \file{dbus-x11} installieren. + \item + Bevor Sie GTK+-Programme starten können, + müssen Sie einmalig den X-Server starten: + \begin{lstlisting}[style=cmd,gobble=8] + XWin -multiwindow & + \end{lstlisting} + \item + Bevor Sie GTK+-Programme starten können, + müssen Sie einmalig pro Shell-Sitzung\\ + die \lstinline[style=cmd]{DISPLAY}-Variable setzen: + \begin{lstlisting}[style=cmd,gobble=8] + export DISPLAY=:0.0 + \end{lstlisting} + \end{itemize} + + \bigskip + \goodbreak + \textbf{GTK+ unter Microsoft Windows: MinGW} + \begin{itemize} + \item + Installieren Sie \file{MSYS2} (Installer). + \item + Installieren Sie von der MinGW-Shell aus GTK+ + und weitere Entwicklungswerkzeuge: + \begin{lstlisting}[style=cmd,gobble=8] + pacman -S mingw-w64-x86_64-gcc + pacman -S mingw-w64-x86_64-gtk3 + pacman -S mingw-w64-x86_64-pkg-config + \end{lstlisting} + \item + Falls nötig, ergänzen Sie in der MinGW-Shell + den Pfad zu den neu installierten Programmen: + \begin{lstlisting}[style=cmd,gobble=8] + export PATH=$PATH:/mingw64/bin + \end{lstlisting} + \end{itemize} + + \bigskip + + \strut\hfill\emph{Viel Erfolg!} + + \vfill + + \begingroup + + \small + + \setlength{\leftskip}{3cm} + + Stand: 4.\ Februar 2021 + +% Soweit nicht anders angegeben:\\ + Copyright \copyright\ 2014, 2015, 2016, 2018, 2019, 2020, 2021\quad Peter Gerwinski\\ + Lizenz: \mylicense + + Sie können diese Praktikumsunterlagen einschließlich \LaTeX-Quelltext +% und Beispielprogramme\\ + herunterladen unter:\\ + \url{https://gitlab.cvh-server.de/pgerwinski/hp} + + \endgroup + +\end{document} diff --git a/20210204/hp-20210204.pdf b/20210204/hp-20210204.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f45a2f65a35783420b9a5467d44682759293c739 Binary files /dev/null and b/20210204/hp-20210204.pdf differ diff --git a/20210204/hp-20210204.tex b/20210204/hp-20210204.tex new file mode 100644 index 0000000000000000000000000000000000000000..ecfb230808f6d7dc05704a8cc72c54c95ef36ff9 --- /dev/null +++ b/20210204/hp-20210204.tex @@ -0,0 +1,1109 @@ +% hp-20210204.pdf - Lecture Slides on Low-Level Programming +% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 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: Objektorientierte Programmierung: virtuelle Methoden + +\documentclass[10pt,t]{beamer} + +\usepackage{pgslides} +\usepackage{rotating} +\usepackage{tikz} + +\title{Hardwarenahe Programmierung} +\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski} +\date{4.\ Februar 2021} + +\begin{document} + +\maketitleframe + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Algorithmen} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\textbf{6}] \textbf{Objektorientierte Programmierung} + \begin{itemize} + \color{medgreen} + \item[6.0] Dynamische Speicherverwaltung + \item[6.1] Konzepte und Ziele + \item[6.2] Beispiel: Zahlen und Buchstaben + \item[6.3] Unions + \color{red} + \item[6.4] Virtuelle Methoden + \item[6.5] Beispiel: Graphische Benutzeroberfläche (GUI) + \item[6.6] Ausblick: C++ + \end{itemize} + \item[\textbf{7}] \textbf{Datenstrukturen} + \vspace*{-1cm} + \end{itemize} + +\end{frame} + +\setcounter{section}{5} +\section{Objektorientierte Programmierung} + +\addtocounter{subsection}{-1} +\subsection{Dynamische Speicherverwaltung} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \begin{itemize} + \item + Array: feste Anzahl von Elementen desselben Typs (z.\,B.\ 3 ganze Zahlen) + \item + Dynamisches Array: variable Anzahl von Elementen desselben Typs + \end{itemize} + + \bigskip + + \begin{lstlisting} + char *name[] = { "Anna", "Berthold", "Caesar" }; + + ... + + name[3] = "Dieter"; + \end{lstlisting} + + \begin{picture}(0,0) + \color{red} + \put(0,0){\line(3,1){3.5}} + \put(0,1){\line(3,-1){3.5}} + \end{picture} + +\end{frame} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \bigskip + + \begin{lstlisting} + #include <stdlib.h> + + ... + + char **name = malloc (3 * sizeof (char *)); + /* Speicherplatz für 3 Zeiger anfordern */ + + ... + + free (name); + /* Speicherplatz freigeben */ + + \end{lstlisting} + +\end{frame} + +\subsection{Konzepte und Ziele} + +\begin{frame} + + \showsection + \showsubsection + + \begin{itemize} + \item +% Array: feste Anzahl von Elementen desselben Typs (z.\,B.\ 3 ganze Zahlen) + Array: Elemente desselben Typs (z.\,B.\ 3 ganze Zahlen) +% \item +% Dynamisches Array: variable Anzahl von Elementen desselben Typs + \item + Problem: Elemente unterschiedlichen Typs + \item + Lösung: den Typ des Elements zusätzlich speichern \textarrow\ \newterm{Objekt} + \item + Problem: Die Elemente sind unterschiedlich groß (Speicherplatz). + \item + Lösung: Im Array nicht die Objekte selbst speichern, sondern Zeiger darauf. + \end{itemize} + \begin{itemize} + \item + Funktionen, die mit dem Objekt arbeiten: \newterm{Methoden} + \begin{onlyenv}<1> + \item + Was die Funktion bewirkt,\\ + hängt vom Typ des Objekts ab + \item + Realisierung über endlose \lstinline{if}-Ketten + \end{onlyenv} + \begin{onlyenv}<2> + \item + Was die Funktion bewirkt + \begin{picture}(0,0) + \color{red} + \put(-4.00,-0.05){\tikz{\draw[thick](0,0.25)--(3.75,-0.05);% + \draw[thick](-0.1,-0.05)--(3.75,0.3);}} + \end{picture}% + Welche Funktion aufgerufen wird,\\ + hängt vom Typ des Objekts ab: \newterm{virtuelle Methode} + \item + Realisierung über endlose \lstinline{if}-Ketten% + \begin{picture}(0,0) + \color{red} + \put(-2.75,-0.05){\tikz{\draw[thick](0,0.25)--(2.5,-0.05);% + \draw[thick](-0.1,-0.05)--(2.5,0.3);}} + \put(1.5,-1.1){\begin{rotate}{7}\large\bf\textarrow\ + kommt gleich +% nächste Woche + \end{rotate}} + \end{picture} + Zeiger, die im Objekt gespeichert sind\\ + (Genaugenommen: Tabelle von Zeigern) + \end{onlyenv} + \end{itemize} + +\end{frame} + +\begin{frame} + + \showsection + \showsubsection + + \begin{itemize} + \item + Problem: Elemente unterschiedlichen Typs + \item + Lösung: den Typ des Elements zusätzlich speichern \textarrow\ \newterm{Objekt} + \item + \newterm{Methoden\/} und \newterm{virtuelle Methoden} + \end{itemize} + + \begin{itemize} + \item + Zeiger auf verschiedene Strukturen\\ + mit einem gemeinsamen Anteil von Datenfeldern\\ + \textarrow\ "`verwandte"' \newterm{Objekte}, \newterm{Klassenhierarchie} von Objekten + \item + Struktur, die \emph{nur\/} den gemeinsamen Anteil enthält\\ + \textarrow\ "`Vorfahr"', \newterm{Basisklasse}, \newterm{Vererbung} + \item +% Explizite Typumwandlung eines Zeigers auf die Basisklasse\\ +% in einen Zeiger auf die \newterm{abgeleitete Klasse}\\ +% \textarrow\ Man kann ein Array unterschiedlicher Objekte\\ +% \strut\phantom{\textarrow} in einer Schleife abarbeiten.\\ + Zeiger auf die Basisklasse dürfen auf Objekte\\ + der \newterm{abgeleiteten Klasse} zeigen\\ + \textarrow\ \newterm{Polymorphie} + \end{itemize} + +\end{frame} + +\subsection{Beispiel: Zahlen und Buchstaben} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \begin{center} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + } t_base;¿ + \end{lstlisting} + \end{minipage}\\[0.5cm] + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + int content; + } t_integer;¿ + \end{lstlisting} + \end{minipage} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + char *content; + } t_string;¿ + \end{lstlisting} + \end{minipage} + \end{center} + +\end{frame} + +\begin{frame}[fragile] + \begin{center} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + } t_base;¿ + \end{lstlisting} + \end{minipage}\\[0.5cm] + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + int content; + } t_integer;¿ + \end{lstlisting} + \end{minipage} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + char *content; + } t_string;¿ + \end{lstlisting} + \end{minipage}\\[0.7cm] + \begin{onlyenv}<1> + \begin{minipage}{8cm} + \begin{lstlisting}[gobble=10] + ¡t_integer i = { 1, 42 }; + t_string s = { 2, "Hello, world!" }; + + t_base *object[] = { (t_base *) &i, (t_base *) &s };¿ + \end{lstlisting} + \end{minipage}% + \begin{picture}(0,0) + \color{red} + \put(-5.4,-0.8){\mbox{$\underbrace{\rule{1.45cm}{0pt}}_{\shortstack{\strut explizite\\Typumwandlung}}$}} + \end{picture} + \end{onlyenv} +% \begin{onlyenv}<2> +% \begin{minipage}{5cm} +% \begin{lstlisting}[gobble=10] +% ¡typedef union +% { +% t_base base; +% t_integer integer; +% t_string string; +% } t_object;¿ +% \end{lstlisting} +% \end{minipage} +% \end{onlyenv} + \end{center} + +\end{frame} + +\subsection{Unions} + +\begin{frame}[fragile] + + \showsubsection + + Variable teilen sich denselben Speicherplatz. + + \medskip + + \begin{minipage}[t]{3.7cm} + \begin{lstlisting}[gobble=6] + ¡typedef union + { + int8_t i; + uint8_t u; + } num8_t;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{4.5cm} + \begin{lstlisting}[gobble=6] + ¡int main (void) + { + num8_t test; + test.i = -1; + printf ("%d\n", test.u); + return 0; + }¿ + \end{lstlisting} + \end{minipage} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Variable teilen sich denselben Speicherplatz. + + \medskip + + \begin{minipage}[t]{3.7cm} + \begin{lstlisting}[gobble=6] + ¡typedef union + { + char s[8]; + uint64_t x; + } num_char_t;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{4.5cm} + \begin{lstlisting}[gobble=6] + ¡int main (void) + { + num_char_t test = { "Hello!" }; + printf ("%lx\n", test.x); + return 0; + }¿ + \end{lstlisting} + \end{minipage} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Variable teilen sich denselben Speicherplatz. + + \medskip + + \begin{minipage}[t]{3.7cm} + \begin{lstlisting}[gobble=6] + ¡typedef union + { + t_base base; + t_integer integer; + t_string string; + } t_object;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{3.0cm} + \begin{lstlisting}[gobble=6] + + ¡typedef struct + { + int type; + } t_base;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{3.0cm} + \begin{lstlisting}[gobble=6] + + ¡typedef struct + { + int type; + int content; + } t_integer;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{3.0cm} + \begin{lstlisting}[gobble=6] + + ¡typedef struct + { + int type; + char *content; + } t_string;¿ + \end{lstlisting} + \end{minipage} + + \bigskip + + \begin{center} + \begin{minipage}{8.5cm} + \begin{lstlisting}[gobble=8] + ¡if (this->base.type == T_INTEGER) + printf ("Integer: %d\n", this->integer.content); + else if (this->base.type == T_STRING) + printf ("String: \"%s\"\n", this->string.content);¿ + \end{lstlisting} + \end{minipage} + \end{center} + +\end{frame} + +\subsection{Virtuelle Methoden} + +\begin{frame}[fragile] + \showsubsection + + \begin{lstlisting} + void print_object (t_object *this) + { + if (this->base.type == T_INTEGER) + printf ("Integer: %d\n", this->integer.content); + else if (this->base.type == T_STRING) + printf ("String: \"%s\"\n", this->string.content); + } + \end{lstlisting} + + \begin{picture}(0,0) + \color{red} + \put(9,1.7){\shortstack[l]{if-Kette:\\\strut wird unübersichtlich}} + \put(1,-2){\mbox{\textarrow}} + \put(0,-3){\mbox{Zeiger auf Funktionen}} + \end{picture} + + \begin{lstlisting}[xleftmargin=4cm] + void print_integer (t_object *this) + { + printf ("Integer: %d\n", this->integer.content); + } + + void print_string (t_object *this) + { + printf ("String: \"%s\"\n", this->string.content); + } + \end{lstlisting} + +\end{frame} + +\begin{frame}[fragile] + \showsubsection + + Zeiger auf Funktionen + + \medskip + + \begin{lstlisting} + void (* print) (t_object *this); + \end{lstlisting} + \begin{picture}(0,1.2)(0,-0.9) + \color{red} + \put(0.95,0.3){\mbox{$\underbrace{\rule{1cm}{0pt}}$}} + \put(0.2,-0.7){\shortstack{das, worauf print zeigt,\\ist eine Funktion}} + \end{picture} + + \begin{itemize} + \item + Objekt enthält Zeiger auf Funktion + \begin{onlyenv}<1> + \medskip + \begin{lstlisting}[gobble=10] + typedef struct + { + void (* print) (union t_object *this); + int content; + } t_integer; + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<2-> + \vspace*{-3.5cm} % Why doesn't a picture environment work here??? :-( + \begin{lstlisting}[gobble=10,xleftmargin=5.5cm] + typedef struct + { + void (* print) (union t_object *this); + int content; + } t_integer; + \end{lstlisting} + \vspace*{0.85cm} + \bigskip + \smallskip + \end{onlyenv} + \pause + \item + Konstruktor initialisiert diesen Zeiger + \begin{onlyenv}<2> + \medskip + \begin{lstlisting}[gobble=10] + t_object *new_integer (int i) + { + t_object *p = malloc (sizeof (t_integer)); + p->integer.print = print_integer; + p->integer.content = i; + return p; + } + \end{lstlisting} + \vspace*{-2cm} + \end{onlyenv} + \pause + \item + Aufruf: "`automatisch"' die richtige Funktion + \begin{onlyenv}<3> + \medskip + \begin{lstlisting}[gobble=10] + for (int i = 0; object[i]; i++) + object[i]->base.print (object[i]); + \end{lstlisting} + \end{onlyenv} + \pause + \medskip + \item + in größeren Projekten:\\ + Objekt enthält Zeiger auf Tabelle von Funktionen + \end{itemize} +\end{frame} + +\subsection{Beispiel: Graphische Benutzeroberfläche (GUI)} + +\begin{frame}[fragile] + + \showsubsection + + \scriptsize + \begin{lstlisting} + #include <gtk/gtk.h> + + int main (int argc, char **argv) + { + gtk_init (&argc, &argv); + GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Hello"); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 10); + GtkWidget *label = gtk_label_new ("Hello, world!"); + gtk_container_add (GTK_CONTAINER (vbox), label); + GtkWidget *button = gtk_button_new_with_label ("Quit"); + g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL); + gtk_container_add (GTK_CONTAINER (vbox), button); + gtk_widget_show (button); + gtk_widget_show (label); + gtk_widget_show (vbox); + gtk_widget_show (window); + gtk_main (); + return 0; + } + \end{lstlisting} + + \vspace*{-6cm}\strut\hfill + \includegraphics[scale=0.85]{hello-gtk.png}\\[2cm] + \begin{flushright} + \normalsize\bf Praktikumsversuch:\\ + Objektorientiertes Zeichenprogramm + \end{flushright} + +\end{frame} + +\subsection{Ausblick: C++} + +\begin{frame}[fragile] + \showsubsection + + \begin{center} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + void (* print) (union t_object *this); + } t_base;¿ + \end{lstlisting} + \end{minipage}\\[0.5cm] + \begin{minipage}{5.5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + void (* print) (...); + int content; + } t_integer;¿ + \end{lstlisting} + \end{minipage} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + void (* print) (union t_object *this); + char *content; + } t_string;¿ + \end{lstlisting} + \end{minipage} + \end{center} + +\end{frame} + +\begin{frame}[fragile] + \showsubsection + + \begin{center} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡struct TBase + { + virtual void print (void); + };¿ + \end{lstlisting} + \end{minipage}\\[0.5cm] + \begin{minipage}{5.5cm} + \begin{lstlisting}[gobble=8] + ¡struct TInteger: public TBase + { + virtual void print (void); + int content; + };¿ + \end{lstlisting} + \end{minipage} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡struct TString: public TBase + { + virtual void print (void); + char *content; + };¿ + \end{lstlisting} + \end{minipage} + \end{center} + +\end{frame} + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Algorithmen} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\textbf{6}] \textbf{Objektorientierte Programmierung} + \begin{itemize} + \item[6.0] Dynamische Speicherverwaltung + \item[6.1] Konzepte und Ziele + \item[6.2] Beispiel: Zahlen und Buchstaben + \item[6.3] Unions + \color{medgreen} + \item[6.4] Virtuelle Methoden + \item[6.5] Beispiel: Graphische Benutzeroberfläche (GUI) + \item[6.6] Ausblick: C++ + \end{itemize} + \item[\textbf{7}] \textbf{Datenstrukturen} + \vspace*{-1cm} + \end{itemize} + +\end{frame} + +\section{Datenstrukturen} +\subsection{Stack und FIFO} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \begin{minipage}{0.48\textwidth} + Im letzten Praktikumsversuch: + \begin{itemize} + \item + Array nur zum Teil benutzt + \item + Variable speichert genutzte Länge + \item + Elemente hinten anfügen\\ + oder entfernen + \arrowitem + Stack\\ + \strut + \end{itemize} + \bigskip + \begin{itemize} + \item + hinten anfügen/entfernen: $\mathcal{O}(1)$\hspace*{-1cm} + \item + vorne oder in der Mitte einfügen/entfernen: $\mathcal{O}(n)$ + \end{itemize} + \end{minipage}\hfill + \begin{minipage}{0.52\textwidth} + Auch möglich: + \begin{itemize} + \item + Array nur zum Teil benutzt + \item + 2 Variable speichern\\genutzte Länge (ringförmig) + \item + Elemente hinten anfügen\\ + oder vorne entfernen + \arrowitem + FIFO + \end{itemize} + \bigskip + \begin{itemize} + \item + vorne oder hinten\\ + anfügen oder entfernen: $\mathcal{O}(1)$ + \item + in der Mitte einfügen/entfernen: $\mathcal{O}(n)$ + \end{itemize} + \end{minipage}\hspace*{-1.5mm} + +\end{frame} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \bigskip + + \begin{minipage}[b]{6cm} + \begin{center} + "`First In -- First Out"' + + \bigskip + + \begin{picture}(6,4) + \thicklines + \color{structure} + \put(0.5,0){\line(1,0){5}} + + \put(3.5,0){\only<1-5>{\line(0,1){1}}} + \put(4.5,0){\only<1-4>{\line(0,1){1}}} + \put(3.5,1){\only<1-4>{\line(1,0){1}}} + \put(4.0,0.5){\only<1-4>{\makebox(0,0){\lstinline{3}}}} + \put(3.0,1.5){\only<1>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(3.0,1.5){\only<1>{\makebox(0,0)[b]{\lstinline{push (3)}}}} + + \put(2.5,0){\only<2-6>{\line(0,1){1}}} + \put(2.5,1){\only<2-5>{\line(1,0){1}}} + \put(3.0,0.5){\only<2-5>{\makebox(0,0){\lstinline{7}}}} + \put(2.0,1.5){\only<2>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(2.0,1.5){\only<2>{\makebox(0,0)[b]{\lstinline{push (7)}}}} + + \put(1.5,0){\only<3-6>{\line(0,1){1}}} + \put(1.5,1){\only<3-6>{\line(1,0){1}}} + \put(2.0,0.5){\only<3-6>{\makebox(0,0){\lstinline{137}}}} + \put(1.0,1.5){\only<3>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(1.0,1.5){\only<3>{\makebox(0,0)[b]{\lstinline{push (137)}}}} + + \put(4.55,1.05){\only<4>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(5.00,1.60){\only<4>{\makebox(0,0)[b]{\lstinline{pop ()}: 3}}} + + \put(3.55,1.05){\only<5>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(4.00,1.60){\only<5>{\makebox(0,0)[b]{\lstinline{pop ()}: 7}}} + + \put(2.55,1.05){\only<6>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(3.00,1.60){\only<6>{\makebox(0,0)[b]{\lstinline{pop ()}: 137}}} + \end{picture} + + \bigskip + + FIFO = Queue = Reihe + \end{center} + \end{minipage}\hfill + \begin{minipage}[b]{6cm} + \begin{center} + "`Last In -- First Out"' + + \bigskip + + \begin{picture}(6,4) + \thicklines + \color{structure} + \put(1.5,0){\line(1,0){3}} + + \put(2.5,0){\line(0,1){1}} + \put(3.5,0){\line(0,1){1}} + \put(2.5,1){\line(1,0){1}} + \put(3.0,0.5){\makebox(0,0){\lstinline{3}}} + \put(2.0,1.5){\only<1>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(2.0,1.5){\only<1>{\makebox(0,0)[b]{\lstinline{push (3)}}}} + + \put(2.5,1){\only<2-5>{\line(0,1){1}}} + \put(3.5,1){\only<2-5>{\line(0,1){1}}} + \put(2.5,2){\only<2-5>{\line(1,0){1}}} + \put(3.0,1.5){\only<2-5>{\makebox(0,0){\lstinline{7}}}} + \put(2.0,2.5){\only<2>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(2.0,2.5){\only<2>{\makebox(0,0)[b]{\lstinline{push (7)}}}} + + \put(2.5,2){\only<3-4>{\line(0,1){1}}} + \put(3.5,2){\only<3-4>{\line(0,1){1}}} + \put(2.5,3){\only<3-4>{\line(1,0){1}}} + \put(3.0,2.5){\only<3-4>{\makebox(0,0){\lstinline{137}}}} + \put(2.0,3.5){\only<3>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(2.0,3.5){\only<3>{\makebox(0,0)[b]{\lstinline{push (137)}}}} + + \put(3.55,3.05){\only<4>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(4.00,3.60){\only<4>{\makebox(0,0)[b]{\lstinline{pop ()}: 137}}} + + \put(3.55,2.05){\only<5>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(4.00,2.60){\only<5>{\makebox(0,0)[b]{\lstinline{pop ()}: 7}}} + + \put(3.55,1.05){\only<6>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(4.00,1.60){\only<6>{\makebox(0,0)[b]{\lstinline{pop ()}: 3}}} + \end{picture} + + \bigskip + + LIFO = Stack = Stapel + \end{center} + \end{minipage} + +% +% \dots + +\end{frame} + +\begin{frame} + + \showsection + \showsubsection + + \bigskip + + \begin{minipage}[t]{6cm} + Array (Stack, FIFO):\\ + in der Mitte einfügen + \begin{center} + \begin{picture}(6,3.8) + \thicklines + \color{structure} + \put(1.5,0){\line(1,0){3}} + + \put(2.5,0){\line(0,1){3}} + \put(3.5,0){\line(0,1){3}} + \put(2.5,1){\line(1,0){1}} + \put(3.0,0.5){\makebox(0,0){\lstinline{3}}} + \put(2.5,1){\line(1,0){1}} + \put(3.0,1.5){\makebox(0,0){\lstinline{7}}} + \put(2.5,2){\line(1,0){1}} + \put(3.0,2.5){\makebox(0,0){\lstinline{137}}} + \put(2.5,3){\line(1,0){1}} + + \put(1.5,1.5){\makebox(0,0)[b]{\lstinline{push (5)}}} + \put(1.5,1.45){\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.95,-0.45);}}} + + \put(3.55,2.5){\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)..controls(0.5,0.45)..(0,0.9);}}} + \put(3.55,1.5){\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)..controls(0.5,0.45)..(0,0.9);}}} + + \pause + \color{red} + \put(4.1,3.0){\makebox(0,0)[l]{\textbf{1.}}} + \put(4.1,2.0){\makebox(0,0)[l]{\textbf{2.}}} + \put(1.5,1.9){\makebox(0,0)[b]{\textbf{3.}}} + + \pause + \put(6.0,1.5){\makebox(0,0)[tl]{$\mathcal{O}(n)$}} + \put(5.95,1.45){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-1.3,0.4);}}} + \put(5.95,1.49){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-1.3,1.1);}}} + \end{picture} + \end{center} + \end{minipage}\pause\hfill + \begin{minipage}[t]{5cm} + In Array (Stack, FIFO) \dots + \begin{itemize} + \item + einfügen: $\mathcal{O}(n)$ + \item + suchen: $\mathcal{O}(n)$ + \item + geschickt suchen: $\mathcal{O}(\log n)$ + \item + beim Einfügen sortieren:\\ + $\mathcal{O}(n \log n)$ \hspace*{-1.8cm}\tikz{\draw[red](-1.8,0)--(0,0.2);\draw[red](-1.8,0.2)--(0,0);} + $\mathcal{O}(n^2)$ + \end{itemize} + \end{minipage} + +\end{frame} + +\subsection{Verkettete Listen} + +\begin{frame} + + \showsection + \showsubsection + + \begin{tikzpicture} + \color{structure} + \node(first) at (0,0.5) {first}; + \node[shape=rectangle,draw,line width=1pt](3) at (1,2) {3}; + \node[shape=rectangle,draw,line width=1pt](5) at (2,1) {5}; + \node[shape=rectangle,draw,line width=1pt](7) at (3,2) {7}; + \node[shape=rectangle,draw,line width=1pt](137) at (5,2) {137}; + \node(NULL) at (7,2) {NULL}; + \draw[-latex](first)--(3); + \only<1>{\draw[-latex](3)--(7);} + \only<2>{\draw[-latex](3) to[out=0] (5);} + \only<2>{\draw[-latex](5) to[in=180] (7);} + \draw[-latex](7)--(137); + \draw[-latex](137)--(NULL); + \end{tikzpicture} + \begin{itemize} + \item + Jeder Datensatz enthält einen Zeiger auf das nächste Element. + \item + Beim letzten Element zeigt der Zeiger auf \lstinline{NULL}. + \item + Eine Variable zeigt auf das erste Element. + \item + Wenn die Liste leer ist, zeigt die Variable auf \lstinline{NULL}. + \arrowitem + (einfach) \textbf{verkettete Liste} + \end{itemize} + +\end{frame} + +\begin{frame} + + \showsection + \showsubsection + + \begin{minipage}[t]{5cm} + In Array (Stack, FIFO) \dots + \begin{itemize} + \item + in der Mitte einfügen: $\mathcal{O}(n)$ + \item + wahlfreier Zugriff: $\mathcal{O}(1)$ + \item + suchen: $\mathcal{O}(n)$ + \item + geschickt suchen: $\mathcal{O}(\log n)$ + \item + beim Einfügen sortieren:\\ + $\mathcal{O}(n \log n)$ \hspace*{-1.8cm}\tikz{\draw[red](-1.8,0)--(0,0.2);\draw[red](-1.8,0.2)--(0,0);} + $\mathcal{O}(n^2)$ + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{6cm} + In (einfach) verkettete/r Liste \dots + \begin{itemize} + \item + in der Mitte einfügen: $\mathcal{O}(1)$ + \item + wahlfreier Zugriff: $\mathcal{O}(n)$ + \item + suchen: $\mathcal{O}(n)$ + \item + geschickt \hspace*{-1.7cm}\tikz{\draw[red](-1.7,0)--(0,0.2);\draw[red](-1.7,0.2)--(0,0);} + suchen: {\color{red}$\mathcal{O}(n)$} + \item + beim Einfügen sortieren: + $\mathcal{O}(n \log n)$ \hspace*{-1.8cm}\tikz{\draw[red](-1.8,0)--(0,0.2);\draw[red](-1.8,0.2)--(0,0);} + $\mathcal{O}(n^2)$ + \end{itemize} + \end{minipage} + \pause + \medskip + \begin{center} + \begin{minipage}[t]{6cm} + In (ausbalancierten) Bäumen \dots + \begin{itemize} + \item + in der Mitte einfügen: $\mathcal{O}(\log n)$ + \item + wahlfreier Zugriff: $\mathcal{O}(\log n)$ + \item + suchen: $\mathcal{O}(\log n)$ + \item + beim Einfügen sortieren: + $\mathcal{O}(n \log n)$ + \end{itemize} + \end{minipage} + \end{center} + \vspace*{-1cm} + +\end{frame} + +\subsection{Bäume} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \begin{minipage}[t]{5cm} + \vspace*{-6cm} + \begin{lstlisting}[gobble=6] + ¡typedef struct node + { + int content; + struct node *left, *right; + } node;¿ + \end{lstlisting} + \bigskip + \bigskip + \begin{onlyenv}<6-> + \begin{itemize} + \item + Einfügen: rekursiv, $\mathcal{O}(\log n)$ + \item + Suchen: rekursiv, $\mathcal{O}(\log n)$ + \item + beim Einfügen sortieren:\\ + rekursiv, $\mathcal{O}(n\log n)$ + \begin{onlyenv}<7-> + \smallskip + \item + {\color{red} + \emph{Worst Case\/}: $\mathcal{O}(n^2)$\\ + vorher bereits sortiert}\\ + \textarrow\ balancierte Bäume\\ + \hspace*{2.15em}Anwendung: Datenbanken\hspace*{-2cm} + \end{onlyenv} + \end{itemize} + \vspace*{-1cm} + \end{onlyenv} + \end{minipage}\hfill + \begin{minipage}[t]{7cm} + \begin{center} + \begin{tikzpicture} + \color{structure} + \node(root) at (0,0) {\lstinline{node *root;}}; + \begin{onlyenv}<2> + \node(3) at (-2,-3) {\lstinline{NULL}}; + \node(137) at (2,-3) {\lstinline{NULL}}; + \end{onlyenv} + \begin{onlyenv}<2-> + \node[shape=rectangle,draw,line width=1pt](7) at (0,-1.5) {7}; + \draw[-latex](root)--(7); + \draw[-latex](7)--(3); + \draw[-latex](7)--(137); + \end{onlyenv} + \begin{onlyenv}<3> + \node(3) at (-2,-3) {\lstinline{NULL}}; + \end{onlyenv} + \begin{onlyenv}<3-> + \node[shape=rectangle,draw,line width=1pt](137) at (2,-3) {137}; + \node(137_left) at (1,-4.5) {\lstinline{NULL}}; + \node(137_right) at (3,-4.5) {\lstinline{NULL}}; + \draw[-latex](137)--(137_left); + \draw[-latex](137)--(137_right); + \end{onlyenv} + \begin{onlyenv}<4> + \node(5) at (-1,-4.5) {\lstinline{NULL}}; + \end{onlyenv} + \begin{onlyenv}<4-> + \node[shape=rectangle,draw,line width=1pt](3) at (-2,-3) {3}; + \node(3_left) at (-3,-4.5) {\lstinline{NULL}}; + \draw[-latex](3)--(3_left); + \draw[-latex](3)--(5); + \end{onlyenv} + \begin{onlyenv}<5-> + \node[shape=rectangle,draw,line width=1pt](5) at (-1,-4.5) {5}; + \node(5_left) at (-2,-6) {\lstinline{NULL}}; + \node(5_right) at (0,-6) {\lstinline{NULL}}; + \draw[-latex](5)--(5_left); + \draw[-latex](5)--(5_right); + \end{onlyenv} + \end{tikzpicture} + \end{center} + \end{minipage} + +\end{frame} + +\end{document} diff --git a/20210204/hp-musterloesung-20210204.pdf b/20210204/hp-musterloesung-20210204.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2e8c876bf111098365da8cf9547fdf3296c55cc6 Binary files /dev/null and b/20210204/hp-musterloesung-20210204.pdf differ diff --git a/20210204/hp-musterloesung-20210204.tex b/20210204/hp-musterloesung-20210204.tex new file mode 100644 index 0000000000000000000000000000000000000000..458400cdc557311597c6efaaee6783d61491971e --- /dev/null +++ b/20210204/hp-musterloesung-20210204.tex @@ -0,0 +1,629 @@ +% hp-musterloesung-20210204.pdf - Solutions to the Exercises on Low-Level Programming +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 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: Objektorientierte Tier-Datenbank (Neuauflage), Iterationsfunktionen, dynamisches Bit-Array + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + + \section*{Hardwarenahe Programmierung\\ + Musterlösung zu den Übungsaufgaben -- 4.\ Februar 2021} + + \exercise{Objektorientierte Tier-Datenbank (Neuauflage)} + + Diese Aufgabe ist eine Neuauflage von Aufgabe 3 der + Übung vom 28.\ Januar 2021,\\ + ergänzt um die Teilaufgaben (e) bis (g). + + \medskip + + Das auf der nächsten Seite dargestellte Programm + (Datei: \gitfile{hp}{2020ws/20210204}{aufgabe-1a.c}) + soll Daten von Tieren verwalten. + + Beim Compilieren erscheinen die folgende Fehlermeldungen: + \begin{lstlisting}[style=terminal] + $ ¡gcc -std=c99 -Wall -O aufgabe-1a.c -o aufgabe-1a¿ + aufgabe-1a.c: In function 'main': + aufgabe-1a.c:31: error: 'animal' has no member named 'wings' + aufgabe-1a.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}{2020ws/20210204}{aufgabe-1b.c}). + Daraufhin gelingt das Compilieren, und die Ausgabe des Programms lautet: + \begin{lstlisting}[style=terminal] + $ ¡gcc -std=c99 -Wall -O aufgabe-1b.c -o aufgabe-1b¿ + $ ¡./aufgabe-1b¿ + 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}{2020ws/20210204}{loesung-1d-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}{2020ws/20210204}{loesung-1d-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}{2020ws/20210204}{loesung-1d-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}{2020ws/20210204}{loesung-1e.c}. + + Diese Lösung basiert auf \gitfile{hp}{2020ws/20210204}{loesung-1d-2.c}, + da diese bereits weniger explizite Typumwandlungen enthält + als \gitfile{hp}{2020ws/20210204}{loesung-1d-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}{2020ws/20210204}{loesung-1f.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}{2020ws/20210204}{loesung-1g.c}. + + \end{itemize} + + \clearpage + + \exercise{Iterationsfunktionen} + + Wir betrachten das folgende Programm (\gitfile{hp}{2020ws/20210204}{loesung-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}{2020ws/20210204}{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}{2020ws/20210204}{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{Dynamisches Bit-Array} + + Schreiben Sie die folgenden Funktionen zur Verwaltung eines dynamischen Bit-Arrays: + \begin{itemize} + \item + \lstinline{void bit_array_init (int n)}\\ + Das Array initialisieren, so daß man \lstinline{n} Bits darin speichern kann.\\ + Die Array-Größe \lstinline{n} ist keine Konstante, sondern erst im laufenden Programm bekannt.\\ + Die Bits sollen auf den Anfangswert 0 initialisiert werden. + \item + \lstinline{void bit_array_set (int i, int value)}\\ + Das Bit mit dem Index \lstinline{i} auf den Wert \lstinline{value} setzen.\\ + Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen; + der Wert \lstinline{value} darf 1 oder 0 sein. + \item + \lstinline{void bit_array_flip (int i)}\\ + Das Bit mit dem Index \lstinline{i} auf den entgegengesetzten Wert setzen,\\ + also auf 1, wenn er vorher 0 ist, bzw.\ auf 0, wenn er vorher 1 ist.\\ + Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen. + \item + \lstinline{int bit_array_get (int i)}\\ + Den Wert des Bit mit dem Index \lstinline{i} zurückliefern.\\ + Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen. + \item + \lstinline{void bit_array_resize (int new_n)}\\ + Die Größe des Arrays auf \lstinline{new_n} Bits ändern.\\ + Dabei soll der Inhalt des Arrays, soweit er in die neue Größe paßt, erhalten bleiben.\\ + Neu hinzukommende Bits sollen auf 0 initialisiert werden. + \item + \lstinline{void bit_array_done (void)}\\ + Den vom Array belegten Speicherplatz wieder freigeben. + \end{itemize} + Bei Bedarf dürfen Sie den Funktionen zusätzliche Parameter mitgeben, + beispielsweise um mehrere Arrays parallel verwalten zu können. + (In der objektorientierten Programmierung wäre dies der implizite Parameter \lstinline{this}, + der auf die Objekt-Struktur zeigt.) + + Die Bits sollen möglichst effizient gespeichert werden, + z.\,B.\ jeweils 8 Bits in einer \lstinline{uint8_t}-Variablen. + + Die Funktionen sollen möglichst robust sein, + d.\,h.\ das Programm darf auch bei unsinnigen Parameterwerten nicht abstürzen, + sondern soll eine Fehlermeldung ausgeben. + + \medskip + + Die folgenden \textbf{Hinweise} beschreiben + einen möglichen Weg, die Aufgabe zu lösen. + Es seht Ihnen frei, die Aufgabe auch auf andere Weise zu lösen. + \begin{itemize} + \item + Setzen Sie zunächst voraus, daß das Array die konstante Länge 8 hat, + und schreiben Sie zunächst nur die Funktionen + \lstinline{bit_array_set()}, \lstinline{bit_array_flip()} und + \lstinline{bit_array_get()}. + \item + Verallgemeinern Sie nun auf eine konstante Länge, + bei der es sich um ein Vielfaches von 8 handelt. + \item + Implementieren Sie nun die Überprüfung auf unsinnige Parameterwerte. + Damit können Sie sich gleichzeitig von der Bedingung lösen, + daß die Länge des Arrays ein Vielfaches von 8 sein muß. + \item + Gehen Sie nun von einem statischen zu einem dynamischen Array über, + und implementieren sie die Funktionen \lstinline{bit_array_init()}, + \lstinline{bit_array_done()} und \lstinline{bit_array_resize()}. + \end{itemize} + +% \points{14} +% +% \medskip +% +% (Hinweis für die Klausur: +% Abgabe in digitaler Form ist erwünscht, aber nicht zwingend.) + + \solution + + Die hier vorgestellte Lösung folgt den Hinweisen. + \begin{itemize} + \item + \textbf{Setzen Sie zunächst voraus, daß das Array die konstante Länge 8 hat, + und schreiben Sie zunächst nur die Funktionen + \lstinline{bit_array_set()}, \lstinline{bit_array_flip()} und + \lstinline{bit_array_get()}.} + + Siehe: \gitfile{hp}{2020ws/20210204}{loesung-3-1.c} + + Wir speichern in jedem der acht Bit einer \lstinline{uint8_t}-Variablen + jeweils eine Zahl, die 0 oder 1 sein kann. + Dies geschieht durch Setzen bzw.\ Löschen bzw.\ Umklappen einzelner Bits + in der Variablen. + + Das Programm enthält zusätzlich eine Funktion \lstinline{output()}, + mit der man sich den Inhalt des Arrays anzeigen lassen kann, + sowie ein Hauptprogramm \lstinline{main()}, um die Funktionen zu testen. + + \item + \textbf{Verallgemeinern Sie nun auf eine konstante Länge, + bei der es sich um ein Vielfaches von 8 handelt.} + + Siehe: \gitfile{hp}{2020ws/20210204}{loesung-3-2.c} + + In diesem Programm setzen wir die Länge auf konstant \lstinline{LENGTH} Bits, + wobei es sich um eine Präprozessor-Konstante mit dem Wert 32 handelt. + + Um \lstinline{LENGTH} Bits zu speichern, benötigen wir ein Array + der Länge \lstinline{LENGTH / 8} Bytes. + + Um auf ein einzelnes Bit zuzugreifen, müssen wir zunächst ermitteln, + in welchem der Bytes sich befindet. Außerdem interessieren wir uns + für die Nummer des Bits innerhalb des Bytes. + Den Array-Index des Bytes erhalten wir, indem wir den Index des Bits + durch 8 dividieren. Der bei dieser Division verbleibende Rest ist die + Nummer des Bits innerhalb des Bytes. + + Diese Rechnungen führen wir in den drei Funktionen + \lstinline{bit_array_set()}, \lstinline{bit_array_flip()} und + \lstinline{bit_array_get()} durch. + (Diese ist eine eher unelegante Code-Verdopplung -- hier sogar eine Verdreifachung. + Für den Produktiveinsatz lohnt es sich, darüber nachzudenken, + wie man diese vermeiden kann, ohne gleichzeitig an Effizienz einzubüßen. + Hierfür käme z.\,B.\ ein Präprozessor-Makro in Frage. + Für die Lösung der Übungsaufgabe wird dies hingegen nicht verlangt.) + + \item + \textbf{Implementieren Sie nun die Überprüfung auf unsinnige Parameterwerte. + Damit können Sie sich gleichzeitig von der Bedingung lösen, + daß die Länge des Arrays ein Vielfaches von 8 sein muß.} + + Siehe: \gitfile{hp}{2020ws/20210204}{loesung-3-3.c} + + Um weitere Code-Verdopplungen zu vermeiden, + führen wir eine Funktion \lstinline{check_index()} ein, + die alle Prüfungen durchführt. + + Wenn die Länge des Arrays kein Vielfaches von 8 ist, + wird das letzte Byte nicht vollständig genutzt. + Die einzige Schwierigkeit besteht darin, die korrekte Anzahl von Bytes + zu ermitteln, nämlich die Länge dividiert durch 8, aber nicht ab-, sondern + aufgerundet. Am elegantesten geht dies durch vorherige Addition von 7: + \lstinline{#define BYTES ((LENGTH + 7) / 8)}. + Es ist aber auch zulässig, die Anzahl der Bytes mit Hilfe einer + \lstinline{if}-Anweisung zu ermitteln: Länge durch 8 teilen und abrunden; + falls die Division nicht glatt aufging, um 1 erhöhen. + + \item + \textbf{Gehen Sie nun von einem statischen zu einem dynamischen Array über, + und implementieren sie die Funktionen \lstinline{bit_array_init()}, + \lstinline{bit_array_done()} und \lstinline{bit_array_resize()}.} + + Siehe: \gitfile{hp}{2020ws/20210204}{loesung-3-4.c}. + Damit ist die Aufgabe gelöst. + + Aus den Präprozessor-Konstanten \lstinline{LENGTH} und \lstinline{BYTES} + werden nun globale \lstinline{int}-Variable. + Die Funktion \lstinline{bit_array_init()} berechnet die korrekten Werte + für diese Variablen und legt das Array mittels \lstinline{malloc()} dynamisch + an. Eine Größenänderung des Arrays erfolgt mittels \lstinline{realloc()}, + das Freigeben mittels \lstinline{free()}. + + Das Programm setzt Variable, die aktuell nicht verwendet werden, + auf den Wert \lstinline{0} bzw.\ \lstinline{NULL}. + Dies ermöglicht es der Funktion \lstinline{check_index()}, + auch zu prüfen, ob das Array vorher korrekt mit \lstinline{bit_array_init()} + erzeugt wurde -- oder ob es vielleicht schon wieder mit + \lstinline{bit_array_done()} freigegeben wurde. + + \end{itemize} + +\end{document} diff --git a/20210204/hp-uebung-20210204.pdf b/20210204/hp-uebung-20210204.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b0b178e5c4573e66b3c4dad8392afd2fcd61f901 Binary files /dev/null and b/20210204/hp-uebung-20210204.pdf differ diff --git a/20210204/hp-uebung-20210204.tex b/20210204/hp-uebung-20210204.tex new file mode 100644 index 0000000000000000000000000000000000000000..bef613ff2e7feff1584b6a485869365486b95933 --- /dev/null +++ b/20210204/hp-uebung-20210204.tex @@ -0,0 +1,303 @@ +% hp-uebung-20210204.pdf - Exercises on Low-Level Programming +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 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: Objektorientierte Tier-Datenbank (Neuauflage), Iterationsfunktionen, dynamisches Bit-Array + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + +% \thispagestyle{empty} + + \section*{Hardwarenahe Programmierung\\ + Übungsaufgaben -- 4.\ Februar 2021} + +% Diese Übung enthält Punkteangaben wie in einer Klausur. +% Um zu "`bestehen"', müssen Sie innerhalb von 100 Minuten +% unter Verwendung ausschließlich zugelassener Hilfsmittel +% 17 Punkte (von insgesamt \totalpoints) erreichen. + + \exercise{Objektorientierte Tier-Datenbank (Neuauflage)} + + Diese Aufgabe ist eine Neuauflage von Aufgabe 3 der + Übung vom 28.\ Januar 2021,\\ + ergänzt um die Teilaufgaben (e) bis (g). + + \medskip + + Das auf der nächsten Seite dargestellte Programm + (Datei: \gitfile{hp}{2020ws/20210204}{aufgabe-1a.c}) + soll Daten von Tieren verwalten. + + Beim Compilieren erscheinen die folgende Fehlermeldungen: + \begin{lstlisting}[style=terminal] + $ ¡gcc -std=c99 -Wall -O aufgabe-1a.c -o aufgabe-1a¿ + aufgabe-1a.c: In function 'main': + aufgabe-1a.c:31: error: 'animal' has no member named 'wings' + aufgabe-1a.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}{2020ws/20210204}{aufgabe-1b.c}). + Daraufhin gelingt das Compilieren, und die Ausgabe des Programms lautet: + \begin{lstlisting}[style=terminal] + $ ¡gcc -std=c99 -Wall -O aufgabe-1b.c -o aufgabe-1b¿ + $ ¡./aufgabe-1b¿ + 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} + + \exercise{Iterationsfunktionen} + + Wir betrachten das folgende Programm (\gitfile{hp}{2020ws/20210204}{aufgabe-2.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} + + \clearpage + + \exercise{Dynamisches Bit-Array} + + Schreiben Sie die folgenden Funktionen zur Verwaltung eines dynamischen Bit-Arrays: + \begin{itemize} + \item + \lstinline{void bit_array_init (int n)}\\ + Das Array initialisieren, so daß man \lstinline{n} Bits darin speichern kann.\\ + Die Array-Größe \lstinline{n} ist keine Konstante, sondern erst im laufenden Programm bekannt.\\ + Die Bits sollen auf den Anfangswert 0 initialisiert werden. + \item + \lstinline{void bit_array_set (int i, int value)}\\ + Das Bit mit dem Index \lstinline{i} auf den Wert \lstinline{value} setzen.\\ + Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen; + der Wert \lstinline{value} darf 1 oder 0 sein. + \item + \lstinline{void bit_array_flip (int i)}\\ + Das Bit mit dem Index \lstinline{i} auf den entgegengesetzten Wert setzen,\\ + also auf 1, wenn er vorher 0 ist, bzw.\ auf 0, wenn er vorher 1 ist.\\ + Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen. + \item + \lstinline{int bit_array_get (int i)}\\ + Den Wert des Bit mit dem Index \lstinline{i} zurückliefern.\\ + Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen. + \item + \lstinline{void bit_array_resize (int new_n)}\\ + Die Größe des Arrays auf \lstinline{new_n} Bits ändern.\\ + Dabei soll der Inhalt des Arrays, soweit er in die neue Größe paßt, erhalten bleiben.\\ + Neu hinzukommende Bits sollen auf 0 initialisiert werden. + \item + \lstinline{void bit_array_done (void)}\\ + Den vom Array belegten Speicherplatz wieder freigeben. + \end{itemize} + Bei Bedarf dürfen Sie den Funktionen zusätzliche Parameter mitgeben, + beispielsweise um mehrere Arrays parallel verwalten zu können. + (In der objektorientierten Programmierung wäre dies der implizite Parameter \lstinline{this}, + der auf die Objekt-Struktur zeigt.) + + Die Bits sollen möglichst effizient gespeichert werden, + z.\,B.\ jeweils 8 Bits in einer \lstinline{uint8_t}-Variablen. + + Die Funktionen sollen möglichst robust sein, + d.\,h.\ das Programm darf auch bei unsinnigen Parameterwerten nicht abstürzen, + sondern soll eine Fehlermeldung ausgeben. + + \medskip + + Die folgenden \textbf{Hinweise} beschreiben + einen möglichen Weg, die Aufgabe zu lösen. + Es seht Ihnen frei, die Aufgabe auch auf andere Weise zu lösen. + \begin{itemize} + \item + Setzen Sie zunächst voraus, daß das Array die konstante Länge 8 hat, + und schreiben Sie zunächst nur die Funktionen + \lstinline{bit_array_set()}, \lstinline{bit_array_flip()} und + \lstinline{bit_array_get()}. + \item + Verallgemeinern Sie nun auf eine konstante Länge, + bei der es sich um ein Vielfaches von 8 handelt. + \item + Implementieren Sie nun die Überprüfung auf unsinnige Parameterwerte. + Damit können Sie sich gleichzeitig von der Bedingung lösen, + daß die Länge des Arrays ein Vielfaches von 8 sein muß. + \item + Gehen Sie nun von einem statischen zu einem dynamischen Array über, + und implementieren Sie die Funktionen \lstinline{bit_array_init()}, + \lstinline{bit_array_done()} und \lstinline{bit_array_resize()}. + \end{itemize} + +% \points{14} +% +% \medskip +% +% (Hinweis für die Klausur: +% Abgabe in digitaler Form ist erwünscht, aber nicht zwingend.) + + \begin{flushright} + \textit{Viel Erfolg!} + \end{flushright} + + \makeatletter + \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}} + \makeatother + +\end{document} diff --git a/20210204/loesung-1d-0f.c b/20210204/loesung-1d-0f.c new file mode 100644 index 0000000000000000000000000000000000000000..04b2d3e8956f4790b3f2ffdf3a314994c640513e --- /dev/null +++ b/20210204/loesung-1d-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/20210204/loesung-1d-1.c b/20210204/loesung-1d-1.c new file mode 100644 index 0000000000000000000000000000000000000000..349523a7d99e33ba81094ffbc8907773b5a3a251 --- /dev/null +++ b/20210204/loesung-1d-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/20210204/loesung-1d-2.c b/20210204/loesung-1d-2.c new file mode 100644 index 0000000000000000000000000000000000000000..f831a75eda1f3e784c8e6c1f24a83d9d6b55ee6c --- /dev/null +++ b/20210204/loesung-1d-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/20210204/loesung-1e.c b/20210204/loesung-1e.c new file mode 100644 index 0000000000000000000000000000000000000000..b984d9253b9c379a88f0fc0ca130c88c3103f8f3 --- /dev/null +++ b/20210204/loesung-1e.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/20210204/loesung-1f.c b/20210204/loesung-1f.c new file mode 100644 index 0000000000000000000000000000000000000000..7b949e6365fc3839e6adc7661e0f8b4dd0c059df --- /dev/null +++ b/20210204/loesung-1f.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/20210204/loesung-1g.c b/20210204/loesung-1g.c new file mode 100644 index 0000000000000000000000000000000000000000..b453a52dbe0ef27399255819808b3f6e562ba3ef --- /dev/null +++ b/20210204/loesung-1g.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/20210204/logo-hochschule-bochum-cvh-text-v2.pdf b/20210204/logo-hochschule-bochum-cvh-text-v2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8 --- /dev/null +++ b/20210204/logo-hochschule-bochum-cvh-text-v2.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum-cvh-text-v2.pdf \ No newline at end of file diff --git a/20210204/logo-hochschule-bochum.pdf b/20210204/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20210204/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20210204/pgscript.sty b/20210204/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20210204/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20210204/pgslides.sty b/20210204/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20210204/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file diff --git a/README.md b/README.md index e4029aebe8dd8e83baba901ef3ef4bc6ff9ddd37..9b2ab1615331d353f9bc19e04e3f5395f8304420 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,10 @@ Vortragsfolien und Beispiele: * [10.12.2020: Präprozessor, Bibliotheken einbinden und verwenden](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20201210/hp-20201210.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2020ws/20201210/) * [17.12.2020: make, Differentialgleichungen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20201217/hp-20201217.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2020ws/20201217/) * [07.01.2021: Rekursion, Aufwandsabschätzungen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210107/hp-20210107.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2020ws/20210107/) - * [14.01.2021: Hardwarenahe Programmierung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210114/hp-20210114.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2020ws/20210114/) + * [14.01.2021: Hardwarenahe Programmierung: Bit-Operationen, I/O-Ports](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210114/hp-20210114.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2020ws/20210114/) + * [21.01.2021: Hardwarenahe Programmierung: Interrupts, volatile-Variable, Byte-Reihenfolge – Endianness, Binärdarstellung negativer Zahlen, Speicherausrichtung – Alignment](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210121/hp-20210121.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2020ws/20210121/) + * [28.01.2021: Objektorientierte Programmierung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210128/hp-20210128.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2020ws/20210128/) + * [04.02.2021: Objektorientierte Programmierung: virtuelle Methoden](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210204/hp-20210204.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2020ws/20210204/) * [alle in 1 Datei](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/hp-slides-2020ws.pdf) Übungsaufgaben: @@ -39,6 +42,9 @@ Vortragsfolien und Beispiele: * [17.12.2020: Kondensator, hüpfender Ball](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20201217/hp-uebung-20201217.pdf) * [07.01.2021: Fakultät, Länge von Strings (Neuauflage), Hexdumps](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210107/hp-uebung-20210107.pdf) * [14.01.2021: Zahlensysteme, Mikrocontroller, Einfügen in Strings (Ergänzung)](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210114/hp-uebung-20210114.pdf) + * [21.01.2021: Trickprogrammierung, Thermometer-Baustein an I²C-Bus, LED-Blinkmuster](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210121/hp-uebung-20210121.pdf) + * [28.01.2021: Speicherformate von Zahlen, Personen-Datenbank, objektorientierte Tier-Datenbank](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210128/hp-uebung-20210128.pdf) + * [04.02.2021: Objektorientierte Tier-Datenbank (Neuauflage), Iterationsfunktionen, dynamisches Bit-Array](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210204/hp-uebung-20210204.pdf) Musterlösungen: --------------- @@ -50,6 +56,9 @@ Musterlösungen: * [17.12.2020: Kondensator, hüpfender Ball](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20201217/hp-musterloesung-20201217.pdf) * [07.01.2021: Fakultät, Länge von Strings (Neuauflage), Hexdumps](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210107/hp-musterloesung-20210107.pdf) * [14.01.2021: Zahlensysteme, Mikrocontroller](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210114/hp-musterloesung-20210114.pdf) + * [21.01.2021: Trickprogrammierung, Thermometer-Baustein an I²C-Bus, LED-Blinkmuster](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210121/hp-musterloesung-20210121.pdf) + * [28.01.2021: Speicherformate von Zahlen, Personen-Datenbank, objektorientierte Tier-Datenbank](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210128/hp-musterloesung-20210128.pdf) + * [04.02.2021: Objektorientierte Tier-Datenbank (Neuauflage), Iterationsfunktionen, dynamisches Bit-Array](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210204/hp-musterloesung-20210204.pdf) Tafelbilder: ------------ @@ -60,6 +69,7 @@ Praktikumsunterlagen: * [Versuch 1: RSA-Verschlüsselung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20201112/hp-2020ws-p1.pdf) * [Versuch 2: Weltraum-Simulation](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20201217/hp-2020ws-p2.pdf) * [Versuch 3: Druckknopfampel](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210114/hp-2020ws-p3.pdf) + * [Versuch 4: Objektorientiertes Grafik-Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2020ws/20210204/hp-2020ws-p4.pdf) Alte Klausuren: --------------- diff --git a/hp-slides-2020ws.pdf b/hp-slides-2020ws.pdf index 204153ff3843d9c96fb2acdd2c1cbe2b3bc62764..2a5d0ce9550c2e58f7edb021e84d836b00248e8c 100644 Binary files a/hp-slides-2020ws.pdf and b/hp-slides-2020ws.pdf differ diff --git a/hp-slides-2020ws.tex b/hp-slides-2020ws.tex index 1bca6b8a138335f36365db9d3774f5c109da05f2..551b589a8c3104cec602367459df620f1167cdbb 100644 --- a/hp-slides-2020ws.tex +++ b/hp-slides-2020ws.tex @@ -26,6 +26,12 @@ \includepdf[pages=-]{20201217/hp-20201217.pdf} \pdfbookmark[1]{07.01.2021: Rekursion, Aufwandsabschätzungen}{20210107} \includepdf[pages=-]{20210107/hp-20210107.pdf} - \pdfbookmark[1]{14.01.2021: Hardwarenahe Programmierung}{20210114} + \pdfbookmark[1]{14.01.2021: Hardwarenahe Programmierung: Bit-Operationen, I/O-Ports}{20210114} \includepdf[pages=-]{20210114/hp-20210114.pdf} + \pdfbookmark[1]{21.01.2021: Hardwarenahe Programmierung: Interrupts, volatile-Variable, Byte-Reihenfolge – Endianness, Binärdarstellung negativer Zahlen, Speicherausrichtung – Alignment}{20210121} + \includepdf[pages=-]{20210121/hp-20210121.pdf} + \pdfbookmark[1]{28.01.2021: Objektorientierte Programmierung}{20210128} + \includepdf[pages=-]{20210128/hp-20210128.pdf} + \pdfbookmark[1]{04.02.2021: Objektorientierte Programmierung: virtuelle Methoden}{20210204} + \includepdf[pages=-]{20210204/hp-20210204.pdf} \end{document}