diff --git a/20191024/arrays-1.c b/20191024/arrays-1.c new file mode 100644 index 0000000000000000000000000000000000000000..35cf856c63942234116544ac721ff0a47d797b09 --- /dev/null +++ b/20191024/arrays-1.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +int main (void) +{ + int prime[5] = { 2, 3, 5, 7, 11 }; + int *p = prime; + for (int i = 0; i < 5; i++) + printf ("%d\n", *(p + i)); + return 0; +} diff --git a/20191024/arrays-2.c b/20191024/arrays-2.c new file mode 100644 index 0000000000000000000000000000000000000000..fb0a55881e2907aad77a409808016ee3b586bd80 --- /dev/null +++ b/20191024/arrays-2.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +int main (void) +{ + int prime[5] = { 2, 3, 5, 7, 11 }; + int *p = prime; + for (int i = 0; i < 5; i++) + printf ("%d\n", *(p - i)); + return 0; +} diff --git a/20191024/arrays-3.c b/20191024/arrays-3.c new file mode 100644 index 0000000000000000000000000000000000000000..03e07cf7c3217dc62dfa33b5ed629e82c5530799 --- /dev/null +++ b/20191024/arrays-3.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +int main (void) +{ + int prime[5] = { 2, 3, 5, 7, 11 }; + int *p = prime; + for (int i = 0; i < 5000000; i++) + printf ("%d\n", *(p - i)); + return 0; +} diff --git a/20191024/arrays-4.c b/20191024/arrays-4.c new file mode 100644 index 0000000000000000000000000000000000000000..2015ffc6cd5057daaa755294ab4af602559eefa4 --- /dev/null +++ b/20191024/arrays-4.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int main (void) +{ + int prime[5] = { 2, 3, 5, 7, 11 }; + for (int *p = prime; p < prime + 5; p++) + printf ("%d\n", *p); + return 0; +} diff --git a/20191024/arrays-4.s b/20191024/arrays-4.s new file mode 100644 index 0000000000000000000000000000000000000000..f2fa9124f2c742ba94f134f302148f72473c1638 --- /dev/null +++ b/20191024/arrays-4.s @@ -0,0 +1,46 @@ + .file "arrays-4.c" + .section .rodata.str1.1,"aMS",@progbits,1 +.LC0: + .string "%d\n" + .text + .globl main + .type main, @function +main: +.LFB11: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + pushq %rbx + .cfi_def_cfa_offset 24 + .cfi_offset 3, -24 + subq $40, %rsp + .cfi_def_cfa_offset 64 + movl $2, (%rsp) + movl $3, 4(%rsp) + movl $5, 8(%rsp) + movl $7, 12(%rsp) + movl $11, 16(%rsp) + movq %rsp, %rbx + leaq 20(%rsp), %rbp +.L2: + movl (%rbx), %esi + leaq .LC0(%rip), %rdi + movl $0, %eax + call printf@PLT + addq $4, %rbx + cmpq %rbp, %rbx + jne .L2 + movl $0, %eax + addq $40, %rsp + .cfi_def_cfa_offset 24 + popq %rbx + .cfi_def_cfa_offset 16 + popq %rbp + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE11: + .size main, .-main + .ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516" + .section .note.GNU-stack,"",@progbits diff --git a/20191024/arrays-5.c b/20191024/arrays-5.c new file mode 100644 index 0000000000000000000000000000000000000000..d206e6c3296fe7f7e48febd10893a5be65fca67a --- /dev/null +++ b/20191024/arrays-5.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +int main (void) +{ + int prime[5] = { 2, 3, 5, 7, 11 }; + int *p = prime; + for (int i = 0; i < 5; i++) + printf ("%d\n", p[i]); + return 0; +} diff --git a/20191024/arrays-5.s b/20191024/arrays-5.s new file mode 100644 index 0000000000000000000000000000000000000000..23714c0e917afcfe5f2f6f5178aeffdb45a78b82 --- /dev/null +++ b/20191024/arrays-5.s @@ -0,0 +1,52 @@ + .file "arrays-5.c" + .section .rodata.str1.1,"aMS",@progbits,1 +.LC0: + .string "%d\n" + .text + .globl main + .type main, @function +main: +.LFB11: + .cfi_startproc + pushq %r12 + .cfi_def_cfa_offset 16 + .cfi_offset 12, -16 + pushq %rbp + .cfi_def_cfa_offset 24 + .cfi_offset 6, -24 + pushq %rbx + .cfi_def_cfa_offset 32 + .cfi_offset 3, -32 + subq $32, %rsp + .cfi_def_cfa_offset 64 + movl $2, (%rsp) + movl $3, 4(%rsp) + movl $5, 8(%rsp) + movl $7, 12(%rsp) + movl $11, 16(%rsp) + movq %rsp, %rbx + leaq 20(%rsp), %r12 + leaq .LC0(%rip), %rbp +.L2: + movl (%rbx), %esi + movq %rbp, %rdi + movl $0, %eax + call printf@PLT + addq $4, %rbx + cmpq %r12, %rbx + jne .L2 + movl $0, %eax + addq $32, %rsp + .cfi_def_cfa_offset 32 + popq %rbx + .cfi_def_cfa_offset 24 + popq %rbp + .cfi_def_cfa_offset 16 + popq %r12 + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE11: + .size main, .-main + .ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516" + .section .note.GNU-stack,"",@progbits diff --git a/20191024/arrays-6.c b/20191024/arrays-6.c new file mode 100644 index 0000000000000000000000000000000000000000..e4982169bf60d94437539e94f9362840db466486 --- /dev/null +++ b/20191024/arrays-6.c @@ -0,0 +1,12 @@ +#include <stdio.h> + +int main (void) +{ + int a[3] = { 2, 3, 5 }; + int b = 7; + int c = 42; + for (int i = 0; i < 5; i++) + a[i] = 0; + printf ("b = %d, c = %d\n", b, c); + return 0; +} diff --git a/20191024/hp-20191024.pdf b/20191024/hp-20191024.pdf index 9877d0302fe88fcd5b658bb9d5a9e839ef289496..b3a14504dc44817d5d1ad2eabd30a752a05e50d3 100644 Binary files a/20191024/hp-20191024.pdf and b/20191024/hp-20191024.pdf differ diff --git a/20191024/hp-20191024.tex b/20191024/hp-20191024.tex index 620a1545c34ca34ed4c751cbdf9fbf5861671c66..67c4afd0da011710b95d240e08997c5654559f2a 100644 --- a/20191024/hp-20191024.tex +++ b/20191024/hp-20191024.tex @@ -20,7 +20,7 @@ % Attribution-ShareAlike 3.0 Unported License along with this % document. If not, see <http://creativecommons.org/licenses/>. -% README: Einführung in C: Zeiger, Arrays und Strings, Strukturen +% README: Einführung in C: Zeiger, Arrays und Strings \documentclass[10pt,t]{beamer} @@ -69,6 +69,7 @@ \color{red} \item[2.10] Zeiger \item[2.11] Arrays und Strings + \color{black} \item[2.12] Strukturen \item[\dots] \end{itemize} @@ -839,45 +840,45 @@ } \end{lstlisting} \end{onlyenv} - \begin{onlyenv}<8> - \begin{lstlisting}[gobble=6] - #include <stdio.h> - - int main (void) - { - char hello[] = "Hello, world!\n"; - printf ("%s", hello); - return 0; - } - ¡ ¿ - \end{lstlisting} - \end{onlyenv} - \begin{onlyenv}<9> - \begin{lstlisting}[gobble=6] - #include <stdio.h> - - int main (void) - { - char *hello = "Hello, world!\n"; - printf ("%s", hello); - return 0; - } - ¡ ¿ - \end{lstlisting} - \end{onlyenv} - \begin{onlyenv}<10> - \begin{lstlisting}[gobble=6] - #include <stdio.h> - - int main (void) - { - char *hello = "Hello, world!\n"; - while (*hello) - printf ("%c", *hello++); - return 0; - } - \end{lstlisting} - \end{onlyenv} +% \begin{onlyenv}<8> +% \begin{lstlisting}[gobble=6] +% #include <stdio.h> +% +% int main (void) +% { +% char hello[] = "Hello, world!\n"; +% printf ("%s", hello); +% return 0; +% } +% ¡ ¿ +% \end{lstlisting} +% \end{onlyenv} +% \begin{onlyenv}<9> +% \begin{lstlisting}[gobble=6] +% #include <stdio.h> +% +% int main (void) +% { +% char *hello = "Hello, world!\n"; +% printf ("%s", hello); +% return 0; +% } +% ¡ ¿ +% \end{lstlisting} +% \end{onlyenv} +% \begin{onlyenv}<10> +% \begin{lstlisting}[gobble=6] +% #include <stdio.h> +% +% int main (void) +% { +% char *hello = "Hello, world!\n"; +% while (*hello) +% printf ("%c", *hello++); +% return 0; +% } +% \end{lstlisting} +% \end{onlyenv} \vspace{-1.7cm}\hfill \begin{minipage}{6.8cm} @@ -904,14 +905,16 @@ \lstinline|%d|\hspace*{0.5em}dezimal & \lstinline|%c|\hspace*{0.5em}Zeichen\\ \lstinline|%x|\hspace*{0.5em}hexadezimal - \pause - & \lstinline|%s|\hspace*{0.5em}String +% \pause +% & \lstinline|%s|\hspace*{0.5em}String \end{tabular} \vspace*{-1cm} \end{itemize} \end{minipage} \end{frame} +\iffalse + \addtocounter{subsection}{-1} \subsection{Arrays und Strings \protect\color{gray}und Zeichen} @@ -1093,6 +1096,8 @@ \end{frame} +\fi + \nosectionnonumber{\inserttitle} \begin{frame} @@ -1113,9 +1118,10 @@ \item[2.9] Funktionen \color{medgreen} \item[2.10] Zeiger + \color{orange} \item[2.11] Arrays und Strings - \item[2.12] Strukturen \color{red} + \item[2.12] Strukturen \item[2.13] Dateien und Fehlerbehandlung \item[2.14] Parameter des Hauptprogramms \item[2.15] String-Operationen diff --git a/20191024/hp-musterloesung-20191024.pdf b/20191024/hp-musterloesung-20191024.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9382ec40169efc257f442edd6a33d03ea91a578b Binary files /dev/null and b/20191024/hp-musterloesung-20191024.pdf differ diff --git a/20191024/hp-musterloesung-20191024.tex b/20191024/hp-musterloesung-20191024.tex new file mode 100644 index 0000000000000000000000000000000000000000..59697dcb198e528d775b86c501285feb29944543 --- /dev/null +++ b/20191024/hp-musterloesung-20191024.tex @@ -0,0 +1,281 @@ +% hp-musterloesung-20191024.pdf - Solutions to the Exercises on Low-Level Programming / Applied Computer Sciences +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Seltsame Programme, Kalender-Berechnung + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + + \section*{Hardwarenahe Programmierung\\ + Musterlösung zu den Übungsaufgaben -- 24.\ Oktober 2019} + + \exercise{Seltsame Programme} + + Unter \url{https://gitlab.cvh-server.de/pgerwinski/hp/tree/master/20191024} + finden Sie (unter anderem)\\ + die Programme \gitfile{hp}{20191024}{test-1.c}, + \gitfile{hp}{20191024}{test-2.c} und \gitfile{hp}{20191024}{test-3.c}. + + Was bewirken diese Programme, und warum verhalten sie sich so? + + \solution + + \begin{itemize} + \item + \gitfile{hp}{20191024}{test-1.c} + + Hinter \lstinline{return} steht ein Ausdruck mit dem + Komma-Operator. Dieser bewirkt, daß der Wert vor dem Komma + berechnet und ignoriert und danach der Wert nach dem Komma + zurückgegeben wird. + + In diesem Fall wird vor dem Komma der Wert des + \lstinline{printf()}-Aufrufs berechnet und ignoriert. + Als Seiteneffekt gibt das Programm die Zeile + \lstinline[style=terminal]{Hello, world!} aus. + Anschließend wird der Wert \lstinline{0} an \lstinline{return} + übergeben und daher \lstinline{return 0} ausgeführt. + + \item + \gitfile{hp}{20191024}{test-2.c} + + Das Programm gibt die Zeile + \lstinline[style=terminal]{Die Antwort lautet: 42} aus. + + Die \lstinline{if}-Bedingung ist eine Zuweisung \lstinline{b = 42}, + die den zugewiesenen Wert \lstinline{42} zurückgibt. + Weil dieser Wert ungleich Null ist, interpretiert + \lstinline{if} ihn als Wahrheitswert "`wahr"', führt also den + \lstinline{if}-Zweig aus und überspringt den + \lstinline{else}-Zweig. + + \item + \gitfile{hp}{20191024}{test-3.c} + + Das Programm stürzt mit einer Fehlermeldung + "`Speicherzugriffsfehler"' oder "`Schutzverletzung"' ab. + + Der Funktionsaufruf \lstinline{printf (42)} übergibt den + Zahlenwert \lstinline{42} als String, also als einen Zeiger + auf \lstinline{char}-Variable, an die Funktion + \lstinline{printf()}. Diese versucht, auf den Speicher ab + Adresse 42 zuzugreifen, wofür aber das Programm keine + Zugriffsrechte hat. Das Betriebssystem beendet daraufhin das + Programm mit der o.\,a.\ Fehlermeldung. + + Der String \lstinline{"Die Antwort lautet: "} wird nicht + ausgegeben, weil Schreiboperationen aus Effizienzgründen + erst nach einer abgeschlossenen Zeile (\lstinline{"\n"}) + durchgeführt werden. + \end{itemize} + + \clearpage + + \exercise{Kalender-Berechnung} + + Am 3.\,1.\,2009 meldete \emph{heise online\/}: + \begin{quote} + Kunden des ersten mobilen Media-Players von Microsoft + erlebten zum Jahresende eine böse Überraschung: + Am 31.\ Dezember 2008 fielen weltweit alle Zune-Geräte der ersten Generation aus. + Ursache war ein interner Fehler bei der Handhabung von Schaltjahren. + + \strut\hfill\url{http://heise.de/-193332}, + \end{quote} + Der Artikel verweist auf ein Quelltextfragment (Datei: \gitfile{hp}{20191024}{aufgabe-2.c}), + das für einen gegebenen Wert \lstinline{days} + das Jahr und den Tag innerhalb des Jahres + für den \lstinline{days}-ten Tag nach dem 1.\,1.\,1980 berechnen soll: + \begin{lstlisting} + year = ORIGINYEAR; /* = 1980 */ + + while (days > 365) + { + if (IsLeapYear (year)) + { + if (days > 366) + { + days -= 366; + year += 1; + } + } + else + { + days -= 365; + year += 1; + } + } + \end{lstlisting} + Dieses Quelltextfragment enthält schlechten Programmierstil, + nämlich mehrere Code-Verdopplungen: + \begin{itemize} + \item + Die Anweisung \lstinline{year += 1} taucht an zwei Stellen auf. + \item + Es gibt zwei unabhängige Abfragen \lstinline{days > 365} und \lstinline{days > 366}:\\ + eine in einer \lstinline{while}- und die andere in einer \lstinline{if}-Bedingung. + \item + Die Länge eines Jahres wird nicht durch eine Funktion berechnet oder in einer Variablen gespeichert; + stattdessen werden an mehreren Stellen die expliziten numerischen Konstanten 365 und 366 verwendet. + \end{itemize} + Diese Probleme führten am 31.\ Dezember 2008 zu einer Endlosschleife. + + Gut hingegen ist die Verwendung einer Konstanten \lstinline{ORIGINYEAR} + anstelle der Zahl 1980 + sowie die Kapselung der Berechnung der Schaltjahr-Bedingung + in einer Funktion \lstinline{IsLeapYear()}. + + \begin{itemize} + \item[(a)] + Erklären Sie das Zustandekommen der Endlosschleife. + \item[(b)] + Schreiben Sie das Quelltextfragment so um, daß es die beschriebenen Probleme + nicht mehr enthält. + \end{itemize} + + \textbf{Hinweis 1:} Verwenden Sie Ihre eigene Funktion \lstinline{IsLeapYear()}. + + \textbf{Hinweis 2}: Schreiben Sie zusätzlich eine Funktion \lstinline{DaysInYear()}. + + \clearpage + + \solution + + \begin{itemize} + \item[(a)] + \textbf{Erklären Sie das Zustandekommen der Endlosschleife.} + + Das Programm startet mit demjenigen Wert für \lstinline{days}, + der der Anzahl der Tage vom 1.\,1.\,1980 bis zum + 31.\,12.\,2008 entspricht. Die \lstinline{while}-Schleife + läuft zunächst solange korrekt durch, bis \lstinline{year} den + Wert \lstinline{2008} und \lstinline{days} den Wert + \lstinline{366} hat. (Der 31.\,12.\ des Schaltjahres 2008 ist + der 366.\ Tag seines Jahres.) + + Die Bedingung der \lstinline{while}-Schleife ist damit + weiterhin erfüllt; das Programm läuft weiter. + + Da 2008 ein Schaltjahr ist, ist auch die Bedingung der äußeren + \lstinline{if}-Anweisung erfüllt. + + Da \lstinline{days} den Wert 366 hat und dieser nicht größer + als 366 ist, ist die innere \lstinline{if}-Bedingung nicht + erfüllt. Somit wird innerhalb der \lstinline{while}-Schleife + kein weiterer Code ausgeführt, die \lstinline{while}-Bedingung + bleibt erfüllt, und das Programm führt eine Endlosschleife + aus. + + \item[(b)] + \textbf{Schreiben Sie das Quelltextfragment so um, daß es die beschriebenen Probleme + nicht mehr enthält.} + + Um das Programm zu testen, genügt es, das Datum auf den + 31.\,12.\,1980 zu stellen, also \lstinline{days} auf den Wert + 366 zu setzen. Darüberhinaus muß man die Funktion + \lstinline{IsLeapYear()} bereitstellen (vgl.\ Aufgabe 1 vom 17.\,10.\,2019). + + Der Quelltext \gitfile{hp}{20191024}{loesung-2-f1.c} ist eine lauffähige + Version des Programms, die den Fehler (Endlosschleife) + reproduziert. + + \breath + + Es liegt nahe, den Fehler in der \lstinline{while}-Bedingung + zu korrigieren, so daß diese Schaltjahre berücksichtigt. Der + Quelltext \gitfile{hp}{20191024}{loesung-2-f2.c} behebt den Fehler auf diese + Weise mit Hilfe von Und- (\lstinline{&&}) und + Oder-Verknüpfungen (\lstinline{||}) in der + \lstinline{while}-Bedingung. + + Der Quelltext \gitfile{hp}{20191024}{loesung-2-f3.c} vermeidet die umständliche + Formulierung mit \lstinline{&&} und \lstinline{||} durch + Verwendung des ternären Operators \lstinline{?:}. Dieser + stellt eine "`\lstinline{if}-Anweisung für Ausdrücke"' bereit. + In diesem Fall liefert er für die rechte Seite des Vergleichs + \lstinline{days >} den Wert 366 im Falle eines Schaltjahrs + bzw.\ ansonsten den Wert 365. + + Beide Lösungen \gitfile{hp}{20191024}{loesung-2-f2.c} und \gitfile{hp}{20191024}{loesung-2-f3.c} + sind jedoch im Sinne der Aufgabenstellung \textbf{falsch}. + Diese lautet: "`Schreiben Sie das Quelltextfragment so um, + daß es die beschriebenen Probleme nicht mehr enthält."' + Mit den beschriebenen Problemen sind die genannten drei + Code-Verdopplungen gemeint, und diese befinden sich weiterhin + im Quelltext. Damit ist der Fehler zwar "`korrigiert"', aber + das Programm ist eher noch unübersichtlicher geworden, so daß + nicht klar ist, ob es nicht noch weitere Fehler enthält. + + \breath + + Eine richtige Lösung liefert \gitfile{hp}{20191024}{loesung-2-4.c}. Dieses + Programm speichert den Wert der Tage im Jahr in einer + Variablen \lstinline{DaysInYear}. Damit erübrigen sich die + \lstinline{if}-Anweisungen innerhalb der + \lstinline{while}-Schleife, und die damit verbundenen + Code-Verdopplungen verschwinden. + + Etwas unschön ist hierbei die neu hinzugekommene + Code-Verdopplung bei der Berechnung von \lstinline{DaysInYear}. + Diese ist allerdings weniger kritisch als die vorherigen, da + sie nur einmal innerhalb der \lstinline{while}-Schleife + vorkommt und das andere Mal außerhalb derselben. + + Um diese Code-Verdopplung loszuwerden, kann man das + \lstinline{if} durch den \lstinline{?:}-Operator ersetzen und + die Zuweisung innerhalb der \lstinline{while}-Bedingung + vornehmen -- siehe \gitfile{hp}{20191024}{loesung-2-5.c}. Dies ist einer der + seltenen Fälle, in denen ein Programm \emph{übersichtlicher\/} + wird, wenn eine Zuweisung innerhalb einer Bedingung + stattfindet. + + Alternativ kann \lstinline{DaysInYear()} auch eine Funktion + sein -- siehe \gitfile{hp}{20191024}{loesung-2-6.c}. Diese Version ist + wahrscheinlich die übersichtlichste, hat jedoch den Nachteil, + daß die Berechnung von \lstinline{DaysInYear()} zweimal statt + nur einmal pro Schleifendurchlauf erfolgt, wodurch Rechenzeit + verschwendet wird. + + \gitfile{hp}{20191024}{loesung-2-7.c} und \gitfile{hp}{20191024}{loesung-2-8.c} beseitigen + dieses Problem durch eine Zuweisung des Funktionsergebnisses + an eine Variable -- einmal innerhalb der + \lstinline{while}-Bedingung und einmal außerhalb. + Der zweimalige Aufruf der Funktion \lstinline{DaysInYear()} in + \gitfile{hp}{20191024}{loesung-2-8.c} zählt nicht als Code-Verdopplung, denn + der Code ist ja in einer Funktion gekapselt. (Genau dazu sind + Funktionen ja da: daß man sie mehrfach aufrufen kann.) + + \breath + + Fazit: Wenn Sie sich beim Programmieren bei + Cut-And-Paste-Aktionen erwischen, sollten Sie die Struktur + Ihres Programms noch einmal überdenken. + + Wahrscheinlich gibt es dann eine elegantere Lösung, deren + Korrektheit man auf den ersten Blick sieht. + + \end{itemize} + +\end{document} diff --git a/20191024/loesung-2-4.c b/20191024/loesung-2-4.c new file mode 100644 index 0000000000000000000000000000000000000000..d141e32582374a3b3e6955f5634191d15edb3709 --- /dev/null +++ b/20191024/loesung-2-4.c @@ -0,0 +1,41 @@ +#include <stdio.h> + +int IsLeapYear (int year) +{ + if (year % 4) + return 0; + else if (year % 100) + return 1; + else if (year % 400) + return 0; + else + return 1; +} + +int main (void) +{ + int ORIGINYEAR = 1980; + int days = 366; + int year; + + year = ORIGINYEAR; /* = 1980 */ + + int DaysInYear; + if (IsLeapYear (year)) + DaysInYear = 366; + else + DaysInYear = 365; + + while (days > DaysInYear) + { + days -= DaysInYear; + year += 1; + if (IsLeapYear (year)) + DaysInYear = 366; + else + DaysInYear = 365; + } + + printf ("year = %d\ndays = %d\n", year, days); + return 0; +} diff --git a/20191024/loesung-2-5.c b/20191024/loesung-2-5.c new file mode 100644 index 0000000000000000000000000000000000000000..8a71934b7df24a28d11a6696e212aaccc430277f --- /dev/null +++ b/20191024/loesung-2-5.c @@ -0,0 +1,33 @@ +#include <stdio.h> + +int IsLeapYear (int year) +{ + if (year % 4) + return 0; + else if (year % 100) + return 1; + else if (year % 400) + return 0; + else + return 1; +} + +int main (void) +{ + int ORIGINYEAR = 1980; + int days = 366; + int year; + + year = ORIGINYEAR; /* = 1980 */ + + int DaysInYear; + + while (days > (DaysInYear = IsLeapYear (year) ? 366 : 365)) + { + days -= DaysInYear; + year += 1; + } + + printf ("year = %d\ndays = %d\n", year, days); + return 0; +} diff --git a/20191024/loesung-2-6.c b/20191024/loesung-2-6.c new file mode 100644 index 0000000000000000000000000000000000000000..0605571480991d1ec73a8cec50395ddf68ae3135 --- /dev/null +++ b/20191024/loesung-2-6.c @@ -0,0 +1,39 @@ +#include <stdio.h> + +int IsLeapYear (int year) +{ + if (year % 4) + return 0; + else if (year % 100) + return 1; + else if (year % 400) + return 0; + else + return 1; +} + +int DaysInYear (int year) +{ + if (IsLeapYear (year)) + return 366; + else + return 365; +} + +int main (void) +{ + int ORIGINYEAR = 1980; + int days = 366; + int year; + + year = ORIGINYEAR; /* = 1980 */ + + while (days > DaysInYear (year)) + { + days -= DaysInYear (year); + year += 1; + } + + printf ("year = %d\ndays = %d\n", year, days); + return 0; +} diff --git a/20191024/loesung-2-7.c b/20191024/loesung-2-7.c new file mode 100644 index 0000000000000000000000000000000000000000..5c98286730aae146cf587b5f3401eb6eadd17aa7 --- /dev/null +++ b/20191024/loesung-2-7.c @@ -0,0 +1,41 @@ +#include <stdio.h> + +int IsLeapYear (int year) +{ + if (year % 4) + return 0; + else if (year % 100) + return 1; + else if (year % 400) + return 0; + else + return 1; +} + +int DaysInYear (int year) +{ + if (IsLeapYear (year)) + return 366; + else + return 365; +} + +int main (void) +{ + int ORIGINYEAR = 1980; + int days = 366; + int year; + + year = ORIGINYEAR; /* = 1980 */ + + int d; + + while (days > (d = DaysInYear (year))) + { + days -= d; + year += 1; + } + + printf ("year = %d\ndays = %d\n", year, days); + return 0; +} diff --git a/20191024/loesung-2-8.c b/20191024/loesung-2-8.c new file mode 100644 index 0000000000000000000000000000000000000000..e94dc80375b88fd5ff3245e8a99f76a5955b6bb8 --- /dev/null +++ b/20191024/loesung-2-8.c @@ -0,0 +1,42 @@ +#include <stdio.h> + +int IsLeapYear (int year) +{ + if (year % 4) + return 0; + else if (year % 100) + return 1; + else if (year % 400) + return 0; + else + return 1; +} + +int DaysInYear (int year) +{ + if (IsLeapYear (year)) + return 366; + else + return 365; +} + +int main (void) +{ + int ORIGINYEAR = 1980; + int days = 366; + int year; + + year = ORIGINYEAR; /* = 1980 */ + + int d = DaysInYear (year); + + while (days > d) + { + days -= d; + year += 1; + d = DaysInYear (year); + } + + printf ("year = %d\ndays = %d\n", year, days); + return 0; +} diff --git a/20191024/loesung-2-f1.c b/20191024/loesung-2-f1.c new file mode 100644 index 0000000000000000000000000000000000000000..4d511c4fa7ee6a9dfb0bc2f69412eeb48745af56 --- /dev/null +++ b/20191024/loesung-2-f1.c @@ -0,0 +1,42 @@ +#include <stdio.h> + +int IsLeapYear (int year) +{ + if (year % 4) + return 0; + else if (year % 100) + return 1; + else if (year % 400) + return 0; + else + return 1; +} + +int main (void) +{ + int ORIGINYEAR = 1980; + int days = 366; + int year; + + year = ORIGINYEAR; /* = 1980 */ + + while (days > 365) + { + if (IsLeapYear (year)) + { + if (days > 366) + { + days -= 366; + year += 1; + } + } + else + { + days -= 365; + year += 1; + } + } + + printf ("year = %d\ndays = %d\n", year, days); + return 0; +} diff --git a/20191024/loesung-2-f2.c b/20191024/loesung-2-f2.c new file mode 100644 index 0000000000000000000000000000000000000000..a44edb09ffde3d3c77cfe673da862260368c33e3 --- /dev/null +++ b/20191024/loesung-2-f2.c @@ -0,0 +1,43 @@ +#include <stdio.h> + +int IsLeapYear (int year) +{ + if (year % 4) + return 0; + else if (year % 100) + return 1; + else if (year % 400) + return 0; + else + return 1; +} + +int main (void) +{ + int ORIGINYEAR = 1980; + int days = 366; + int year; + + year = ORIGINYEAR; /* = 1980 */ + + while ((IsLeapYear (year) && days > 366) + || (!IsLeapYear (year) && days > 365)) + { + if (IsLeapYear (year)) + { + if (days > 366) + { + days -= 366; + year += 1; + } + } + else + { + days -= 365; + year += 1; + } + } + + printf ("year = %d\ndays = %d\n", year, days); + return 0; +} diff --git a/20191024/loesung-2-f3.c b/20191024/loesung-2-f3.c new file mode 100644 index 0000000000000000000000000000000000000000..dbfe5040274953c3b90d6b2da194c0c8ae64f04f --- /dev/null +++ b/20191024/loesung-2-f3.c @@ -0,0 +1,42 @@ +#include <stdio.h> + +int IsLeapYear (int year) +{ + if (year % 4) + return 0; + else if (year % 100) + return 1; + else if (year % 400) + return 0; + else + return 1; +} + +int main (void) +{ + int ORIGINYEAR = 1980; + int days = 366; + int year; + + year = ORIGINYEAR; /* = 1980 */ + + while (days > (IsLeapYear (year) ? 366 : 365)) + { + if (IsLeapYear (year)) + { + if (days > 366) + { + days -= 366; + year += 1; + } + } + else + { + days -= 365; + year += 1; + } + } + + printf ("year = %d\ndays = %d\n", year, days); + return 0; +} diff --git a/20191024/pointers-1.c b/20191024/pointers-1.c new file mode 100644 index 0000000000000000000000000000000000000000..3bd2e86c08fbe05eb8eb9b42d886e30f8f0be286 --- /dev/null +++ b/20191024/pointers-1.c @@ -0,0 +1,14 @@ +#include <stdio.h> + +void calc_answer (int *a) +{ + *a = 42; +} + +int main (void) +{ + int answer; + calc_answer (&answer); + printf ("The answer is %d.\n", answer); + return 0; +} diff --git a/20191024/pointers-2.c b/20191024/pointers-2.c new file mode 100644 index 0000000000000000000000000000000000000000..421153a64907b61eebbacec398ed4f1fcb487cc6 --- /dev/null +++ b/20191024/pointers-2.c @@ -0,0 +1,14 @@ +#include <stdio.h> + +void calc_answer (int a) +{ + a = 42; +} + +int main (void) +{ + int answer; + calc_answer (answer); + printf ("The answer is %d.\n", answer); + return 0; +} diff --git a/20191024/pointers-3.c b/20191024/pointers-3.c new file mode 100644 index 0000000000000000000000000000000000000000..7867933ea67073e239e5b307d2c219639442be77 --- /dev/null +++ b/20191024/pointers-3.c @@ -0,0 +1,14 @@ +#include <stdio.h> + +void calc_answer (int *a) +{ + *a = 42; +} + +int main (void) +{ + int answer; + calc_answer (answer); + printf ("The answer is %d.\n", answer); + return 0; +} diff --git a/20191024/strings-1.c b/20191024/strings-1.c new file mode 100644 index 0000000000000000000000000000000000000000..81bc3cda8affb6268786ac989dd2907d9a84783a --- /dev/null +++ b/20191024/strings-1.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int main (void) +{ + char hello[] = "Hello, world!\n"; + for (char *p = hello; *p; p++) + printf ("%d", *p); + return 0; +} diff --git a/20191024/strings-2.c b/20191024/strings-2.c new file mode 100644 index 0000000000000000000000000000000000000000..4df32974a15ef2752512cc8b9889381b5a0917cd --- /dev/null +++ b/20191024/strings-2.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int main (void) +{ + char hello[] = "Hello, world!\n"; + for (char *p = hello; *p; p++) + printf ("%c", *p); + return 0; +} diff --git a/20191024/strings-3.c b/20191024/strings-3.c new file mode 100644 index 0000000000000000000000000000000000000000..d4559b4bd31358a25cbc23ecefc1540334e99962 --- /dev/null +++ b/20191024/strings-3.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +int main (void) +{ + for (char *p = "Hello, world!\n"; *p; p++) + printf ("%c", *p); + return 0; +} diff --git a/20191024/strings-4.c b/20191024/strings-4.c new file mode 100644 index 0000000000000000000000000000000000000000..d4559b4bd31358a25cbc23ecefc1540334e99962 --- /dev/null +++ b/20191024/strings-4.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +int main (void) +{ + for (char *p = "Hello, world!\n"; *p; p++) + printf ("%c", *p); + return 0; +} diff --git a/20191031/aufgabe-1.c b/20191031/aufgabe-1.c new file mode 100644 index 0000000000000000000000000000000000000000..ad9d80416bad5c7c0edf9c9d4f175146c92a2755 --- /dev/null +++ b/20191031/aufgabe-1.c @@ -0,0 +1,8 @@ +int fun_1 (char *s1, char *s2) +{ + int result = 1; + for (int i = 0; s1[i] && s2[i]; i++) + if (s1[i] != s2[i]) + result = 0; + return result; +} diff --git a/20191031/aufgabe-2.c b/20191031/aufgabe-2.c new file mode 100644 index 0000000000000000000000000000000000000000..dc58b6e8ee4a7a023654aa0eb3a9715a5b9f75cf --- /dev/null +++ b/20191031/aufgabe-2.c @@ -0,0 +1 @@ +char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);} diff --git a/20191031/aufgabe-3.c b/20191031/aufgabe-3.c new file mode 100644 index 0000000000000000000000000000000000000000..cd80c21b95b5a4c91a43a8b3e849f5e12db183c7 --- /dev/null +++ b/20191031/aufgabe-3.c @@ -0,0 +1,14 @@ +#include <stdio.h> + +int main (void) +{ + int n, i, divisors; + for (n = 0; n < 100; n++) + divisors = 0; + for (i = 0; i < n; i++) + if (n % i == 0) + divisors++; + if (divisors = 2) + printf ("%d ist eine Primzahl.\n", n); + return 0; +} diff --git a/20191031/gitlab.png b/20191031/gitlab.png new file mode 100644 index 0000000000000000000000000000000000000000..5724da8b8338534857e5e845f1f1a9b67f0fab1a Binary files /dev/null and b/20191031/gitlab.png differ diff --git a/20191031/hp-20191031.pdf b/20191031/hp-20191031.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1c32474caa0760f77f580ed33475072b85d8458e Binary files /dev/null and b/20191031/hp-20191031.pdf differ diff --git a/20191031/hp-20191031.tex b/20191031/hp-20191031.tex new file mode 100644 index 0000000000000000000000000000000000000000..af1bf2c904b786da8d04247fce1938b295a177fe --- /dev/null +++ b/20191031/hp-20191031.tex @@ -0,0 +1,931 @@ +% hp-20191031.pdf - Lecture Slides on Low-Level Programming +% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Einführung in C: Arrays und Strings und Zeichen, Strukturen + +\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{31.\ Oktober 2019} + +\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} + \begin{itemize} + \vspace*{-\smallskipamount} + \item[\dots] + \item[2.5] Verzweigungen + \item[2.6] Schleifen + \item[2.7] Strukturierte Programmierung + \item[2.8] Seiteneffekte + \item[2.9] Funktionen + \color{medgreen} + \item[2.10] Zeiger + \color{orange} + \item[2.11] Arrays und Strings + \color{red} + \item[2.12] Strukturen + \item[2.13] Dateien und Fehlerbehandlung + \item[2.14] Parameter des Hauptprogramms + \item[2.15] String-Operationen + \end{itemize} + \color{gray} + \item[\textbf{3}] \textbf{Bibliotheken} + \vspace*{-\smallskipamount} + \item[\textbf{\dots}] +% \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} +% \item[\textbf{5}] \textbf{Algorithmen} +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + +\end{frame} + +\setcounter{section}{1} +\section{Einführung in C} +\setcounter{subsection}{9} +\subsection{Zeiger} + +\begin{frame}[fragile] + \showsubsection + + \begin{lstlisting} + #include <stdio.h> + + void calc_answer (int *a) + { + *a = 42; + } + + int main (void) + { + int answer; + calc_answer (&answer); + printf ("The answer is %d.\n", answer); + return 0; + } + \end{lstlisting} + +% \pause + \vspace{-5cm}\hspace{5cm}% + \begin{minipage}{7cm} + \begin{itemize} + \item + \lstinline{*a} ist eine \lstinline{int}. +% \pause + \item + unärer Operator \lstinline{*}:\\ + Pointer-Dererefenzierung +% \pause + \arrowitem + \lstinline{a} ist ein Zeiger (Pointer) auf eine \lstinline{int}. +% \pause + \bigskip + \item + unärer Operator \lstinline{&}: Adresse + \end{itemize} + \end{minipage} +\end{frame} + +\subsection{Arrays und Strings} + +\begin{frame}[fragile] + \showsubsection + + Ein Zeiger zeigt auf eine Variable\only<2->{ und deren Nachbarn}. + + \bigskip + \pause + \pause + + \begin{onlyenv}<1-8> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + int prime[5] = { 2, 3, 5, 7, 11 }; + int *p = prime; + for (int i = 0; i < 5; i++) + printf ("%d\n", *(p + i)); + return 0; + } + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<9> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + int prime[5] = { 2, 3, 5, 7, 11 }; + int *p = prime; + for (int i = 0; i < 5; i++) + printf ("%d\n", p[i]); + return 0; + } + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<10> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + int prime[5] = { 2, 3, 5, 7, 11 }; + for (int i = 0; i < 5; i++) + printf ("%d\n", prime[i]); + return 0; + } + ¡ ¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<11> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + int prime[5] = { 2, 3, 5, 7, 11 }; + for (int *p = prime; + p < prime + 5; p++) + printf ("%d\n", *p); + return 0; + } + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<12> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + int prime[6] = { 2, 3, 5, 7, 11, 0 }; + for (int *p = prime; *p; p++) + printf ("%d\n", *p); + return 0; + } + ¡ ¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<13-> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + int prime[] = { 2, 3, 5, 7, 11, 0 }; + for (int *p = prime; *p; p++) + printf ("%d\n", *p); + return 0; + } + ¡ ¿ + \end{lstlisting} + \end{onlyenv} + + \pause + \vspace{-3.05cm}\hspace{5.5cm}% + \begin{minipage}{6.5cm} + \begin{itemize} + \item + \lstinline{prime} ist \alt<5->{ein Array}{eine Ansammlung} von\\fünf ganzen Zahlen. + \pause + \pause + \item + \only<6-9>{\begin{picture}(0,0) + \color{red} + \put(-1.6,0.1){\tikz{\draw[-latex](0.0,0.0)--(-1,0);}} + \end{picture}}% + \lstinline{prime} ist ein Zeiger auf eine \lstinline{int}. + \pause + \item + \lstinline{p + i} ist ein Zeiger\\ + auf den \lstinline{i}-ten Nachbarn von \lstinline{*p}. + \pause + \item + \lstinline{*(p + i)} ist der \lstinline{i}-te Nachbar von \lstinline{*p}. + \pause + \item + Andere Schreibweise:\\ + \lstinline{p[i]} statt \lstinline{*(p + i)} + \pause + \pause + \item + Zeiger-Arithmetik:\\ + \lstinline{p++} rückt den Zeiger \lstinline{p}\\ + um eine \lstinline{int} weiter. + \pause + \pause + \item + Array ohne \only<14->{explizite }Längenangabe:\\ + Compiler zählt selbst + \vspace*{-1cm} + \pause + \begin{picture}(0,0) + \put(-5.2,1.0){\makebox(0,0)[br]{\color{red}\bf\shortstack{Die Länge des Arrays\\ist \emph{nicht\/} veränderlich!}}} + \end{picture} + \end{itemize} + \end{minipage} +\end{frame} + +% \begin{frame}[fragile] +% \showsubsection +% +% \begin{lstlisting} +% #include <stdio.h> +% +% int main (void) +% { +% char hello_world[] = "Hello, world!\n"; +% int i = 0; +% while (hello_world[i] != 0) +% printf ("%d", hello_world[i++]); +% return 0; +% } +% \end{lstlisting} +% \end{frame} + +% \begin{frame}[fragile] +% \showsubsection +% +% \begin{lstlisting} +% #include <stdio.h> +% +% int main (void) +% { +% char hello_world[] = "Hello, world!\n"; +% int i = 0; +% while (hello_world[i]) +% printf ("%d", hello_world[i++]); +% return 0; +% } +% \end{lstlisting} +% \end{frame} + +% \begin{frame}[fragile] +% \showsubsection +% +% \begin{lstlisting} +% #include <stdio.h> +% +% int main (void) +% { +% char hello_world[] = "Hello, world!\n"; +% char *p = hello_world; +% while (*p) +% printf ("%c", *p++); +% return 0; +% } +% \end{lstlisting} +% \end{frame} + +\begin{frame}[fragile] + \showsubsection + + \begin{onlyenv}<1-6> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + char hello[] = "Hello, world!\n"; + for (char *p = hello; *p; p++) + printf ("%d", *p); + return 0; + } + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<7> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + char hello[] = "Hello, world!\n"; + for (char *p = hello; *p; p++) + printf ("%c", *p); + return 0; + } + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<8> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + char hello[] = "Hello, world!\n"; + printf ("%s", hello); + return 0; + } + ¡ ¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<9> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + char *hello = "Hello, world!\n"; + printf ("%s", hello); + return 0; + } + ¡ ¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<10> + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + char *hello = "Hello, world!\n"; + while (*hello) + printf ("%c", *hello++); + return 0; + } + \end{lstlisting} + \end{onlyenv} + + \vspace{-1.7cm}\hfill + \begin{minipage}{6.8cm} + \begin{itemize} + \pause[2] + \item + Ein \lstinline{char} ist eine kleinere \lstinline{int}. + \pause + \item + Ein "`String"' in C ist ein Array von \lstinline{char}s\only<4->{,\\ + also ein Zeiger auf \lstinline{char}s}\only<5->{\\ + also ein Zeiger auf (kleinere) Integer}. + \pause + \pause + \pause + \item + Der letzte \lstinline{char} muß 0 sein.\\ + Er kennzeichnet das Ende des Strings. + \pause + \item + Die Formatspezifikation\\ + entscheidet über die Ausgabe:\\[\smallskipamount] + \begin{tabular}{ll} + \lstinline|%d|\hspace*{0.5em}dezimal + & \lstinline|%c|\hspace*{0.5em}Zeichen\\ + \lstinline|%x|\hspace*{0.5em}hexadezimal + \pause + & \lstinline|%s|\hspace*{0.5em}String + \end{tabular} + \vspace*{-1cm} + \end{itemize} + \end{minipage} +\end{frame} + +\addtocounter{subsection}{-1} +\subsection{Arrays und Strings \protect\color{gray}und Zeichen} + +\begin{frame}[fragile] + \showsubsection + + \emph{"`Alles ist Zahl."'\/} -- Schule der Pythagoreer, 6.\ Jh.\ v.\,Chr. + + \medskip + + \begin{center} + \renewcommand{\arraystretch}{1.5} + \begin{tabular}{r} + \lstinline|"Hello"|\\ + \lstinline|'H'|\\ + \lstinline|'a' + 4| + \end{tabular} + \renewcommand{\arraystretch}{1.0} + \begin{tabular}{c} + ist nur eine andere\\ + Schreibweise für + \end{tabular} + \renewcommand{\arraystretch}{1.5} + \begin{tabular}{l} + \lstinline|{ 72, 101, 108, 108, 111, 0 }|\\ + \lstinline|72|\\ + \lstinline|'e'| + \end{tabular} + \renewcommand{\arraystretch}{1.0} + \end{center} + + \begin{itemize} + \item + Welchen Zahlenwert hat \lstinline{'*'} im Zeichensatz (normalerweise: ASCII)?\\ + Welches Zeichen entspricht dem Zahlenwert \lstinline{71}? + + \smallskip + + \begin{lstlisting}[gobble=8] + printf ("%d\n", '*'); + printf ("%c\n", 71); + \end{lstlisting} + \medskip + \item + Ist \lstinline{char ch} ein Großbuchstabe? + + \smallskip + + \begin{lstlisting}[gobble=8] + if (ch >= 'A' && ch <= 'Z') + ... + \end{lstlisting} + \smallskip + \item + Groß- in Kleinbuchstaben umwandeln + + \smallskip + + \begin{lstlisting}[gobble=8] + ch += 'a' - 'A'; + \end{lstlisting} + \end{itemize} + \vspace*{-1cm} +\end{frame} + +\subsection{Strukturen} + +\begin{frame}[fragile] + \showsubsection + + \begin{lstlisting} + #include <stdio.h> + + typedef struct + { + char day, month; + int year; + } + date; + + int main (void) + { + date today = { 24, 10, 2019 }; + printf ("%d.%d.%d\n", today.day, today.month, today.year); + return 0; + } + \end{lstlisting} +\end{frame} + +\begin{frame}[fragile] + \showsubsection + + \vspace*{0.9mm} + \begin{minipage}[b]{6cm} + \begin{lstlisting}[gobble=6] + ¡#include <stdio.h> + + typedef struct + { + char day, month; + int year; + } + date; + + void set_date (date *d) + { + (*d).day = 24; + (*d).month = 10; + (*d).year = 2019; + }¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[b]{6cm} + \begin{lstlisting}[gobble=6] + ¡int main (void) + { + date today; + set_date (&today); + printf ("%d.%d.%d\n", today.day, + today.month, today.year); + return 0; + }¿ + \end{lstlisting} + \end{minipage} +\end{frame} + +\begin{frame}[fragile] + \showsubsection + + \vspace*{0.9mm} + \begin{minipage}[b]{6cm} + \begin{lstlisting}[gobble=6] + ¡#include <stdio.h> + + typedef struct + { + char day, month; + int year; + } + date; + + void set_date (date *d) + { + d->day = 24; + d->month = 10; + d->year = 2019; + }¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[b]{6cm} + \hspace*{-1cm}% + \lstinline{foo->bar} + ist Abkürzung für + \lstinline{(*foo).bar} + + \bigskip + + \visible<2->{% + \hspace*{-1cm}% + Eine Funktion, die mit einem \lstinline{struct} arbeitet,\\ + \hspace*{-1cm}% + kann man eine \newterm{Methode\/} des \lstinline{struct} nennen.} + + \bigskip + \bigskip + + \begin{lstlisting}[gobble=6] + ¡int main (void) + { + date today; + set_date (&today); + printf ("%d.%d.%d\n", today.day, + today.month, today.year); + return 0; + }¿ + \end{lstlisting} + \end{minipage} + +\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} + \begin{itemize} + \vspace*{-\smallskipamount} + \item[\dots] + \item[2.5] Verzweigungen + \item[2.6] Schleifen + \item[2.7] Strukturierte Programmierung + \item[2.8] Seiteneffekte + \item[2.9] Funktionen + \item[2.10] Zeiger + \color{medgreen} + \item[2.11] Arrays und Strings + \item[2.12] Strukturen + \color{red} + \item[2.13] Dateien und Fehlerbehandlung + \item[2.14] Parameter des Hauptprogramms + \item[2.15] String-Operationen + \end{itemize} + \item[\textbf{3}] \textbf{Bibliotheken} + \vspace*{-\smallskipamount} + \item[\textbf{\dots}] +% \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} +% \item[\textbf{5}] \textbf{Algorithmen} +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + +\end{frame} + +\subsection{Dateien und Fehlerbehandlung} + +\begin{frame}[fragile] + \showsubsection + \vspace*{-0.2925cm} + \begin{minipage}[t]{6cm} + \begin{onlyenv}<1> + \begin{lstlisting}[gobble=8] + ¡#include <stdio.h> + + int main (void) + { + FILE *f = fopen ("fhello.txt", "w"); + fprintf (f, "Hello, world!\n"); + fclose (f); + return 0; + }¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<2> + \begin{lstlisting}[gobble=8] + ¡#include <stdio.h> + + int main (void) + { + FILE *f = fopen ("fhello.txt", "w"); + if (f) + { + fprintf (f, "Hello, world!\n"); + fclose (f); + } + return 0; + }¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<3> + \begin{lstlisting}[gobble=8] + ¡#include <stdio.h> + #include <errno.h> + + int main (void) + { + FILE *f = fopen ("fhello.txt", "w"); + if (f) + { + fprintf (f, "Hello, world!\n"); + fclose (f); + } + else + fprintf (stderr, "error #%d\n", errno); + return 0; + }¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<4> + \begin{lstlisting}[gobble=8] + ¡#include <stdio.h> + #include <errno.h> + #include <string.h> + + int main (void) + { + FILE *f = fopen ("fhello.txt", "w"); + if (f) + { + fprintf (f, "Hello, world!\n"); + fclose (f); + } + else + { + char *msg = strerror (errno); + fprintf (stderr, "%s\n", msg); + } + return 0; + }¿ + \end{lstlisting} + \vspace*{-1cm} + \end{onlyenv} + \begin{onlyenv}<5-> + \begin{lstlisting}[gobble=8] + ¡#include <stdio.h> + #include <errno.h> + #include <er¡ror.h> + + int main (void) + { + FILE *f = fopen ("fhello.txt", "w"); + if (!f) + error (-1, errno, "cannot open file"); + fprintf (f, "Hello, world!\n"); + fclose (f); + return 0; + } + \end{lstlisting} + \end{onlyenv} + \end{minipage}\pause\hspace*{-1.5cm}% + \begin{minipage}[t]{8.5cm} + \bigskip + \only<3->{\bigskip} + \begin{itemize} + \item + Wenn die Datei nicht geöffnet werden kann,\\ + gibt \lstinline{fopen()} den Wert \lstinline{NULL} zurück. + \pause + \medskip + \item + \addtolength{\leftskip}{1cm} + Die globale Variable \lstinline{int errno}\\ + enthält dann die Nummer des Fehlers.\\ + Benötigt: \lstinline{#include <errno.h>} + \pause + \medskip + \only<5->{\bigskip} + \item + Die Funktion \lstinline{strerror()} wandelt \lstinline{errno}\\ + in einen Fehlermeldungstext um.\\ + Benötigt: \lstinline{#include <string.h>} + \pause + \medskip + \item + \addtolength{\leftskip}{-1.5cm} + Die Funktion \lstinline{error()} gibt eine Fehlermeldung aus\\ + und beendet das Programm.\\ + Benötigt: \lstinline{#include <er¡¿ror.h>} + \pause + \medskip + \item + \textbf{Niemals Fehler einfach ignorieren!} + \end{itemize} + \addtolength{\leftskip}{0.5cm} + \end{minipage} +\end{frame} + +\subsection{Parameter des Hauptprogramms} + +\begin{frame}[fragile] + + \showsubsection + + \begin{lstlisting} + #include <stdio.h> + + int main (int argc, char **argv) + { + printf ("argc = %d\n", argc); + for (int i = 0; i < argc; i++) + printf ("argv[%d] = \"%s\"\n", i, argv[i]); + return 0; + } + \end{lstlisting} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \begin{lstlisting} + #include <stdio.h> + + int main (int argc, char **argv) + { + printf ("argc = %d\n", argc); + for (int i = 0; *argv; i++, argv++) + printf ("argv[%d] = \"%s\"\n", i, *argv); + return 0; + } + \end{lstlisting} + +\end{frame} + +\subsection{String-Operationen} + +\begin{frame}[fragile] + + \showsubsection + + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char hello[] = "Hello, world!\n"; + + printf ("%s\n", hello); + printf ("%zd\n", strlen (hello)); + + printf ("%s\n", hello + 7); + printf ("%zd\n", strlen (hello + 7)); + + hello[5] = 0; + printf ("%s\n", hello); + printf ("%zd\n", strlen (hello)); + + return 0; + } + \end{lstlisting} + \vspace*{-1cm} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char *anton = "Anton"; + char *zacharias = "Zacharias"; + + printf ("%d\n", strcmp (anton, zacharias)); + printf ("%d\n", strcmp (zacharias, anton)); + printf ("%d\n", strcmp (anton, anton)); + + char buffer[100] = "Huber "; + strcat (buffer, anton); + printf ("%s\n", buffer); + + return 0; + } + \end{lstlisting} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char buffer[100] = ""; + sprintf (buffer, "Die Antwort lautet: %d", 42); + printf ("%s\n", buffer); + + char *answer = strstr (buffer, "Antwort"); + printf ("%s\n", answer); + printf ("found at: %zd\n", answer - buffer); + + return 0; + } + \end{lstlisting} + +\end{frame} + +\begin{frame} + + \showsection + + Sprachelemente weitgehend komplett + + \bigskip + Es fehlen: + \begin{itemize} + \item + Ergänzungen (z.\,B.\ ternärer Operator, \lstinline{union}, \lstinline{unsigned}, \lstinline{volatile}) + \item + Bibliotheksfunktionen (z.\,B.\ \lstinline{malloc()}) + \arrowitem + werden eingeführt, wenn wir sie brauchen + \bigskip + \item + Konzepte (z.\,B.\ rekursive Datenstrukturen, Klassen selbst bauen) + \arrowitem + werden eingeführt, wenn wir sie brauchen, oder: + \arrowitem + Literatur\\[\smallskipamount] + (z.\,B.\ Wikibooks: C-Programmierung,\\ + Dokumentation zu Compiler und Bibliotheken) + \bigskip + \item + Praxiserfahrung + \arrowitem + Übung und Praktikum: nur Einstieg + \arrowitem + selbständig arbeiten + \end{itemize} +\end{frame} + +\end{document} diff --git a/20191031/hp-uebung-20191031.pdf b/20191031/hp-uebung-20191031.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a102194cf3950d93579ee6c74bd8a96fa823a42d Binary files /dev/null and b/20191031/hp-uebung-20191031.pdf differ diff --git a/20191031/hp-uebung-20191031.tex b/20191031/hp-uebung-20191031.tex new file mode 100644 index 0000000000000000000000000000000000000000..d32c823f2f36ba797d0e432da94f9306b0eb9d9c --- /dev/null +++ b/20191031/hp-uebung-20191031.tex @@ -0,0 +1,127 @@ +% hp-uebung-20191031.pdf - Exercises on Low-Level Programming / Applied Computer Sciences +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\thispagestyle{empty} + +\begin{document} + + \thispagestyle{empty} + + \section*{Hardwarenahe Programmierung\\ + Übungsaufgaben -- 31.\ Oktober 2019} + + \exercise{Strings} + + Strings werden in der Programmiersprache C + durch Zeiger auf \lstinline{char}-Variable realisiert. + + Wir betrachten die folgende Funktion (Datei: \gitfile{hp}{20191031}{aufgabe-1.c}): + \begin{center} + \begin{minipage}{8cm} + \begin{lstlisting}[gobble=8] + int fun_1 (char *s1, char *s2) + { + int result = 1; + for (int i = 0; s1[i] && s2[i]; i++) + if (s1[i] != s2[i]) + result = 0; + return result; + } + \end{lstlisting} + \end{minipage}% + \end{center} + \begin{itemize} + \item[(a)] + Was bewirkt die Funktion? % \points{3} + \item[(b)] + Welchen Sinn hat die Bedingung "`\lstinline{s1[i] && s2[i]}"' + in der \lstinline{for}-Schleife? % \points{2} + \item[(c)] + Was würde sich ändern, wenn die Bedingung "`\lstinline{s1[i] && s2[i]}"' + in der \lstinline{for}-Schleife\\ + zu "`\lstinline{s1[i]}"' verkürzt würde? % \points{3} +% \item[(d)] +% Von welcher Ordnung (Landau-Symbol) ist die Funktion \lstinline{fun_1()} +% hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen in den Strings +% -- und warum? % \points{2} + \item[(d)] + Schreiben Sie eine eigene Funktion, + die dieselbe Aufgabe erledigt wie \lstinline{fun_1()}, nur effizienter. +% und geben Sie die Ordnung (Landau-Symbol) der von Ihnen geschriebenen Funktion an. % \points{5} + \end{itemize} + + \exercise{Programm analysieren} + + Wir betrachten das folgende C-Programm (Datei: \gitfile{hp}{20191031}{aufgabe-2.c}): + \begin{lstlisting} + char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);} + \end{lstlisting} + \vspace{-\medskipamount} + \begin{itemize} + \item[(a)] + Was bewirkt dieses Programm? + \item[(b)] + Wofür stehen die Zahlen? + \item[(c)] + Ergänzen Sie das Programm derart, daß seine \lstinline{main()}-Funktion + \lstinline{int main (void)} lautet und eine \lstinline{return}-Anweisung hat, + wobei die in Aufgabenteil (a) festgestellte Eigenschaft erhalten bleiben soll. + \end{itemize} + + \exercise{Fehlerhaftes Primzahl-Programm} + + \begin{minipage}[t]{5.5cm} + Das nebenstehende Primzahlsuchprogramm (Datei: \gitfile{hp}{20191031}{aufgabe-3.c}) + soll Zahlen ausgeben, die genau zwei Teiler haben, ist aber fehlerhaft. + + \smallskip + + Korrigieren Sie das Programm derart, daß ein Programm entsteht, + welches alle Primzahlen kleiner 100 ausgibt.% \points 5 + \end{minipage}\hfill + \begin{minipage}[t]{9cm} + \vspace*{-0.5cm} + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + int main (void) + { + int n, i, divisors; + for (n = 0; n < 100; n++) + divisors = 0; + for (i = 0; i < n; i++) + if (n % i == 0) + divisors++; + if (divisors = 2) + printf ("%d ist eine Primzahl.\n", n); + return 0; + } + \end{lstlisting} + \end{minipage} + +\end{document} diff --git a/20191031/logo-hochschule-bochum-cvh-text-v2.pdf b/20191031/logo-hochschule-bochum-cvh-text-v2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8 --- /dev/null +++ b/20191031/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/20191031/logo-hochschule-bochum.pdf b/20191031/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20191031/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20191031/pgscript.sty b/20191031/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20191031/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20191031/pgslides.sty b/20191031/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20191031/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file diff --git a/README.md b/README.md index b39e399e0ebaf7db92c3b3c2214317ba9b8b21b1..2ef89e24a5be0a3912dac201dfff74c0d31c43c7 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,8 @@ Vortragsfolien und Beispiele: ----------------------------- * [10.10.2019: Einführung, Einführung in C (bis Schleifen)](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191010/hp-20191010.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/master/20191010/) * [17.10.2019: Einführung in C: Seiteneffekte, Funktionen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191017/hp-20191017.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/master/20191017/) - * [24.10.2019: Einführung in C: Zeiger, Arrays und Strings, Strukturen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191024/hp-20191024.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/master/20191024/) + * [24.10.2019: Einführung in C: Zeiger, Arrays und Strings](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191024/hp-20191024.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/master/20191024/) + * [31.10.2019: Einführung in C: Arrays und Strings und Zeichen, Strukturen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191031/hp-20191031.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/master/20191031/) * [alle in 1 Datei](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/hp-slides-2019ws.pdf) Übungsaufgaben: @@ -27,10 +28,12 @@ Vortragsfolien und Beispiele: * [10.10.2019: Hello-World-Programme, Schaltjahr ermitteln, Maximum berechnen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191010/hp-uebung-20191010.pdf) * [17.10.2019: Schaltjahr ermitteln, Multiplikationstabelle, Fibonacci-Zahlen, fehlerhaftes Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191017/hp-uebung-20191017.pdf) * [24.10.2019: Seltsame Programme, Kalender-Berechnung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191024/hp-uebung-20191024.pdf) + * [31.10.2019: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191031/hp-uebung-20191031.pdf) Musterlösungen: --------------- * [17.10.2019: Schaltjahr ermitteln, Multiplikationstabelle, Fibonacci-Zahlen, fehlerhaftes Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191017/hp-musterloesung-20191017.pdf) + * [24.10.2019: Seltsame Programme, Kalender-Berechnung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191024/hp-musterloesung-20191024.pdf) Tafelbilder: ------------ diff --git a/hp-slides-2019ws.pdf b/hp-slides-2019ws.pdf index 18be7be511d45261200f26e3b1068d0e92d11675..76d7c0332d847c718b6e414631fad1a7021e8c32 100644 Binary files a/hp-slides-2019ws.pdf and b/hp-slides-2019ws.pdf differ diff --git a/hp-slides-2019ws.tex b/hp-slides-2019ws.tex index bd64bffd73b26d442d4ac01f2235962e578f00c1..2d58287f8f60da4446bbbc193509525efe61b9ed 100644 --- a/hp-slides-2019ws.tex +++ b/hp-slides-2019ws.tex @@ -12,8 +12,10 @@ \includepdf[pages=2-]{script/hp-slides-title-2019ws.pdf} \pdfbookmark[1]{10.10.2019: Einführung, Einführung in C (bis Schleifen)}{20191010} \includepdf[pages=-]{20191010/hp-20191010.pdf} - \pdfbookmark[1]{17.10.2019: Einführung in C: Seiteneffekte, Funktionen, Zeiger, Arrays und Strings}{20191017} + \pdfbookmark[1]{17.10.2019: Einführung in C: Seiteneffekte, Funktionen}{20191017} \includepdf[pages=-]{20191017/hp-20191017.pdf} - \pdfbookmark[1]{24.10.2019: Einführung in C: Zeiger, Arrays und Strings, Strukturen}{20191024} + \pdfbookmark[1]{24.10.2019: Einführung in C: Zeiger, Arrays und Strings}{20191024} \includepdf[pages=-]{20191024/hp-20191024.pdf} + \pdfbookmark[1]{31.10.2019: Einführung in C: Arrays und Strings und Zeichen, Strukturen}{20191031} + \includepdf[pages=-]{20191031/hp-20191031.pdf} \end{document}