diff --git a/20211018/hp-20211018.tex b/20211018/hp-20211018.tex index 240819a3dc630b25e7937788255c1be853a5c374..e9fa799f358c24b28a875ed0553fc2141854695c 100644 --- a/20211018/hp-20211018.tex +++ b/20211018/hp-20211018.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 +% README: Einführung in C: Arrays und Strings, Strukturen \documentclass[10pt,t]{beamer} diff --git a/20211025/aufgabe-1.c b/20211025/aufgabe-1.c new file mode 100644 index 0000000000000000000000000000000000000000..ad9d80416bad5c7c0edf9c9d4f175146c92a2755 --- /dev/null +++ b/20211025/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/20211025/aufgabe-2-1.c b/20211025/aufgabe-2-1.c new file mode 100644 index 0000000000000000000000000000000000000000..e56af8cdd1c1abcac992605475472612878b786d --- /dev/null +++ b/20211025/aufgabe-2-1.c @@ -0,0 +1,6 @@ +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/20211025/aufgabe-2-2.c b/20211025/aufgabe-2-2.c new file mode 100644 index 0000000000000000000000000000000000000000..9d3e005456a7316340a5c5d404e7d6f911487771 --- /dev/null +++ b/20211025/aufgabe-2-2.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +char *f = "char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c"; + +int main (void) +{ + printf (f, 34, f, 34, 10); + return 0; +} diff --git a/20211025/aufgabe-2.c b/20211025/aufgabe-2.c new file mode 100644 index 0000000000000000000000000000000000000000..dc58b6e8ee4a7a023654aa0eb3a9715a5b9f75cf --- /dev/null +++ b/20211025/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/20211025/aufgabe-3.c b/20211025/aufgabe-3.c new file mode 100644 index 0000000000000000000000000000000000000000..cd80c21b95b5a4c91a43a8b3e849f5e12db183c7 --- /dev/null +++ b/20211025/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/20211025/hp-20211025.pdf b/20211025/hp-20211025.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b99f2f6716dff85543d90e9dde0917cb7688e95d Binary files /dev/null and b/20211025/hp-20211025.pdf differ diff --git a/20211025/hp-20211025.tex b/20211025/hp-20211025.tex new file mode 100644 index 0000000000000000000000000000000000000000..e14ab656150850d32c79be29d453e05c32b1b6e4 --- /dev/null +++ b/20211025/hp-20211025.tex @@ -0,0 +1,956 @@ +% hp-20211025.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: Einführung in C: Arrays und Strings und Zeichen, Strukturen, Dateien und Fehlerbehandlung + +\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{25.\ Oktober 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} + \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} + \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}{10} +\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? + + \vspace{-\medskipamount} + + \begin{lstlisting}[gobble=8] + printf ("%d\n", '*'); + \end{lstlisting} + + \smallskip + + (normalerweise: ASCII) + \medskip + \item + Ist \lstinline{char ch} ein Großbuchstabe? + + \vspace{-\medskipamount} + + \begin{lstlisting}[gobble=8] + char ch = 'M'; + if (ch >= 'A' && ch <= 'Z') + ... + \end{lstlisting} + \medskip + \item + Groß- in Kleinbuchstaben umwandeln + + \vspace{-\medskipamount} + + \begin{lstlisting}[gobble=8] + ch += 'a' - 'A'; + \end{lstlisting} + \end{itemize} +\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 = { 25, 10, 2021 }; + 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 = 25; + (*d).month = 10; + (*d).year = 2021; + }¿ + \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 = 25; + d->month = 10; + d->year = 2021; + }¿ + \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} + \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} + +\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 + + \vspace*{-0.4cm} + \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 + + \vspace*{-0.4cm} + \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} + \vspace*{-1cm} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \vspace*{-0.4cm} + \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} + \vspace*{-1cm} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \vspace*{-0.4cm} + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char buffer[100] = ""; + snprintf (buffer, 100, "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} + +\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 + \item[2.11] Arrays und Strings + \item[2.12] Strukturen + \color{medgreen} + \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} + +\end{document} diff --git a/20211025/hp-musterloesung-20211025.pdf b/20211025/hp-musterloesung-20211025.pdf new file mode 100644 index 0000000000000000000000000000000000000000..11dff33541836bdf62664d90cfe4169cc0b43ba5 Binary files /dev/null and b/20211025/hp-musterloesung-20211025.pdf differ diff --git a/20211025/hp-musterloesung-20211025.tex b/20211025/hp-musterloesung-20211025.tex new file mode 100644 index 0000000000000000000000000000000000000000..1266ef73b5d0767c1a0b83fb868bf50016f03602 --- /dev/null +++ b/20211025/hp-musterloesung-20211025.tex @@ -0,0 +1,414 @@ +% hp-musterloesung-20211025.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: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + + \section*{Hardwarenahe Programmierung\\ + Musterlösung zu den Übungsaufgaben -- 25.\ Oktober 2021} + + \exercise{Strings} + + Strings werden in der Programmiersprache C + durch Zeiger auf \lstinline{char}-Variable realisiert. + + Wir betrachten die folgende Funktion (Datei: \gitfile{hp}{2021ws/20211025}{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} + + \solution + + \begin{itemize} + \item[(a)] + \textbf{Was bewirkt die Funktion?} + + Sie vergleicht zwei Strings miteinander bis zur Länge des kürzeren Strings + und gibt bei Gleichheit 1 zurück, ansonsten 0. + + Mit anderen Worten: + Die Funktion prüft, ob zwei Strings bis zur Länge des kürzeren übereinstimmen, + und gibt bei Gleichheit 1 zurück, ansonsten 0. + + Die Funktion prüft insbesondere \textbf{nicht} zwei Strings auf Gleichheit, + und sie ist \textbf{nicht} funktionsgleich zur + Standard-Bibliotheksfunktion \lstinline{strcmp()}. + + \item[(b)] + \textbf{Welchen Sinn hat die Bedingung "`\lstinline{s1[i] && s2[i]}"' + in der \lstinline{for}-Schleife?} + + Die Bedingung prüft, ob \emph{bei einem der beiden Strings\/} + die Ende-Markierung (Null-Symbol) erreicht ist. + Falls ja, wird die Schleife beendet. + + \item[(c)] + \textbf{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?} + + In diesem Fall würde nur für \lstinline{s1} geprüft, + ob das Ende erreicht ist. + Wenn \lstinline{s1} länger ist als \lstinline{s2}, + würde \lstinline{s2} über sein Ende hinaus ausgelesen. + Dies kann zu Lesezugriffen auf Speicher außerhalb des Programms + und damit zu einem Absturz führen + ("`Speicherzugriffsfehler"', "`Schutzverletzung"'). + + \item[(d)] + \textbf{Schreiben Sie eine eigene Funktion, + die dieselbe Aufgabe erledigt wie \lstinline{fun_1()}, nur effizienter.} + + Die Effizienz läßt sich steigern, indem man die Schleife abbricht, + sobald das Ergebnis feststeht. + Es folgen drei Möglichkeiten, dies zu realisieren. + \end{itemize} + + \begin{center} + \begin{minipage}[t]{8cm} + Erweiterung der Schleifenbedingung: + + \begin{lstlisting}[gobble=8] + int fun_2 (char *s1, char *s2) + { + int result = 1; + for (int i = 0; s1[i] && s2[i] && result; i++) + if (s1[i] != s2[i]) + result = 0; + return result; + } + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{6cm} + Verwendung von \lstinline{return}: + + \begin{lstlisting}[gobble=8] + int fun_3 (char *s1, char *s2) + { + for (int i = 0; s1[i] && s2[i]; i++) + if (s1[i] != s2[i]) + return 0; + return 1; + } + \end{lstlisting} + \end{minipage} + \end{center} + \vspace*{-1cm}\goodbreak + + \begin{center} + \begin{minipage}{9cm} + Die nebenstehende Lösung unter Verwendung von \lstinline{break} + ist zwar ebenfalls richtig, aber länger und weniger übersichtlich + als die beiden anderen Lösungen. + + \smallskip + + Die Datei \gitfile{hp}{2021ws/20211025}{loesung-1.c} enthält ein Testprogramm + für alle o.\,a.\ Lösungen. + Das Programm testet nur die offensichtlichsten Fälle; + für den Einsatz der Funktionen in einer Produktivumgebung + wären weitaus umfassendere Tests erforderlich. + + \smallskip + + Das Testprogramm enthält String-Zuweisungen wie z.\,B.\ + \lstinline{s2 = "Apfel"}. + Dies funktioniert, weil wir damit einen Zeiger (\lstinline{char *s2}) + auf einen neuen Speicherbereich (\lstinline{"Apfel"}) zeigen lassen. + Eine entsprechende Zuweisung zwischen Arrays + (\lstinline{char s3[] = "Birne"; s3 = "Pfirsich";)} + funktioniert \emph{nicht}. + + \end{minipage}\hspace*{1cm}% + \begin{minipage}{6cm} + \begin{lstlisting}[gobble=8] + int fun_4 (char *s1, char *s2) + { + int result = 1; + for (int i = 0; s1[i] && s2[i]; i++) + if (s1[i] != s2[i]) + { + result = 0; + break; + } + return result; + } + \end{lstlisting} + \end{minipage} + \end{center} + + \exercise{Programm analysieren} + + Wir betrachten das folgende C-Programm (Datei: \gitfile{hp}{2021ws/20211025}{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} + + \solution + + \begin{itemize} + \item[(a)] + \textbf{Was bewirkt dieses Programm?} + + Es gibt \emph{seinen eigenen Quelltext\/} aus. + + (Wichtig ist die Bezugnahme auf den eigenen Quelltext. + Die Angabe\\ + "`Es gibt + \lstinline|char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}| + aus"'\\ + genügt insbesondere nicht.) + + \item[(b)] + \textbf{Wofür stehen die Zahlen?} + + Die 34 steht für ein Anführungszeichen und die 10 für ein + Zeilenendezeichen (\lstinline{\n}). + + Hintergrund: Um den eigenen Quelltext ausgeben zu können, muß + das Programm auch Anführungszeichen und Zeilenendezeichen + ausgeben. Dies geschieht normalerweise mit vorangestelltem + Backslash: \lstinline{\"} bzw.\ \lstinline{\n}. Um dann aber + den Backslash ausgeben zu können, müßte man diesem ebenfalls + einen Backslash voranstellen: \lstinline{\\}. Damit dies nicht + zu einer Endlosschleife wird, verwendet der Programmierer + dieses Programms den Trick mit den Zahlen, die durch + \lstinline{%c} als Zeichen ausgegeben werden. + + \item[(c)] + \textbf{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.} + + Datei: \gitfile{hp}{2021ws/20211025}{loesung-2.c} + \begin{lstlisting}[gobble=8] + char*f="char*f=%c%s%c;int main(void){printf(f,34,f,34,10);return 0;}%c"; + int main(void){printf(f,34,f,34,10);return 0;} + \end{lstlisting} + Das Programm ist eine einzige, lange Zeile, die hier nur aus + Platzgründen als zwei Zeilen abgedruckt wird. Auf das + Semikolon am Ende der "`ersten Zeile"' folgt unmittelbar -- ohne Leerzeichen -- + das Schlüsselwort \lstinline{int} am Anfang der "`zweiten Zeile"'. + + Mit "`die in Aufgabenteil (a) festgestellte Eigenschaft"' ist + gemeint, daß das Programm weiterhin seinen eigenen Quelltext + ausgeben soll. Die Herausforderung dieser Aufgabe besteht + darin, das Programm zu modifizieren, ohne diese Eigenschaft zu + verlieren. + + Zusatzaufgabe für Interessierte: Ergänzen Sie das Programm so, + daß es auch mit \lstinline[style=cmd]{-Wall} ohne Warnungen + compiliert werden kann. + + Hinweis dazu: \lstinline{#include<stdio.h>} + (ohne Leerzeichen, um Platz zu sparen) + + Lösung der Zusatzaufgabe: \gitfile{hp}{2021ws/20211025}{loesung-2x.c} + + \end{itemize} + + \exercise{Fehlerhaftes Primzahl-Programm} + + \begin{minipage}[t]{5.5cm} + Das nebenstehende Primzahlsuchprogramm (Datei: \gitfile{hp}{2021ws/20211025}{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} + + \solution + + Beim Compilieren des Beispiel-Programms mit + \lstinline[style=cmd]{gcc -Wall} erhalten wir die folgende Warnung: + \begin{lstlisting}[style=terminal] + aufgabe-2.c:11:5: warning: suggest parentheses around assignment + used as truth value [-Wparentheses] + \end{lstlisting} + Beim Ausführen gibt das Programm die folgende (falsche) Behauptung aus: + \begin{lstlisting}[style=terminal] + 100 ist eine Primzahl. + \end{lstlisting} + + Einen ersten Hinweis auf den Fehler im Programm liefert die Warnung. + Die Bedingung \lstinline{if (divisors = 2)} in Zeile 11 + steht \emph{nicht\/} für einen Vergleich + der Variablen \lstinline{divisors} mit der Zahl 2, + sondern für eine Zuweisung der Zahl 2 an die Variable \lstinline{divisors}. + Neben dem \emph{Seiteneffekt\/} der Zuweisung gibt \lstinline{divisors = 2} + den Wert \lstinline{2} zurück. + Als Bedingung interpretiert, hat \lstinline{2} den Wahrheitswert "`wahr"' ("`true"'); + die \lstinline{printf()}-Anweisung wird daher in jedem Fall ausgeführt. + + Korrektur dieses Fehlers: \lstinline{if (divisors == 2)} + -- siehe die Datei \gitfile{hp}{2021ws/20211025}{loesung-2-1.c}. + + \bigskip + + Nach der Korrektur dieses Fehlers compiliert das Programm ohne Warnung, + gibt aber beim Ausführen die folgende Fehlermeldung aus: + \begin{lstlisting}[style=terminal] + Gleitkomma-Ausnahme + \end{lstlisting} + (Bemerkung: Bei ausgeschalteter Optimierung + -- \lstinline[style=cmd]{gcc} ohne \lstinline[style=cmd]{-O} -- + kommt diese Fehlermeldung bereits beim ersten Versuch, das Programm auszuführen. + Der Grund für dieses Verhalten ist, daß bei eingeschalteter Optimierung + irrelevante Teile des Programms entfernt und gar nicht ausgeführt werden, + so daß der Fehler nicht zum Tragen kommt. + In diesem Fall wurde die Berechnung von \lstinline{divisors} komplett wegoptimiert, + da der Wert dieser Variablen nirgendwo abgefragt, + sondern durch die Zuweisung \lstinline{if (divisors = 2)} + sofort wieder überschrieben wurde.) + + Die Fehlermeldung "`\lstinline[style=terminal]{Gleitkomma-Ausnahme}"' + ist insofern irreführend, als daß hier gar keine Gleitkommazahlen im Spiel sind; + andererseits deutet sie auf einen Rechenfehler hin, was auch tatsächlich zutrifft. + Durch Untersuchen aller Rechenoperationen + -- z.\,B.\ durch das Einfügen zusätzlicher \lstinline{printf()} -- + finden wir den Fehler in Zeile 9: + Die Modulo-Operation \lstinline{n % i} ist eine Division, + die dann fehlschlägt, wenn der Divisor \lstinline{i} den Wert 0 hat. + Die Fehlerursache ist die bei 0 beginnende \lstinline{for}-Schleife in Zeile 8: + \lstinline{for (i = 0; i < n; i++)}. + + Korrektur dieses Fehlers: Beginn der Schleife mit \lstinline{i = 1} + statt \lstinline{i = 0} -- siehe die Datei \gitfile{hp}{2021ws/20211025}{loesung-2-2.c}. + + \bigskip + + Nach der Korrektur dieses Fehlers gibt das Programm überhaupt nichts mehr aus. + + Durch Untersuchen des Verhaltens des Programms + -- z.\,B.\ durch das Einfügen zusätzlicher \lstinline{printf()} -- + stellen wir fest, daß die Zeilen 8 bis 12 des Programms nur einmal ausgeführt werden + und nicht, wie die \lstinline{for}-Schleife in Zeile 6 vermuten ließe, 100mal. + Der Grund dafür ist, daß sich die \lstinline{for}-Schleife + nur auf die unmittelbar folgende Anweisung \lstinline{divisors = 0} bezieht. + Nur diese Zuweisung wird 100mal ausgeführt; + alles andere befindet sich außerhalb der \lstinline{for}-Schleife. + (Die Einrückung hat in C keine inhaltliche Bedeutung, + sondern dient nur zur Verdeutlichung der Struktur des Programms. + In diesem Fall entsprach die tatsächliche Struktur nicht der beabsichtigten.) + + Korrektur dieses Fehlers: + geschweifte Klammern um den Inhalt der äußeren \lstinline{for}-Schleife + -- siehe die Datei \gitfile{hp}{2021ws/20211025}{loesung-2-3.c}. + + \bigskip + + Nach der Korrektur dieses Fehlers gibt das Programm folgendes aus: + \begin{lstlisting}[style=terminal] + 4 ist eine Primzahl. + 9 ist eine Primzahl. + 25 ist eine Primzahl. + 49 ist eine Primzahl. + \end{lstlisting} + Diese Zahlen sind keine Primzahlen (mit zwei Teilern), + sondern sie haben drei Teiler. + Demnach findet das Programm einen Teiler zu wenig. + (Um diesen Fehler zu finden, kann man sich zu jeder Zahl + die gefundene Anzahl der Teiler \lstinline{divisors} ausgeben lassen.) + + Der nicht gefundene Teiler ist jeweils die Zahl selbst. + Dies kommt daher, daß die Schleife + \lstinline{for (i = 1; i < n; i++)} nur bis \lstinline{n - 1} geht, + also keine Division durch \lstinline{n} stattfindet. + + Korrektur dieses Fehlers: Schleifenbedingung \lstinline{i <= n} + statt \lstinline{i < n} + -- siehe die Datei \gitfile{hp}{2021ws/20211025}{loesung-2-4.c}. + + \bigskip + + Nach der Korrektur dieses Fehlers verhält sich das Programm korrekt. + + Die Datei \gitfile{hp}{2021ws/20211025}{loesung-2-4.c} enthält somit das korrigierte Programm. + +\end{document} diff --git a/20211025/hp-uebung-20211025.pdf b/20211025/hp-uebung-20211025.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e452bd3c91d71aff6b4d5bd3524cc3cde2df0cfa Binary files /dev/null and b/20211025/hp-uebung-20211025.pdf differ diff --git a/20211025/hp-uebung-20211025.tex b/20211025/hp-uebung-20211025.tex new file mode 100644 index 0000000000000000000000000000000000000000..b6785572e59d4aa25af36cb7f8457b456cf7a299 --- /dev/null +++ b/20211025/hp-uebung-20211025.tex @@ -0,0 +1,127 @@ +% hp-uebung-20211025.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: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\thispagestyle{empty} + +\begin{document} + + \thispagestyle{empty} + + \section*{Hardwarenahe Programmierung\\ + Übungsaufgaben -- 25.\ Oktober 2021} + + \exercise{Strings} + + Strings werden in der Programmiersprache C + durch Zeiger auf \lstinline{char}-Variable realisiert. + + Wir betrachten die folgende Funktion (Datei: \gitfile{hp}{2021ws/20211025}{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}{2021ws/20211025}{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}{2021ws/20211025}{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/20211025/loesung-1.c b/20211025/loesung-1.c new file mode 100644 index 0000000000000000000000000000000000000000..29a2b7f234ea5c31b06780e9dd461dff95dd33a3 --- /dev/null +++ b/20211025/loesung-1.c @@ -0,0 +1,67 @@ +#include <stdio.h> + +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; +} + +int fun_2 (char *s1, char *s2) +{ + int result = 1; + for (int i = 0; s1[i] && s2[i] && result; i++) + if (s1[i] != s2[i]) + result = 0; + return result; +} + +int fun_3 (char *s1, char *s2) +{ + for (int i = 0; s1[i] && s2[i]; i++) + if (s1[i] != s2[i]) + return 0; + return 1; +} + +int fun_4 (char *s1, char *s2) +{ + int result = 1; + for (int i = 0; s1[i] && s2[i]; i++) + if (s1[i] != s2[i]) + { + result = 0; + break; + } + return result; +} + +int main (void) +{ + char *s1 = "Apfel"; + char *s2 = "Apfelkuchen"; + if (fun_1 (s1, s2) && fun_2 (s1, s2) && fun_3 (s1, s2) && fun_4 (s1, s2)) + printf ("OK\n"); + else + printf ("failed\n"); + s1 = "Apfelkuchen"; + s2 = "Apfel"; + if (fun_1 (s1, s2) && fun_2 (s1, s2) && fun_3 (s1, s2) && fun_4 (s1, s2)) + printf ("OK\n"); + else + printf ("failed\n"); + s2 = "Birnenmarmelade"; + if (fun_1 (s1, s2) || fun_2 (s1, s2) || fun_3 (s1, s2) || fun_4 (s1, s2)) + printf ("failed\n"); + else + printf ("OK\n"); + s1 = s2; + s2 = "Apfelkuchen"; + if (fun_1 (s1, s2) || fun_2 (s1, s2) || fun_3 (s1, s2) || fun_4 (s1, s2)) + printf ("failed\n"); + else + printf ("OK\n"); + return 0; +} diff --git a/20211025/loesung-2.c b/20211025/loesung-2.c new file mode 100644 index 0000000000000000000000000000000000000000..6346384a81d62e7e687f4db99be3ba8fe4020744 --- /dev/null +++ b/20211025/loesung-2.c @@ -0,0 +1 @@ +char*f="char*f=%c%s%c;int main(void){printf(f,34,f,34,10);return 0;}%c";int main(void){printf(f,34,f,34,10);return 0;} diff --git a/20211025/loesung-2x.c b/20211025/loesung-2x.c new file mode 100644 index 0000000000000000000000000000000000000000..fcc65e153ddf009f55af118278774cd202f7c316 --- /dev/null +++ b/20211025/loesung-2x.c @@ -0,0 +1,2 @@ +#include<stdio.h> +char*f="#include<stdio.h>%cchar*f=%c%s%c;int main(void){printf(f,10,34,f,34,10);return 0;}%c";int main(void){printf(f,10,34,f,34,10);return 0;} diff --git a/20211025/loesung-3-1.c b/20211025/loesung-3-1.c new file mode 100644 index 0000000000000000000000000000000000000000..248883b772ca68d498ae4dc080e83899eb715570 --- /dev/null +++ b/20211025/loesung-3-1.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/20211025/loesung-3-2.c b/20211025/loesung-3-2.c new file mode 100644 index 0000000000000000000000000000000000000000..0cc3db639099eab0040c568acbd46987eb599645 --- /dev/null +++ b/20211025/loesung-3-2.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 = 1; i < n; i++) + if (n % i == 0) + divisors++; + if (divisors == 2) + printf ("%d ist eine Primzahl.\n", n); + return 0; +} diff --git a/20211025/loesung-3-3.c b/20211025/loesung-3-3.c new file mode 100644 index 0000000000000000000000000000000000000000..af2694c1ad2f710d79d7913b9dcfc7348be96115 --- /dev/null +++ b/20211025/loesung-3-3.c @@ -0,0 +1,16 @@ +#include <stdio.h> + +int main (void) +{ + int n, i, divisors; + for (n = 0; n < 100; n++) + { + divisors = 0; + for (i = 1; i < n; i++) + if (n % i == 0) + divisors++; + if (divisors == 2) + printf ("%d ist eine Primzahl.\n", n); + } + return 0; +} diff --git a/20211025/loesung-3-4.c b/20211025/loesung-3-4.c new file mode 100644 index 0000000000000000000000000000000000000000..770d92706cc68f64147e5efd443880ac3d875495 --- /dev/null +++ b/20211025/loesung-3-4.c @@ -0,0 +1,16 @@ +#include <stdio.h> + +int main (void) +{ + int n, i, divisors; + for (n = 0; n < 100; n++) + { + divisors = 0; + for (i = 1; i <= n; i++) + if (n % i == 0) + divisors++; + if (divisors == 2) + printf ("%d ist eine Primzahl.\n", n); + } + return 0; +} diff --git a/20211025/logo-hochschule-bochum-cvh-text-v2.pdf b/20211025/logo-hochschule-bochum-cvh-text-v2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8 --- /dev/null +++ b/20211025/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/20211025/logo-hochschule-bochum.pdf b/20211025/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20211025/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20211025/pgscript.sty b/20211025/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20211025/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20211025/pgslides.sty b/20211025/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20211025/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file diff --git a/README.md b/README.md index 9b4619f64670d76b6387ee30d094b01f3efc4f0c..cca50f0a7db8dfeb766cd5d4ee98072e6e3ce985 100644 --- a/README.md +++ b/README.md @@ -18,17 +18,23 @@ Für Details siehe [common/README](https://gitlab.cvh-server.de/pgerwinski/hp/ra Vortragsfolien und Beispiele: ----------------------------- * [04.10.2021: Einführung, Einführung in C (bis Schleifen)](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211004/hp-20211004.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211004/) - * [11.10.2021: Einführung in C: Seiteneffekte, Funktionen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211011/hp-20211011.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211011/) + * [11.10.2021: Einführung in C: Seiteneffekte, Funktionen, Zeiger](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211011/hp-20211011.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211011/) + * [18.10.2021: Einführung in C: Arrays und Strings, Strukturen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211018/hp-20211018.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211018/) + * [25.10.2021: Einführung in C: Arrays und Strings und Zeichen, Strukturen, Dateien und Fehlerbehandlung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211025/hp-20211025.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211025/) * [alle in 1 Datei](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/hp-slides-2021ws.pdf) Übungsaufgaben: --------------- * [04.10.2021: Hello-World-Programme, Schaltjahr ermitteln, Maximum berechnen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211004/hp-uebung-20211004.pdf) * [11.10.2021: Schaltjahr ermitteln, Multiplikationstabelle, Fibonacci-Zahlen, fehlerhaftes Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211011/hp-uebung-20211011.pdf) + * [18.10.2021: Seltsame Programme, Kalender-Berechnung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211018/hp-uebung-20211018.pdf) + * [25.10.2021: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211025/hp-uebung-20211025.pdf) Musterlösungen: --------------- * [11.10.2021: Schaltjahr ermitteln, Multiplikationstabelle, Fibonacci-Zahlen, fehlerhaftes Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211011/hp-musterloesung-20211011.pdf) + * [18.10.2021: Seltsame Programme, Kalender-Berechnung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211018/hp-musterloesung-20211018.pdf) + * [25.10.2021: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211025/hp-musterloesung-20211025.pdf) Tafelbilder: ------------ diff --git a/hp-slides-2021ws.pdf b/hp-slides-2021ws.pdf index 10b5d181cdcd61a8a9f2c8b5ef771253ab2f1e27..280d352972bb97ef923e1652546b58297a0f657b 100644 Binary files a/hp-slides-2021ws.pdf and b/hp-slides-2021ws.pdf differ diff --git a/hp-slides-2021ws.tex b/hp-slides-2021ws.tex index 1e7df3a592bfe3db4f6a703a18c87f1d1744d5a0..4b12fd848b43ce69bc04bb8ed0bc9c1ae05cee02 100644 --- a/hp-slides-2021ws.tex +++ b/hp-slides-2021ws.tex @@ -12,6 +12,10 @@ \includepdf[pages=2-]{script/hp-slides-title-2021ws.pdf} \pdfbookmark[1]{04.10.2021: Einführung, Einführung in C (bis Schleifen)}{20211004} \includepdf[pages=-]{20211004/hp-20211004.pdf} - \pdfbookmark[1]{11.10.2021: Einführung in C: Seiteneffekte, Funktionen}{20211011} + \pdfbookmark[1]{11.10.2021: Einführung in C: Seiteneffekte, Funktionen, Zeiger}{20211011} \includepdf[pages=-]{20211011/hp-20211011.pdf} + \pdfbookmark[1]{18.10.2021: Einführung in C: Arrays und Strings, Strukturen}{20211018} + \includepdf[pages=-]{20211018/hp-20211018.pdf} + \pdfbookmark[1]{25.10.2021: Einführung in C: Arrays und Strings und Zeichen, Strukturen, Dateien und Fehlerbehandlung}{20211025} + \includepdf[pages=-]{20211025/hp-20211025.pdf} \end{document}