diff --git a/20210107/InstallationUndVerwendungGTKWin10.pdf b/20210107/InstallationUndVerwendungGTKWin10.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3757e05839ad8463e7da520b343a93af1f30d951 Binary files /dev/null and b/20210107/InstallationUndVerwendungGTKWin10.pdf differ diff --git a/20210107/Tower_of_Hanoi.jpeg b/20210107/Tower_of_Hanoi.jpeg new file mode 120000 index 0000000000000000000000000000000000000000..a1a794afda08596ffa2f46f278db53455de25b6c --- /dev/null +++ b/20210107/Tower_of_Hanoi.jpeg @@ -0,0 +1 @@ +../common/Tower_of_Hanoi.jpeg \ No newline at end of file diff --git a/20210107/aufgabe-1.c b/20210107/aufgabe-1.c new file mode 100644 index 0000000000000000000000000000000000000000..abbf364a3db17611e41d086591826e98a8a3672b --- /dev/null +++ b/20210107/aufgabe-1.c @@ -0,0 +1,16 @@ +#include <stdio.h> + +int fak (int n) +{ + if (n <= 0) + return 1; + else + return n * fak (n - 1); +} + +int main (void) +{ + for (int n = 0; n <= 5; n++) + printf ("%d\n", fak (n)); + return 0; +} diff --git a/20210107/aufgabe-2.c b/20210107/aufgabe-2.c new file mode 100644 index 0000000000000000000000000000000000000000..d0b065941fbc0082bf867d872527299dca97b98f --- /dev/null +++ b/20210107/aufgabe-2.c @@ -0,0 +1,18 @@ +#include <string.h> + +int fun_1 (char *s) +{ + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; +} + +int fun_2 (char *s) +{ + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; +} diff --git a/20210107/aufgabe-3.c b/20210107/aufgabe-3.c new file mode 100644 index 0000000000000000000000000000000000000000..2bcd5e63a71f212b7243d1f7d9c92406d1e41e77 --- /dev/null +++ b/20210107/aufgabe-3.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +int main (void) +{ + char buffer[100]; + fgets (buffer, 100, stdin); + for (char *p = buffer; *p; p++) + printf ("%02x", *p); + printf ("\n"); +} diff --git a/20210107/hp-20210107.pdf b/20210107/hp-20210107.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0503488856a9624499caa49b82e1a83ce6e35f04 Binary files /dev/null and b/20210107/hp-20210107.pdf differ diff --git a/20210107/hp-20210107.tex b/20210107/hp-20210107.tex new file mode 100644 index 0000000000000000000000000000000000000000..0e48bfed60b59e2731f579314252ee949a00019c --- /dev/null +++ b/20210107/hp-20210107.tex @@ -0,0 +1,852 @@ +% hp-20210107.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: Rekursion, Aufwandsabschätzungen + +\documentclass[10pt,t]{beamer} + +\usepackage{pgslides} +\usepackage{pdftricks} +\usepackage{tikz} + +\begin{psinputs} + \usepackage[utf8]{inputenc} + \usepackage[german]{babel} + \usepackage[T1]{fontenc} + \usepackage{helvet} + \renewcommand*\familydefault{\sfdefault} + \usepackage{pstricks,pst-grad} +\end{psinputs} + +\title{Hardwarenahe Programmierung} +\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski} +\date{7.\ Januar 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} + \begin{itemize} + \item[3.1] Der Präprozessor + \item[3.2] Bibliotheken einbinden + \item[3.3] Bibliotheken verwenden + \color{medgreen} + \item[3.4] Projekt organisieren: make + \end{itemize} + \item[\textbf{4}] \textbf{Algorithmen} + \begin{itemize} + \color{medgreen} + \item[5.1] Differentialgleichungen + \color{red} + \item[5.2] Rekursion + \item[5.3] Aufwandsabschätzungen + \end{itemize} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \vspace*{-\smallskipamount} + \item[\textbf{\dots}] + \end{itemize} + +\end{frame} + +\setcounter{section}{2} +\section{Bibliotheken} +\subsection{Der Präprozessor} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \lstinline{#include}: %\pause: + Text einbinden + \begin{itemize} +% \pause + \item + \lstinline{#include <stdio.h>}: Standard-Verzeichnisse -- Standard-Header +% \pause + \item + \lstinline{#include "answer.h"}: auch aktuelles Verzeichnis -- eigene Header + \end{itemize} + +% \pause + \bigskip + + \lstinline{#define VIER 4}: Text ersetzen lassen -- Konstante definieren + \begin{itemize} +% \pause + \item + Kein Semikolon! +% \pause + \item + Berechnungen in Klammern setzen:\\ + \lstinline{#define VIER (2 + 2)} +% \pause + \item + Konvention: Großbuchstaben + \end{itemize} + +\end{frame} + +\subsection{Bibliotheken einbinden} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + Inhalt der Header-Datei: externe Deklarationen + +% \pause + \smallskip + \lstinline{extern int answer (void);} + +% \pause + \smallskip + \lstinline{extern int printf (__const char *__restrict __format, ...);} + +% \pause + \bigskip + Funktion wird "`anderswo"' definiert + \begin{itemize} +% \pause + \item + separater C-Quelltext: mit an \lstinline[style=terminal]{gcc} übergeben +% \pause + \item + Zusammenfügen zu ausführbarem Programm durch den \newterm{Linker} +% \pause + \item + vorcompilierte Bibliothek: \lstinline[style=terminal]{-lfoo}\\ +% \pause + = Datei \file{libfoo.a} in Standard-Verzeichnis + \end{itemize} + +\end{frame} + +\subsection{Bibliothek verwenden (Beispiel: GTK+)} + +\begin{frame}[fragile] + + \showsubsection + + \begin{itemize} + \item + \lstinline{#include <gtk/gtk.h>} +% \pause + \smallskip + \item + Mit \lstinline[style=cmd]{pkg-config --cflags --libs} erfährt man,\\ + welche Optionen und Bibliotheken man an \lstinline[style=cmd]{gcc} + übergeben muß\alt<1->{.}{:} +% \pause + \begin{onlyenv}<1> + \begin{lstlisting}[style=terminal,gobble=10] + $ ¡pkg-config --cflags --libs gtk+-3.0¿ + -pthread -I/usr/include/gtk-3.0 -I/usr/include/at-spi2- + atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1 + .0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/usr/ + include/gtk-3.0 -I/usr/include/gio-unix-2.0/ -I/usr/inc + lude/cairo -I/usr/include/pango-1.0 -I/usr/include/harf + buzz -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I + /usr/include/cairo -I/usr/include/pixman-1 -I/usr/inclu + de/freetype2 -I/usr/include/libpng16 -I/usr/include/gdk + -pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/glib + -2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lgtk + -3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcai + ro-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject + -2.0 -lglib-2.0 + \end{lstlisting} + \vspace*{-3cm} + \end{onlyenv} + \pause + \arrowitem + Compiler-Aufruf: + \begin{onlyenv}<2> + \begin{lstlisting}[style=terminal,gobble=10] + $ ¡gcc -Wall -O hello-gtk.c -pthread -I/usr/include/gtk- + 3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-sp + i-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-g + nu/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/inclu + de/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/pa + ngo-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1. + 0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/in + clude/pixman-1 -I/usr/include/freetype2 -I/usr/include/ + libpng16 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/l + ibpng16 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux + -gnu/glib-2.0/include -lgtk-3 -lgdk-3 -lpangocairo-1.0 + -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pix + buf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -o hello-gtk¿ + \end{lstlisting} + \vspace*{-2cm} + \end{onlyenv} + \begin{onlyenv}<3-> + \begin{lstlisting}[style=terminal,gobble=10] + $ ¡gcc -Wall -O hello-gtk.c $(pkg-config --cflags --libs + gtk+-3.0) -o hello-gtk¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<3> + \begin{picture}(0,0)(0.3,0.3) + \color{red} + \put(6.6,-0.6){\makebox(0,0)[bl]{\tikz{\draw[-latex](0,0)--(3,1.5);}}} + \put(6.3,-0.7){\makebox(0,0)[t]{\shortstack{\strut Optionen:\\ + \strut u.\,a.\ viele Include-Verzeichnisse:\\ + \lstinline[style=cmd]{-I/usr/include/gtk-3.0}}}} + \put(10.0,-2.1){\makebox(0,0)[bl]{\tikz{\draw[-latex](0,0)--(1.5,3);}}} + \put(10.3,-2.2){\makebox(0,0)[t]{\shortstack{\strut Bibliotheken:\\ + \strut u.\,a.\ \lstinline[style=cmd]{-lgtk-3 -lcairo}\qquad\strut}}} + \end{picture} + \end{onlyenv} + \pause + \pause + \item + Auf manchen Plattformen kommt es auf die Reihenfolge an: + \begin{lstlisting}[style=terminal,gobble=8] + $ ¡gcc -Wall -O $(pkg-config --cflags gtk+-3.0) \ + hello-gtk.c $(pkg-config --libs gtk+-3.0) \ + -o hello-gtk¿ + \end{lstlisting} + (Backslash = "`Es geht in der nächsten Zeile weiter."') + \end{itemize} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Selbst geschriebene Funktion übergeben: \newterm{Callback} + + \bigskip + + \begin{lstlisting}[xleftmargin=1em] + gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data) + { + /* Zeichenbefehle */ + ... + + return FALSE; + } + + ... + + g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL); + \end{lstlisting} + + \medskip + + \begin{itemize} + \arrowitem + GTK+ ruft immer dann, wenn es etwas zu zeichnen gibt,\\ + die Funktion \lstinline{draw} auf. + \end{itemize} + +% \pause + \begin{picture}(0,0)(-0.07,0.2) + \color{red} + \put(5.3,4.8){\makebox(0,0)[bl]{\tikz{\draw[-latex](0,0)--(1.90,1.15);}}} + \put(5.0,4.7){\makebox(0,0)[t]{\shortstack{\strut repräsentiert den\\ + \strut Bildschirm, auf den\\ + \strut gezeichnet werden soll}}} +% \pause + \put(9.7,5.1){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-0.2,0.85);}}} + \put(9.7,5.0){\makebox(0,0)[t]{\shortstack{\strut optionale Zusatzinformationen\\ + \strut für draw(), typischerweise\\ + \strut ein Zeiger auf ein struct}}} + \put(10.0,3.5){\makebox(0,0)[tl]{\tikz{\draw[-latex](0,0)--(0.6,-1.25);}}} + \end{picture} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Selbst geschriebene Funktion übergeben: \newterm{Callback} + + \bigskip + + \begin{lstlisting}[xleftmargin=1em] + gboolean timer (GtkWidget *widget) + { + /* Rechenbefehle */ + ... + + gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT); + g_timeout_add (50, (GSourceFunc) timer, widget); + return FALSE; + } + + ... + + g_timeout_add (50, (GSourceFunc) timer, drawing_area); + \end{lstlisting} + + \medskip + + \begin{itemize} + \arrowitem + GTK+ ruft nach 50 Millisekunden + die Funktion \lstinline{timer} auf. + \end{itemize} + +% \pause + \begin{picture}(0,0)(-0.07,0.2) + \color{red} + \put(9.7,6.7){\makebox(0,0)[t]{\shortstack{\strut Dieser Bereich soll\\ + \strut neu gezeichnet werden.}}} + \put(9.7,5.7){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.6,-0.8);}}} +% \pause + \put(4.3,3.2){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-0.7,0.6);}}} + \put(4.3,3.1){\makebox(0,0)[t]{\shortstack{\strut In weiteren 50 Millisekunden soll\\ + \strut die Funktion erneut aufgerufen werden.}}} +% \pause + \put(9.3,2.9){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-3.3,0.9);}}} + \put(9.8,2.8){\makebox(0,0)[t]{\shortstack{\strut Explizite Typumwandlung\\ + \strut eines Zeigers (später)}}} + \end{picture} + + \vspace*{-1cm} + +\end{frame} + +\subsection{Projekt organisieren: make} + +\begin{frame}[fragile] + + \showsubsection + \begin{itemize} + \item + \only<4->{explizite und implizite} Regeln + \begin{onlyenv}<2> + \smallskip + \begin{lstlisting}[language=make,gobble=10] + philosophy: philosophy.o answer.o + gcc philosophy.o answer.o -o philosophy + + answer.o: answer.c answer.h + gcc -Wall -O answer.c -c + + philosophy.o: philosophy.c answer.h + gcc -Wall -O philosophy.c -c + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<4> + \smallskip + \begin{lstlisting}[language=make,gobble=10] + TARGET = philosophy + OBJECTS = philosophy.o answer.o + HEADERS = answer.h + CFLAGS = -Wall -O + + $(TARGET): $(OBJECTS) + gcc $(OBJECTS) -o $(TARGET) + + %.o: %.c $(HEADERS) + gcc $(CFLAGS) $< -c + + clean: + rm -f $(OBJECTS) $(TARGET) + \end{lstlisting} + \end{onlyenv} + \item + Makros + \begin{onlyenv}<3> + \smallskip + \begin{lstlisting}[language=make,gobble=10] + TARGET = philosophy + OBJECTS = philosophy.o answer.o + HEADERS = answer.h + CFLAGS = -Wall -O + + $(TARGET): $(OBJECTS) + gcc $(OBJECTS) -o $(TARGET) + + answer.o: answer.c $(HEADERS) + gcc $(CFLAGS) answer.c -c + + philosophy.o: philosophy.c $(HEADERS) + gcc $(CFLAGS) philosophy.c -c + + clean: + rm -f $(OBJECTS) $(TARGET) + \end{lstlisting} + \vspace*{-1cm} + \end{onlyenv} + \begin{onlyenv}<5-> + \smallskip + \arrowitem + 3 Sprachen: C, Präprozessor, make + \end{onlyenv} + \end{itemize} + +\end{frame} + +\section{Algorithmen} +\subsection{Differentialgleichungen} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \textbf{Beispiel 1: Gleichmäßig beschleunigte Bewegung} + + \strut\hfill + \begin{minipage}{2.5cm} + \vspace*{0.6cm} + \begin{align*} + x'(t) &= v_x(t) \\[0.65cm] + y'(t) &= v_y(t) \\[0.75cm] + v_x'(t) &= 0 \\[0.65cm] + v_y'(t) &= -g + \end{align*} + \vspace*{0.0cm} + \end{minipage}% + \only<1>{\hspace*{9.49cm}}\strut + \only<2->{\hfill$\Rightarrow$\hfill}% + \begin{onlyenv}<2-8> + \begin{minipage}{8.3cm} + \begin{align*} + x(t) &= \int v_x(t)\,dt + \visible<4->{= \int v_{0x}\,dt} + \visible<5->{= x_0 + v_{0x}\cdot t}\\[\medskipamount] + y(t) &= \int v_y(t)\,dt + \visible<7->{= \int v_{0y} - g\cdot t\,dt} + \visible<8->{= y_0 + v_{0y}\cdot t + - {\textstyle\frac12}gt^2}\\[\bigskipamount] + v_x(t) &= \int 0\,dt + \visible<3->{= v_{0x}} \\[\medskipamount] + v_y(t) &= \int -g\,dt + \visible<6->{= v_{0y} - g\cdot t} + \end{align*} + \end{minipage}% + \end{onlyenv}% + \begin{onlyenv}<9-> + \begin{minipage}{3.5cm} + \vspace*{0.5cm} + \begin{lstlisting}[gobble=8,xleftmargin=0.5em] + ¡x += vx * dt;¿ + \end{lstlisting} + \vspace{0.75cm} + \begin{lstlisting}[gobble=8,xleftmargin=0.5em] + ¡y += vy * dt;¿ + \end{lstlisting} + \vspace{0.90cm} + \begin{lstlisting}[gobble=8,xleftmargin=0.5em] + ¡vx += 0 * dt;¿ + \end{lstlisting} + \vspace{0.75cm} + \begin{lstlisting}[gobble=8,xleftmargin=0.5em] + ¡vy += -g * dt;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}{5.13cm} + Siehe: \file{gtk-13.c} + \end{minipage} + \end{onlyenv}% + \hfill\strut + +\end{frame} + +\begin{frame}[fragile] + \showsection + \showsubsection + + \textbf{Beispiel 1: Gleichmäßig beschleunigte Bewegung} + + \medskip + + \textbf{Beispiel 2: Mathematisches Pendel} + + \vspace*{-2\bigskipamount} + + \begin{picture}(0,0) + \put(8,-6.5){\includegraphics{pendulum.pdf}} + \end{picture} + + \begin{eqnarray*} + \varphi'(t) &=& \omega(t) \\[\smallskipamount] + \omega'(t) &=& -\frac{g}{l}\cdot\sin\varphi(t)\hspace*{7.1cm} + \end{eqnarray*} + \vspace*{-1.5\medskipamount} + \begin{itemize} + \item + Von Hand (analytisch):\\ + Lösung raten (Ansatz), Parameter berechnen + \item + Mit Computer (numerisch):\\ + Eulersches Polygonzugverfahren + \end{itemize} + \smallskip + \begin{lstlisting}[gobble=0] + phi += dt * omega; + omega += - dt * g / l * sin (phi); + \end{lstlisting} + + \pause + \bigskip + + \textbf{Beispiel 3: Weltraum-Simulation} + + Praktikumsaufgabe + \vspace*{-1cm} + +\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} + \begin{itemize} + \item[3.1] Der Präprozessor + \item[3.2] Bibliotheken einbinden + \item[3.3] Bibliotheken verwenden + \color{medgreen} + \item[3.4] Projekt organisieren: make + \end{itemize} + \item[\textbf{4}] \textbf{Algorithmen} + \begin{itemize} + \color{medgreen} + \item[5.1] Differentialgleichungen + \color{red} + \item[5.2] Rekursion + \item[5.3] Aufwandsabschätzungen + \end{itemize} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \vspace*{-\smallskipamount} + \item[\textbf{\dots}] + \end{itemize} + \vspace*{-1cm} + +\end{frame} + +\subsection{Rekursion} + +\begin{frame}[fragile] + + \showsubsection + + Vollständige Induktion: + \vspace*{-0.725cm} + \begin{displaymath} + \hspace*{4cm} + \left. + \begin{array}{r} + \mbox{Aussage gilt für $n = 1$}\\[2pt] + \mbox{Schluß von $n - 1$ auf $n$} + \end{array} + \right\} + \mbox{Aussage gilt für alle $n\in\mathbb{N}$} + \end{displaymath} + \vspace*{-0.5cm} + + \pause + + Türme von Hanoi + + \begin{onlyenv}<2> + \begin{center} + \includegraphics[width=12.2cm]{Tower_of_Hanoi.jpeg} + \end{center} + \end{onlyenv} + + \begin{onlyenv}<3-> + \begin{itemize} + \item + 64 Scheiben, 3 Plätze, + \only<3-4>{\hfill\makebox(0,0)[rt]{\includegraphics[width=6cm]{Tower_of_Hanoi.jpeg}}}\\ + immer 1 Scheibe verschieben + \item + Ziel: Turm verschieben + \item + Es dürfen nur kleinere Scheiben\\ + auf größeren liegen. + \bigskip + \pause + \pause + \item + $n = 1$ Scheibe: fertig + \item + Wenn $n - 1$ Scheiben verschiebbar:\\ + schiebe $n - 1$ Scheiben auf Hilfsplatz,\\ + verschiebe die darunterliegende,\\ + hole $n - 1$ Scheiben von Hilfsplatz + \end{itemize} + \begin{onlyenv}<5> + \vspace{-4.3cm} + \begin{lstlisting}[gobble=8,xleftmargin=6.4cm] + void move (int from, int to, int disks) + { + if (disks == 1) + move_one_disk (from, to); + else + { + int help = 0 + 1 + 2 - from - to; + move (from, help, disks - 1); + move (from, to, 1); + move (help, to, disks - 1); + } + } + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<6-> + \vspace{-5.0cm} + \hspace*{7.4cm}\begin{minipage}[t]{5cm} + 32 Scheiben: + \begin{lstlisting}[gobble=10,style=terminal] + $ ¡time ./hanoi-9a¿ + ... + real 0m32,712s + user 0m32,708s + sys 0m0,000s + \end{lstlisting} + \pause[7] + \begin{itemize} + \arrowitem + etwas über 1 Minute\\ + für 64 Scheiben + \end{itemize} + \pause + \vspace*{-0.5cm} + \begin{picture}(0,0) + \color{red} + \put(0,0){\makebox(0,0)[bl]{\tikz[line width=1pt]{\draw(0,0)--(4,0.8);}}} + \put(0,0.8){\makebox(0,0)[tl]{\tikz[line width=1pt]{\draw(0,0)--(4,-0.8);}}} + \end{picture} + + Für jede zusätzliche Scheibe\\verdoppelt sich die Rechenzeit! + % 32.712 * 2^32 / 3600 / 24 / 365.25 = 4452.08032888280477602859 + \begin{itemize} + \arrowitem + $\frac{32,712\,\text{s}\,\cdot\,2^{32}}{3600\,\cdot\,24\,\cdot\,365,25} \approx 4452$ + Jahre\\[\smallskipamount] + für 64 Scheiben + \end{itemize} + \end{minipage} + \end{onlyenv} + \end{onlyenv} + +\end{frame} + +\subsection{Aufwandsabschätzungen \protect\color{gray}-- Komplexitätsanalyse} + +\begin{frame}[fragile] + +% \newcommand{\w}{\hspace*{0.75pt}} + + \showsubsection + + \begin{picture}(0,0) + \put(7.6,-0.5){% + \begin{minipage}[t]{5.3cm} +% \vspace*{-1.0cm}\includegraphics{landau-symbols.pdf} + \vspace*{-1.0cm}\alt<16->{\includegraphics{landau-symbols-3.pdf}}% + {\alt<15->{\includegraphics{landau-symbols-2.pdf}}% + {\includegraphics{landau-symbols.pdf}}} + \small + \begin{description}\itemsep0pt\leftskip-0.5cm + \item[$n$:] Eingabedaten + \item[$g(n)$:] Rechenzeit + \end{description} + \end{minipage}} + \end{picture} + + \vspace*{-\bigskipamount} + + Wann ist ein Programm "`schnell"'? + + \medskip + + \begin{onlyenv}<1-2> + Türme von Hanoi: $\mathcal{O}(2^n)$ + \par\medskip + Für jede zusätzliche Scheibe\\verdoppelt sich die Rechenzeit! + % 32.712 * 2^32 / 3600 / 24 / 365.25 = 4452.08032888280477602859 + \begin{itemize} + \arrowitem + $\frac{32,712\,\text{s}\,\cdot\,2^{32}}{3600\,\cdot\,24\,\cdot\,365,25} \approx 4452$ + Jahre\\[\smallskipamount] + für 64 Scheiben + \end{itemize} + + \bigskip + \end{onlyenv} + + \begin{onlyenv}<2-> + Faustregel:\\Schachtelung der Schleifen zählen\\ + $k$ Schleifen ineinander \textarrow\ $\mathcal{O}(n^k)$ + + \bigskip + \end{onlyenv} + + \begin{onlyenv}<3-13> + \textbf{Beispiel: Sortieralgorithmen} + + \smallskip + + Anzahl der Vergleiche bei $n$ Strings + \begin{itemize} + \item + Maximum suchen \pause[4]mit Schummeln\pause: $\mathcal{O}(1)$ + \pause + \item + Maximum suchen\pause: $\mathcal{O}(n)$ + \pause + \item + Selection-Sort\pause: $\mathcal{O}(n^2)$ + \pause + \item + Bubble-Sort\pause: $\mathcal{O}(n)$ bis $\mathcal{O}(n^2)$ + \pause + \item + Quicksort\pause: $\mathcal{O}(n\log n)$ bis $\mathcal{O}(n^2)$ + \end{itemize} + + \end{onlyenv} + + \begin{onlyenv}<14> + \textbf{Wie schnell ist RSA-Verschlüsselung?} + + \smallskip + + \begin{math} + c = m^e\,\%\,N + \end{math} + \quad + ("`$\%$"' = "`modulo"') + + \medskip + + \begin{lstlisting}[gobble=6,xleftmargin=2em] + int c = 1; + for (int i = 0; i < e; i++) + c = (c * m) % N; + \end{lstlisting} + + \smallskip + + \begin{itemize} + \item + $\mathcal{O}(e)$ Iterationen +% \item +% wenn $n$ die Anzahl der Binärziffern (Bits) von $e$ ist: +% $\mathcal{O}(2^n)$ Iterationen + \item + mit Trick: + $\mathcal{O}(\log e)$ Iterationen ($\log e$ = Anzahl der Ziffern von $e$) + \end{itemize} + + \smallskip + + Jede Iteration enthält eine Multiplikation und eine Division.\\ + Aufwand dafür: $\mathcal{O}(\log e)$\\ + \textarrow\ Gesamtaufwand: $\mathcal{O}\bigl((\log e)^2\bigr)$ + + \end{onlyenv} + + \begin{onlyenv}<15-> + + \textbf{Wie schnell ist RSA?}\\ + + \smallskip + + ($n$ = typische beteiligte Zahl, z.\,B. $e,p,q$) + + \begin{itemize} + \item + Ver- und Entschlüsselung (Exponentiation):\\ + \strut\hbox to 3.5cm{\color{red}$\mathcal{O}\!\left((\log n)^2\right)$\hss} + \only<16->{{\color{magenta}$\mathcal{O}(n^2)$}} + \item + Schlüsselerzeugung (Berechnung von $d$):\\ + \strut\hbox to 3.5cm{\color{red}$\mathcal{O}\!\left((\log n)^2\right)$\hss} + \only<16->{{\color{magenta}$\mathcal{O}(n^2)$}} + \item + Verschlüsselung brechen (Primfaktorzerlegung):\\ + \strut\hbox to 3.5cm{\color{red}$\mathcal{O}\bigl(2^{\sqrt{\log n\,\cdot\,\log\log n}}\bigr)$\hss} + \only<16->{{\color{magenta}$\mathcal{O}\bigl(2^{\sqrt{n\log n}}\bigr)$}} + \end{itemize} + + \vspace{0cm plus 1filll} + + \textbf{Die Sicherheit von RSA beruht darauf, + daß das Brechen der Verschlüsselung aufwendiger ist als + \boldmath$\mathcal{O}\bigl((\log n)^k\bigr)$ (für beliebiges $k$).} + + \vspace*{0.65cm} + + \end{onlyenv} + +\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} + \begin{itemize} + \item[3.1] Der Präprozessor + \item[3.2] Bibliotheken einbinden + \item[3.3] Bibliotheken verwenden + \item[3.4] Projekt organisieren: make + \end{itemize} + \item[\textbf{4}] \textbf{Algorithmen} + \begin{itemize} + \item[5.1] Differentialgleichungen + \color{medgreen} + \item[5.2] Rekursion + \item[5.3] Aufwandsabschätzungen + \end{itemize} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \vspace*{-\smallskipamount} + \item[\textbf{\dots}] + \end{itemize} + \vspace*{-1cm} + +\end{frame} + +\end{document} diff --git a/20210107/hp-musterloesung-20210107.pdf b/20210107/hp-musterloesung-20210107.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c154a59ec11e00019d6653f8a309f770ce37a0e6 Binary files /dev/null and b/20210107/hp-musterloesung-20210107.pdf differ diff --git a/20210107/hp-musterloesung-20210107.tex b/20210107/hp-musterloesung-20210107.tex new file mode 100644 index 0000000000000000000000000000000000000000..2027ef6d209d940a82a925f8d8fee50f54ab0048 --- /dev/null +++ b/20210107/hp-musterloesung-20210107.tex @@ -0,0 +1,357 @@ +% hp-musterloesung-20210107.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: Fakultät, Länge von Strings (Neuauflage), Hexdumps + +\documentclass[a4paper]{article} + +\usepackage{pgscript} +\usepackage{gnuplot-lua-tikz} + +\begin{document} + + \section*{Hardwarenahe Programmierung\\ + Musterlösung zu den Übungsaufgaben -- 7.\ Januar 2021} + + \exercise{Fakultät} + + Die Fakultät $n!$ einer ganzen Zahl $n \ge 0$ ist definiert als: + \begin{eqnarray*} + 1 & \mbox{für} & n = 0, \\ + n \cdot (n-1)! & \mbox{für} & n > 0. + \end{eqnarray*} + + Mit anderen Worten: $n! = 1\cdot2\cdot3\cdot\dots\cdot n$. + + Die folgende Funktion \lstinline{fak()} berechnet die Fakultät \emph{rekursiv} + (Datei: \gitfile{hp}{2020ws/20210107}{aufgabe-1.c}): + + \begin{lstlisting} + int fak (int n) + { + if (n <= 0) + return 1; + else + return n * fak (n - 1); + } + \end{lstlisting} + + \begin{enumerate}[\quad(a)] + \item + Schreiben Sie eine Funktion, die die Fakultät \emph{iterativ} berechnet,\\ + d.\,h.\ mit Hilfe einer Schleife anstelle von Rekursion. + \points{3} + \item + Wie viele Multiplikationen (Landau-Symbol) + erfordern beide Versionen der Fakultätsfunktion\\ + in Abhängigkeit von \lstinline$n$? + Begründen Sie Ihre Antwort. + \points{2} + \item + Wieviel Speicherplatz (Landau-Symbol) + erfordern beide Versionen der Fakultätsfunktion\\ + in Abhängigkeit von \lstinline$n$? + Begründen Sie Ihre Antwort. + \points{3} + \end{enumerate} + + \solution + + \begin{itemize} + \item[(a)] + \textbf{Schreiben Sie eine Funktion, die die Fakultät \emph{iterativ} berechnet,\\ + d.\,h.\ mit Hilfe einer Schleife anstelle von Rekursion.} + + Datei: \gitfile{hp}{2020ws/20210107}{loesung-1.c} + \begin{lstlisting}[gobble=8] + int fak (int n) + { + int f = 1; + for (int i = 2; i <= n; i++) + f *= i; + return f; + } + \end{lstlisting} + + \item[(b)] + \textbf{Wie viele Multiplikationen (Landau-Symbol) + erfordern beide Versionen der Fakultätsfunktion\\ + in Abhängigkeit von \lstinline$n$? + Begründen Sie Ihre Antwort.} + + In beiden Fällen werden $n$ Zahlen miteinander multipliziert -- + oder $n - 1$, wenn man Multiplikationen mit 1 ausspart. + In jedem Fall hängt die Anzahl der Multiplikationen + linear von $n$ ab; es sind $\mathcal{O}(n)$ Multiplikationen. + Insbesondere arbeiten also beide Versionen gleich schnell. + + \item[(c)] + \textbf{Wieviel Speicherplatz (Landau-Symbol) + erfordern beide Versionen der Fakultätsfunktion\\ + in Abhängigkeit von \lstinline$n$? + Begründen Sie Ihre Antwort.} + + Die iterative Version der Funktion benötigt 2 Variable vom Typ \lstinline{int}, + nämlich \lstinline{n} und \lstinline{f}. + Dies ist eine konstante Zahl; + der Speicherplatzverbrauch ist daher $\mathcal{O}(1)$. + + Die rekursive Version der Funktion erzeugt + jedesmal, wenn sie sich selbst aufruft, + eine zusätzliche Variable \lstinline{n}. + Es sind $n + 1$ Aufrufe; die Anzahl der Variablen \lstinline{n} + hängt linear von $n$ ab; der Speicherplatzverbrauch ist also $\mathcal{O}(n)$. + \end{itemize} + + \exercise{Länge von Strings} + + Diese Aufgabe ist eine Neuauflage von Aufgabe 3 der + Übung vom 14.\ November 2019,\\ + ergänzt um die Teilaufgaben (f) und (g). + + \medskip + + Strings werden in der Programmiersprache C durch Zeiger auf \lstinline{char}-Variable realisiert. + + Beispiel: \lstinline{char *hello_world = "Hello, world!\n"} + + Die Systembibliothek stellt eine Funktion \lstinline{strlen()} zur Ermittlung der Länge von Strings\\ + zur Verfügung (\lstinline{#include <string.h>}). + + \begin{enumerate}[\quad(a)] + \item + Auf welche Weise ist die Länge eines Strings gekennzeichnet? + \points{1} + \item + Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"}, + und wieviel Speicherplatz belegt sie?\\ + \points{2} + \item + Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)}, + die die Länge eines Strings zurückgibt.\\ + \points{3} + \end{enumerate} + + \goodbreak + + Wir betrachten nun die folgenden Funktionen (Datei: \gitfile{hp}{2020ws/20210107}{aufgabe-2.c}): + \begin{center} + \begin{minipage}{8cm} + \begin{lstlisting}[gobble=8] + int fun_1 (char *s) + { + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; + } + \end{lstlisting} + \end{minipage}% + \begin{minipage}{6cm} + \vspace*{-1cm} + \begin{lstlisting}[gobble=8] + int fun_2 (char *s) + { + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; + } + \end{lstlisting} + \vspace*{-1cm} + \end{minipage} + \end{center} + \begin{enumerate}[\quad(a)]\setcounter{enumi}{3} + \item + Was bewirken die beiden Funktionen? + \points{2} + \item + Schreiben Sie eine eigene Funktion, + die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},\\ + nur effizienter. + \points{4} + \item + Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen + hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String? + Begründen Sie Ihre Antwort. + Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen. + \points{3} + \item + Von welcher Ordnung (Landau-Symbol) ist Ihre effizientere Funktion?\\ + Begründen Sie Ihre Antwort. + \points{1} + \end{enumerate} + + \solution + + \begin{itemize} + \item[(a)] + \textbf{Auf welche Weise ist die Länge eines Strings gekennzeichnet?} + + Ein String ist ein Array von \lstinline{char}s. + Nach den eigentlichen Zeichen des Strings enthält das Array + \textbf{ein Null-Symbol} (Zeichen mit Zahlenwert 0, + nicht zu verwechseln mit der Ziffer \lstinline{'0'}) als Ende-Markierung. + Die Länge eines Strings ist die Anzahl der Zeichen + \emph{vor\/} diesem Symbol. + + \item[(b)] + {\bf Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"}, + und wieviel Speicherplatz belegt sie?} + + Sie ist 14 Zeichen lang (\lstinline{'\n'} ist nur 1 Zeichen; + das Null-Symbol, das das Ende markiert, zählt hier nicht mit) + und belegt Speicherplatz für 15 Zeichen + (15 Bytes -- einschließlich Null-Symbol / Ende-Markierung). + + \item[(c)] + \textbf{Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)}, + die die Länge eines Strings zurückgibt.} + + Siehe die Dateien \gitfile{hp}{2020ws/20210107}{loesung-2c-1.c} (mit Array-Index) + und \gitfile{hp}{2020ws/20210107}{loesung-2c-2.c} (mit Zeiger-Arithmetik). + Beide Lösungen sind korrekt und arbeiten gleich schnell. + + Die Warnung \lstinline[style=terminal]{conflicting types for built-in function "strlen"} + kann normalerweise ignoriert werden; + auf manchen Systemen (z.\,B.\ MinGW) hat jedoch die eingebaute Funktion \lstinline{strlen()} + beim Linken Vorrang vor der selbstgeschriebenen, + so daß die selbstgeschriebene Funktion nie aufgerufen wird. + In solchen Fällen ist es zulässig, die selbstgeschriebene Funktion + anders zu nennen (z.\,B.\ \lstinline{my_strlen()}). + + \item[(d)] + \textbf{Was bewirken die beiden Funktionen?} + + Beide addieren die Zahlenwerte der im String enthaltenen Zeichen + und geben die Summe als Funktionsergebnis zurück. + + Im Falle des Test-Strings \lstinline{"Hello, world!\n"} + lautet der Rückgabewert 1171 (siehe \gitfile{hp}{2020ws/20210107}{loesung-2d-1.c} und \gitfile{hp}{2020ws/20210107}{loesung-2d-2.c}). + + \item[(e)] + \textbf{Schreiben Sie eine eigene Funktion, + die dieselbe Aufgabe erledigt wie \lstinline{fun_2()}, + nur effizienter.} + + Die Funktion wird effizienter, + wenn man auf den Aufruf von \lstinline{strlen()} verzichtet + und stattdessen die Ende-Prüfung in derselben Schleife vornimmt, + in der man auch die Zahlenwerte der Zeichen des Strings aufsummiert. + + Die Funktion \lstinline{fun_3()} in der Datei \gitfile{hp}{2020ws/20210107}{loesung-2e-1.c} + realisiert dies mit einem Array-Index, + Die Funktion \lstinline{fun_4()} in der Datei \gitfile{hp}{2020ws/20210107}{loesung-2e-2.c} + mit Zeiger-Arithmetik. + Beide Lösungen sind korrekt und arbeiten gleich schnell. + + \textbf{Bemerkung:} Die effizientere Version der Funktion + arbeitet doppelt so schnell wie die ursprüngliche, + hat aber ebenfalls die Ordnung $\mathcal{O}(n)$ -- siehe unten. + + \item[(f)] + \textbf{Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen + hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String? + Begründen Sie Ihre Antwort. + Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen.} + + Vorüberlegung: \lstinline{strlen()} greift in einer Schleife + auf alle Zeichen des Strings der Länge $n$ zu, + hat also $\mathcal{O}(n)$. + + \lstinline{fun_1()} ruft in jedem Schleifendurchlauf + (zum Prüfen der \lstinline{while}-Bedingung) einmal \lstinline{strlen()} auf + und greift anschließend auf ein Zeichen des Strings zu, + hat also $\mathcal{O}\bigl(n\cdot(n+1)\bigr) = \mathcal{O}(n^2)$. + + \lstinline{fun_2()} ruft einmalig \lstinline{strlen()} auf + und greift anschließend in einer Schleife auf alle Zeichen des Strings zu, + hat also $\mathcal{O}(n+n) = \mathcal{O}(n)$. + + \item[(g)] + \textbf{Von welcher Ordnung (Landau-Symbol) ist Ihre effizientere Funktion?\\ + Begründen Sie Ihre Antwort.} + + In beiden o.\,a.\ Lösungsvarianten + -- \gitfile{hp}{2020ws/20210107}{loesung-2e-1.c} + und \gitfile{hp}{2020ws/20210107}{loesung-2e-2.c} -- + arbeitet die Funktion mit einer einzigen Schleife, + die gleichzeitig die Zahlenwerte addiert und das Ende des Strings sucht. + + Mit jeweils einer einzigen Schleife + haben beide Funktionen die Ordnung $\mathcal{O}(n)$. + + \end{itemize} + + \exercise{Hexdumps} + + Das folgende Programm (\gitfile{hp}{2020ws/20210107}{aufgabe-2.c}) liest + einen String ein und gibt die ASCII-Werte der Buchstaben hexadezimal aus. + (Anders als z.\,B.\ \lstinline{scanf()} + akzeptiert die Funktion \lstinline{fgets()} zum Lesen von Strings auch Leerzeichen, + und sie vermeidet Pufferüberläufe.) + \begin{lstlisting}[style=numbered] + #include <stdio.h> + + int main (void) + { + char buffer[100]; + fgets (buffer, 100, stdin); + for (char *p = buffer; *p; p++) + printf ("%02x", *p); + printf ("\n"); + } + \end{lstlisting} + Beispiel: Bei der Eingabe von \lstinline[style=cmd]{Dies ist ein Test.} + erscheint die Ausgabe\\ + \lstinline[style=terminal]{44696573206973742065696e20546573742e0a}. + + Schreiben Sie ein Programm, das diese Umwandlung in umgekehrter Richtung vornimmt, + also z.\,B.\ bei Eingabe von \lstinline[style=cmd]{44696573206973742065696e20546573742e0a} + wieder \lstinline[style=terminal]{Dies ist ein Test.} ausgibt. + + \points{6} + + Hinweis für die Klausur: + Abgabe in digitaler Form ist erwünscht, aber nicht zwingend. + + \solution + + Siehe \gitfile{hp}{2020ws/20210107}{loesung-2.c}. + + Das Programm macht mehrfach davon Gebrauch, + daß in C Zeichen und Zahlen äquivalent sind. + Wenn z.\,B.\ die \lstinline{char}-Variable \lstinline{c} + den Wert \lstinline{'3'} (Ziffer 3) enthält, + dann hat der Ausdruck \lstinline{c - '0'} den Wert \lstinline{3} (Zahlenwert 3). + Hierfür ist es insbesondere nicht nötig, vorauszusetzen, + daß wir den ASCII-Zeichensatz verwenden und \lstinline{'0'} + den Wert \lstinline{48} hat. + + Bei Eingabe von \lstinline[style=cmd]{44696573206973742065696e20546573742e0a} + gibt das Programm zusätzlich eine Leerzeile aus. + Die liegt daran, daß das \lstinline[style=cmd]{0a} am Ende + bereits eine Zeilenschaltung enthält und das Programm mit + \lstinline{printf ("\n")} eine zusätzliche Zeilenschaltung ausgibt. + +\end{document} diff --git a/20210107/hp-uebung-20210107.pdf b/20210107/hp-uebung-20210107.pdf new file mode 100644 index 0000000000000000000000000000000000000000..068a5c491dd2622ecc9223c9fc0cf9ffed8fd762 Binary files /dev/null and b/20210107/hp-uebung-20210107.pdf differ diff --git a/20210107/hp-uebung-20210107.tex b/20210107/hp-uebung-20210107.tex new file mode 100644 index 0000000000000000000000000000000000000000..3e06f4d7420fa1182fce1741aa6bf718df3c7ce5 --- /dev/null +++ b/20210107/hp-uebung-20210107.tex @@ -0,0 +1,203 @@ +% hp-uebung-20210107.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: Fakultät, Länge von Strings (Neuauflage), Hexdumps + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + +% \thispagestyle{empty} + + \section*{Hardwarenahe Programmierung\\ + Übungsaufgaben -- 7.\ Januar 2021} + + Diese Übung enthält Punkteangaben wie in einer Klausur. + Um zu "`bestehen"', müssen Sie innerhalb von 85 Minuten + unter Verwendung ausschließlich zugelassener Hilfsmittel + 15 Punkte (von insgesamt \totalpoints) erreichen. + + \exercise{Fakultät} + + Die Fakultät $n!$ einer ganzen Zahl $n \ge 0$ ist definiert als: + \begin{eqnarray*} + 1 & \mbox{für} & n = 0, \\ + n \cdot (n-1)! & \mbox{für} & n > 0. + \end{eqnarray*} + + Mit anderen Worten: $n! = 1\cdot2\cdot3\cdot\dots\cdot n$. + + Die folgende Funktion \lstinline{fak()} berechnet die Fakultät \emph{rekursiv} + (Datei: \gitfile{hp}{2020ws/20210107}{aufgabe-1.c}): + + \begin{lstlisting} + int fak (int n) + { + if (n <= 0) + return 1; + else + return n * fak (n - 1); + } + \end{lstlisting} + + \begin{enumerate}[\quad(a)] + \item + Schreiben Sie eine Funktion, die die Fakultät \emph{iterativ} berechnet,\\ + d.\,h.\ mit Hilfe einer Schleife anstelle von Rekursion. + \points{3} + \item + Wie viele Multiplikationen (Landau-Symbol) + erfordern beide Versionen der Fakultätsfunktion\\ + in Abhängigkeit von \lstinline$n$? + Begründen Sie Ihre Antwort. + \points{2} + \item + Wieviel Speicherplatz (Landau-Symbol) + erfordern beide Versionen der Fakultätsfunktion\\ + in Abhängigkeit von \lstinline$n$? + Begründen Sie Ihre Antwort. + \points{3} + \end{enumerate} + + \exercise{Länge von Strings} + + Diese Aufgabe ist eine Neuauflage von Aufgabe 3 der + Übung vom 10.\ Dezember 2020,\\ + ergänzt um die Teilaufgaben (f) und (g). + + \medskip + + Strings werden in der Programmiersprache C durch Zeiger auf \lstinline{char}-Variable realisiert. + + Beispiel: \lstinline{char *hello_world = "Hello, world!\n"} + + Die Systembibliothek stellt eine Funktion \lstinline{strlen()} zur Ermittlung der Länge von Strings\\ + zur Verfügung (\lstinline{#include <string.h>}). + + \begin{enumerate}[\quad(a)] + \item + Auf welche Weise ist die Länge eines Strings gekennzeichnet? + \points{1} + \item + Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"}, + und wieviel Speicherplatz belegt sie?\\ + \points{2} + \item + Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)}, + die die Länge eines Strings zurückgibt.\\ + \points{3} + \end{enumerate} + + \goodbreak + + Wir betrachten nun die folgenden Funktionen (Datei: \gitfile{hp}{2020ws/20210107}{aufgabe-2.c}): + \begin{center} + \begin{minipage}{8cm} + \begin{lstlisting}[gobble=8] + int fun_1 (char *s) + { + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; + } + \end{lstlisting} + \end{minipage}% + \begin{minipage}{6cm} + \vspace*{-1cm} + \begin{lstlisting}[gobble=8] + int fun_2 (char *s) + { + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; + } + \end{lstlisting} + \vspace*{-1cm} + \end{minipage} + \end{center} + \begin{enumerate}[\quad(a)]\setcounter{enumi}{3} + \item + Was bewirken die beiden Funktionen? + \points{2} + \item + Schreiben Sie eine eigene Funktion, + die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},\\ + nur effizienter. + \points{4} + \item + Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen + hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String? + Begründen Sie Ihre Antwort. + Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen. + \points{3} + \item + Von welcher Ordnung (Landau-Symbol) ist Ihre effizientere Funktion?\\ + Begründen Sie Ihre Antwort. + \points{1} + \end{enumerate} + + \exercise{Hexdumps} + + Das folgende Programm (\gitfile{hp}{2020ws/20210107}{aufgabe-3.c}) liest + einen String ein und gibt die ASCII-Werte der Buchstaben hexadezimal aus. + (Anders als z.\,B.\ \lstinline{scanf()} + akzeptiert die Funktion \lstinline{fgets()} zum Lesen von Strings auch Leerzeichen, + und sie vermeidet Pufferüberläufe.) + \begin{lstlisting}[style=numbered] + #include <stdio.h> + + int main (void) + { + char buffer[100]; + fgets (buffer, 100, stdin); + for (char *p = buffer; *p; p++) + printf ("%02x", *p); + printf ("\n"); + } + \end{lstlisting} + Beispiel: Bei der Eingabe von \lstinline[style=cmd]{Dies ist ein Test.} + erscheint die Ausgabe\\ + \lstinline[style=terminal]{44696573206973742065696e20546573742e0a}. + + Schreiben Sie ein Programm, das diese Umwandlung in umgekehrter Richtung vornimmt, + also z.\,B.\ bei Eingabe von \lstinline[style=cmd]{44696573206973742065696e20546573742e0a} + wieder \lstinline[style=terminal]{Dies ist ein Test.} ausgibt. + + \points{6} + + 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/20210107/landau-symbols-2.pdf b/20210107/landau-symbols-2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..6b458b6efd8e274824a6dfcaabc4b9c27d196dc4 --- /dev/null +++ b/20210107/landau-symbols-2.pdf @@ -0,0 +1 @@ +../common/landau-symbols-2.pdf \ No newline at end of file diff --git a/20210107/landau-symbols-3.pdf b/20210107/landau-symbols-3.pdf new file mode 120000 index 0000000000000000000000000000000000000000..46efa409b35ff5df763c744a423599cba515d886 --- /dev/null +++ b/20210107/landau-symbols-3.pdf @@ -0,0 +1 @@ +../common/landau-symbols-3.pdf \ No newline at end of file diff --git a/20210107/landau-symbols.pdf b/20210107/landau-symbols.pdf new file mode 120000 index 0000000000000000000000000000000000000000..ca145425bf07439c680632aa0663f84be601a565 --- /dev/null +++ b/20210107/landau-symbols.pdf @@ -0,0 +1 @@ +../common/landau-symbols.pdf \ No newline at end of file diff --git a/20210107/loesung-1.c b/20210107/loesung-1.c new file mode 100644 index 0000000000000000000000000000000000000000..c2d6f6003924627ae97831407c191eaac42a09c1 --- /dev/null +++ b/20210107/loesung-1.c @@ -0,0 +1,16 @@ +#include <stdio.h> + +int fak (int n) +{ + int f = 1; + for (int i = 2; i <= n; i++) + f *= i; + return f; +} + +int main (void) +{ + for (int n = 0; n <= 5; n++) + printf ("%d\n", fak (n)); + return 0; +} diff --git a/20210107/loesung-2c-1.c b/20210107/loesung-2c-1.c new file mode 100644 index 0000000000000000000000000000000000000000..69ddd0e4e749f6ca31bfa3d4f929c333648ef6ea --- /dev/null +++ b/20210107/loesung-2c-1.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int strlen (char *s) +{ + int l = 0; + while (s[l]) + l++; + return l; +} + +int main (void) +{ + printf ("%d\n", strlen ("Hello, world!\n")); + return 0; +} diff --git a/20210107/loesung-2c-2.c b/20210107/loesung-2c-2.c new file mode 100644 index 0000000000000000000000000000000000000000..e783c474e485e80d08a6e86f8ae6e179f5a294f4 --- /dev/null +++ b/20210107/loesung-2c-2.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int strlen (char *s) +{ + char *s0 = s; + while (*s) + s++; + return s - s0; +} + +int main (void) +{ + printf ("%d\n", strlen ("Hello, world!\n")); + return 0; +} diff --git a/20210107/loesung-2d-1.c b/20210107/loesung-2d-1.c new file mode 100644 index 0000000000000000000000000000000000000000..57521382c21fb743c6f5f5c65320bc4ac9360b1a --- /dev/null +++ b/20210107/loesung-2d-1.c @@ -0,0 +1,34 @@ + +#include <stdio.h> + +int strlen (char *s) +{ + int l = 0; + while (s[l]) + l++; + return l; +} + +int fun_1 (char *s) +{ + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; +} + +int fun_2 (char *s) +{ + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; +} + +int main (void) +{ + printf ("%d\n", fun_1 ("Hello, world!\n")); + printf ("%d\n", fun_2 ("Hello, world!\n")); + return 0; +} diff --git a/20210107/loesung-2d-2.c b/20210107/loesung-2d-2.c new file mode 100644 index 0000000000000000000000000000000000000000..5f3f0961129aa16fc9c4510ae21bb77b69913b12 --- /dev/null +++ b/20210107/loesung-2d-2.c @@ -0,0 +1,34 @@ + +#include <stdio.h> + +int strlen (char *s) +{ + char *s0 = s; + while (*s) + s++; + return s - s0; +} + +int fun_1 (char *s) +{ + int x = 0; + for (int i = 0; i < strlen (s); i++) + x += s[i]; + return x; +} + +int fun_2 (char *s) +{ + int i = 0, x = 0; + int len = strlen (s); + while (i < len) + x += s[i++]; + return x; +} + +int main (void) +{ + printf ("%d\n", fun_1 ("Hello, world!\n")); + printf ("%d\n", fun_2 ("Hello, world!\n")); + return 0; +} diff --git a/20210107/loesung-2e-1.c b/20210107/loesung-2e-1.c new file mode 100644 index 0000000000000000000000000000000000000000..74f5add0c5f62cccb8f817d40f860893f496db11 --- /dev/null +++ b/20210107/loesung-2e-1.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int fun_3 (char *s) +{ + int i = 0, x = 0; + while (s[i]) + x += s[i++]; + return x; +} + +int main (void) +{ + printf ("%d\n", fun_3 ("Hello, world!\n")); + return 0; +} diff --git a/20210107/loesung-2e-2.c b/20210107/loesung-2e-2.c new file mode 100644 index 0000000000000000000000000000000000000000..b223d2d17c261d7cf1373a8379def8911a45ccb7 --- /dev/null +++ b/20210107/loesung-2e-2.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int fun_4 (char *s) +{ + int x = 0; + while (*s) + x += *s++; + return x; +} + +int main (void) +{ + printf ("%d\n", fun_4 ("Hello, world!\n")); + return 0; +} diff --git a/20210107/loesung-3.c b/20210107/loesung-3.c new file mode 100644 index 0000000000000000000000000000000000000000..872058ac9fecdcb59ac1104ca67841cb3dc974a9 --- /dev/null +++ b/20210107/loesung-3.c @@ -0,0 +1,28 @@ +#include <stdio.h> + +int read_hex (char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else + { + fprintf (stderr, "invalid hex digit '%c'\n", c); + return 0; + } +} + +int main (void) +{ + char buffer[100]; + fgets (buffer, 100, stdin); + for (char *p = buffer; p[0] && p[1]; p += 2) + { + char c = 16 * read_hex (p[0]) + read_hex (p[1]); + printf ("%c", c); + } + printf ("\n"); +} diff --git a/20210107/loesung-3d-0f.c b/20210107/loesung-3d-0f.c new file mode 100644 index 0000000000000000000000000000000000000000..04b2d3e8956f4790b3f2ffdf3a314994c640513e --- /dev/null +++ b/20210107/loesung-3d-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/20210107/loesung-3d-1.c b/20210107/loesung-3d-1.c new file mode 100644 index 0000000000000000000000000000000000000000..349523a7d99e33ba81094ffbc8907773b5a3a251 --- /dev/null +++ b/20210107/loesung-3d-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/20210107/loesung-3d-2.c b/20210107/loesung-3d-2.c new file mode 100644 index 0000000000000000000000000000000000000000..f831a75eda1f3e784c8e6c1f24a83d9d6b55ee6c --- /dev/null +++ b/20210107/loesung-3d-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/20210107/loesung-3e.c b/20210107/loesung-3e.c new file mode 100644 index 0000000000000000000000000000000000000000..b984d9253b9c379a88f0fc0ca130c88c3103f8f3 --- /dev/null +++ b/20210107/loesung-3e.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/20210107/loesung-3f.c b/20210107/loesung-3f.c new file mode 100644 index 0000000000000000000000000000000000000000..7b949e6365fc3839e6adc7661e0f8b4dd0c059df --- /dev/null +++ b/20210107/loesung-3f.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/20210107/loesung-3g.c b/20210107/loesung-3g.c new file mode 100644 index 0000000000000000000000000000000000000000..b453a52dbe0ef27399255819808b3f6e562ba3ef --- /dev/null +++ b/20210107/loesung-3g.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/20210107/logo-hochschule-bochum-cvh-text-v2.pdf b/20210107/logo-hochschule-bochum-cvh-text-v2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8 --- /dev/null +++ b/20210107/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/20210107/logo-hochschule-bochum.pdf b/20210107/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20210107/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20210107/pendulum.pdf b/20210107/pendulum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..7d1d87305cdb8840a248ff2207538d758464f452 --- /dev/null +++ b/20210107/pendulum.pdf @@ -0,0 +1 @@ +../common/pendulum.pdf \ No newline at end of file diff --git a/20210107/pgscript.sty b/20210107/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20210107/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20210107/pgslides.sty b/20210107/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20210107/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file