Skip to content

Commit a9e03ce

Browse files
jenukfriedz
authored andcommitted
Funktionenabschnitt voellig neu (#59)
* Funktionenabschnitt voellig neu * Erklärung der Signatur ausgebaut, Text etwas umstrukturiert * \cppinline ergänzt * Funktions Signatur Beispiel in \cppinline getan das es Highlighting bekommt * formatierung leicht angepasst das es dem Restlichen codingstyle entspricht * Revert "formatierung leicht angepasst das es dem Restlichen codingstyle" This reverts commit d356b42. * Fixed mixed spaces/tabs * Versentliches rückgängig machen rückgängig gemacht * Funktionsrumpf weiter ausgeführt * variable umbenannt in main * inline cpp nicht mehr auskommentiert * Neues Beispiel, alter Text * Neues Beispiel * Altes Beispiel gelöscht * \bf -> \textbf * auch *.out und _minted-vorkurs/ ignoriert * \chapter{...} -> \chapter*{...} * oft \texttt{...} -> \cppinline{...}
1 parent 5b7665a commit a9e03ce

8 files changed

Lines changed: 137 additions & 142 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
*.aux
22
*.log
33
*.toc
4+
*.out
45
vorkurs.pdf
56
folien/folien.pdf
67
folien/passwort.tex
78
folien_abschied/folien.pdf
9+
_minted-vorkurs/

basics/funktionen.tex

Lines changed: 67 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,84 @@
11
\lesson{Funktionen}
22

3-
Wir haben den Begriff schon ein paarmal genannt und auch, wenn ihr es
4-
vielleicht nicht gemerkt habt, sie waren schon die ganze Zeit vor eurer Nase:
5-
Funktionen.
3+
Aus der Mathematik kennt ihr bereits Funktionen, wie zum Beispiel $f(x) = 4x^3 - 8x^2 + 16x - 12$.
4+
Eine wichtige Idee dahinter ist es einfach $f(3)$ zu schreiben, wenn man eigentlich $4 \cdot 3^3 - 8 \cdot 3^2 + 16 \cdot 3 - 12$ meint.
5+
Da dies häufig vorteilhaft ist, wurde diese Funktionalität in die meisten Programmiersprachen übernommen.
66

7-
Eine Funktion ist im Wesentlichen eine Möglichkeit, eine Folge von Anweisungen
8-
zu bündeln und isolieren. Wir haben schon einmal ein Programm gesehen, mit dem
9-
wir testen können, ob eine Zahl eine Primzahl ist, oder nicht. Viele Vorteile
10-
von Funktionen, lassen sich an diesem Beispiel illustrieren. Stellt euch vor,
11-
ihr braucht in eurem Programm an vielen Stellen einen solchen Primzahltest. Ihr
12-
könntet jedes mal den gesamten benötigten Code hinschreiben, aber das wäre doch
13-
eine Menge Arbeit. Eine Funktion ermöglicht es euch, den Code zum Testen
14-
auszulagern in eine eigene Funktion z.B. \texttt{istprim}. Immer, wenn ihr dann
15-
testen wollt, ob eine Zahl \texttt{n} eine Primzahl ist, könnt ihr dann einfach
16-
schreiben \texttt{istprim(n)} und ruft damit die Funktion auf. Das spart
17-
Schreibarbeit.
7+
Eine Funktion in \Cpp besteht aus zwei Teilen: der \emph{Signatur} und dem \emph{Funktionsrumpf}.
8+
Die Kombination von Parametertypen und Rückgabetyp bildet die Signatur einer Funktion.
9+
Parameter sind Werte, die der Funktion übergeben werden, zum Beispiel das $x$ in $f(x)$.
10+
Für eine Funktion \cppinline{my_func}, die $x^n$ berechnen soll, könnte eine Signatur so aussehen:
1811

19-
Stellt euch vor, irgendwann ist euch dann ein Test mittels Probedivision nicht
20-
mehr schnell genug (weil ihr z.B. immer größere Zahlen testen wollt) und ihr
21-
wollt auf einen schnelleren Test umsteigen. Ohne Funktionen müsstet ihr jedes
22-
Vorkommen eines Primzahltests in eurem Code einzeln durch den neuen Test
23-
ersetzen. Mit Funktionen gibt es genau eine Stelle, an der ihr den Code
24-
austauschen müsst und all die Stellen, an denen ihr ihn benutzt, übernehmen
25-
automatisch die neue Implementation.
12+
\begin{center}
13+
\cppinline{double my_func(double x, int n)}
14+
\end{center}
2615

27-
Zuletzt haben wir in der letzten Lektion einiges über Lesbarkeit von Quellcode
28-
gelernt. Lesbarkeit erhöht Wartbarkeit und reduziert die Möglichkeiten, Fehler
29-
zu machen. Was stellt ihr euch lesbarer vor, eine Datei, in der einige tausend
30-
Zeilen Code stehen, ohne sichtbare Struktur und einfach nur als Folge von
31-
Anweisungen, oder mehrere kleine Datein, mit beschreibenden, verständlichen
32-
Namen, in denen jeweils mehrere Fun¡tionen, ebenfalls mit verständlichen Namen
33-
stehen, das alles schön aufgeteilt nach Themengebiet? Funktionen erhöhen
34-
Lesbarkeit und helfen, den Code zu strukturieren, was ihn verständlicher macht.
16+
%Signatur Diagramm von Koebi? Ich kriege nichts schönes hin
3517

36-
Das wohl wichtigste Beispiel für eine Funktion habt ihr bereits kennengelernt:
37-
Die \texttt{main}-Funktion. Diese spezielle Funktion ist der Eintrittspunkt für
38-
euer Programm. Der Code der \texttt{main}-Funktion ist der erste, der läuft,
39-
sobald die \texttt{main} fertig abgearbeitet ist, beendet sich euer Programm.
40-
Damit haben wir auch schon die Wesentlichen Eckpunkte, wie eine Funktion
41-
syntaktisch auszusehen hat.
18+
Diese Signatur besteht also aus einem Datentypen, der den Rückgabetypen der Funktion bestimmt, direkt gefolgt von dem Namen der Funktion, der beliebig gewählt werden kann.
19+
Und dahinter in Klammern werden die einzelnen Paramter durch Komma getrennt angeben, wobei ein Paramter immer aus dem Datentyp des Paramters und einem beliebigen Namen für den Paramter besteht.
20+
In diesem Fall ist also \texttt{double} der Rückgabewert, \cppinline{my_func} der Name, \cppinline{x} ein Parameter mit dem Typ \texttt{double} und \cppinline{n} ein Paramter mit dem Typ \texttt{int}.
21+
Damit können dann Werte an die Funktion in der Form \cppinline{my_func(1.41, 2)} übergeben werden.
4222

43-
Das \texttt{int main()} heißt die \emph{Signatur} der Funktion. Die Signatur
44-
enthält immer den Datentyp, den die Funktion ausgeben soll (in diesem Fall
45-
\texttt{int}, also eine ganze Zahl), einen Namen (in diesem Fall der spezielle
46-
Name \texttt{main}) sowie Parameter, die Eingabewerte (in diesem Fall gibt es
47-
keine Parameter, wir werden aber gleich sehen, wie eine Funktion auszusehen
48-
hat, die Parameter entgegennimmt). An die Signatur schließt sich direkt eine
49-
öffnende geschweifte Klammer, dann kommen alle Anweisungen, aus denen die
50-
Funktion bestehen soll, dann eine schließende geschweifte Klammer.
23+
An dieser Stelle ist der Unterschied zwischen Rückgabe und Ausgabe wichtig: Eine Ausgabe (gekennzeichnet durch \cppinline{std::cout}) gibt Informationen auf dem Bildschirm für die Nutzerin aus, eine Rückgabe (gekennzeichnet durch \texttt{return}) gibt hingegen ein bestimmtes Ergebnis an einen anderen Teil des Programmes zurück, damit dieser dort in einer Variable gespeichert oder direkt weiter verarbeitet werden kann.
24+
Dabei kann man sich vorstellen, dass der Funktionsaufruf nach dem die Funktion ausgeführt wurde durch den Rückgabewert ersetzt wird.
25+
Dies könnte für die Funktion \cppinline{my_func} folendermaßen aussehen:
5126

52-
Um das Ergebnis einer Funktion zurückzugeben, benutzen wir \texttt{return}. Wir
53-
haben das bereits einmal gesehen, wo wir es benutzt haben, um unser Programm zu
54-
beenden -- das funktionierte in dem Fall, weil wir uns in der \texttt{main}
55-
befanden und wie gesagt beendet sich das Programm, sobald die \texttt{main}
56-
fertig ist. Mit Funktionen könnte ein Programm, was eine Zahl darauf testet,
57-
eine Primzahl zu sein, so aussehen:
58-
\inputcpp{funktion.cpp}
27+
\begin{center}
28+
\cppinline{f(5.0 + f(3.0, 2), 3)} $\mapsto$ \cppinline{f(5.0 + 9.0, 3)} $\mapsto$ \cppinline{f(14.0, 3)} $\mapsto$ \cppinline{2744}
29+
\end{center}
30+
31+
32+
Der Funktionsrumpf beinhaltet den Code, der beim Funktionsaufruf tatsächlich ausgeführt wird.
33+
Dieser wird wie in einer Schleife von \mintinline{c++}|{| und \mintinline{c++}|}| umschlossen.
34+
Innerhalb dieser Klammern kann dann beliebiger Code ausgeführt werden, wie auch in der \texttt{main}-Funktion.
35+
Dabei kann auf die Parameter einfach mit dem in der Signatur definierten Namen zugegriffen werden.
36+
Also in unserem Beispiel mit \cppinline{x} und \cppinline{n}.
37+
Vor dem Ende des Funktionsrumpfes muss eine Rückgabe mit \texttt{return} ausgeführt werden.
38+
Das kann zum Beispiel so \texttt{return x;} oder so \texttt{return 5;} aussehen.
39+
40+
Funktionen werden beispielsweise benötigt, wenn bestimmte Programmteile häufiger mit verschiedenen Parametern ausgeführt werden sollen.
41+
Die Collatz-Vermutung\footnote{\url{https://de.wikipedia.org/wiki/Collatz-Vermutung}} besagt für die Folge:
42+
\[
43+
x_n =
44+
\begin{cases}
45+
\frac{x_{n-1}}{2} & x_{n-1} \text{ ist gerade} \\
46+
3 \cdot x_{n-1} + 1 & x_{n-1} \text{ ist ungerade}
47+
\end{cases}
48+
\]
49+
dass jeder Startwert $x_1$ aus den natürlichen Zahlen nach endlich vielen Schritten bei der $1$ angelangt.
50+
Zum Beispiel für den Startwert $x_1 = 42$:
5951

60-
Parameter geben wir also in den Klammern an, jeweils so, wie wenn wir eine
61-
Variable erstellen würden, mit einem Typ und einem Namen. Wenn wir mehrere
62-
Parameter brauchen, können wir sie mit Kommata trennen. Dann müssen wir auch,
63-
wenn wir die Funktion benutzen, die einzelnen Eingaben mit Kommata trennen.
52+
\[
53+
42 \mapsto 21 \mapsto 64 \mapsto 32 \mapsto 16 \mapsto 8 \mapsto 4 \mapsto 2 \mapsto 1 \mapsto 4 \mapsto 2 \mapsto 1 \mapsto \ldots
54+
\]
55+
56+
Wenn nun die Frage aufkommt was die nächsten Folgenglieder von verschiedenen Zahlen sind, wäre ein möglicher Lösungsweg eine Funktion zu schreiben, die der Nutzerin die nächste Zahl in dieser Folge zurückgibt.
57+
58+
\inputcpp{funktion.cpp}
6459

6560
\textbf{Praxis:}
6661
\begin{enumerate}
67-
\item Schreibt eine Funktion, die einen Parameter vom Typ
68-
\texttt{std::string} hat und einen Rückgabewert vom Typ \texttt{int}.
69-
Die Funktion soll -- so wie wir es bisher schon in vielen Programmen
70-
gemacht haben -- den eingegebenen String (der z.B. die Aufforderung
71-
enthält, eine Zahl einzugeben) auf die Konsole ausgeben und einen
72-
\texttt{int} von der Nutzerin einlesen. Dieser eingelesene \texttt{int}
73-
soll dann von der Funktion zurückgegeben werden.
74-
Denkt euch einen sprechenden Namen für diese Funktion aus.
75-
\item Passt \texttt{funktion.cpp} so an, dass es eure Funktion benutzt.
76-
\item Kompiliert das angepasste Programm und lasst es im debugger Schritt
77-
für Schritt durchlaufen. Um die Funktion durchlaufen zu lassen, habt
78-
ihr zwei Möglichkeiten: Ihr könnt einen neuen breakpoint in der
79-
Funktion erstellen, oder ihr könnt, sobald der debugger euch anzeigt,
80-
als nächstes die Funktion aufrufen zu wollen, \texttt{step} statt
81-
\texttt{next} aufrufen, sodass er in die Funktion hineinspringt.
62+
\item Verändert das Programm in \texttt{funktion.cpp} so, dass es nicht die einzelnen Zahlen \texttt{x1}, \texttt{x2} und \texttt{x3}, sondern die Summe dieser ausgibt.
63+
%Wirkt wie Kinderkram nicht zum Funktionskapitel, möchte aber nochmal den Unterschied zwischen Ausgabe und Rückgabe dadurch nochmal klarer machen
64+
\item Kompiliert das angepasste Programm und lasst es im debugger Schritt für Schritt durchlaufen, setzt dafür wieder einen breakpoint für die \texttt{main}-Funktion.
65+
Sobald der debugger euch anzeigt, als nächstes die Funktion ausführen zu wollen, \texttt{step} statt \texttt{next} aufrufen, sodass der debugger in die Funktion hineinspringt.
66+
\item Schreibt eine Funktion (nach der Funktion \texttt{collatz} und vor \texttt{main}), die einen \texttt{int} entgegen nimmt und die Anzahl der Schritte bestimmt bis die Folge bei der 1 angekommen ist und diese als \texttt{int} zurückgibt.
67+
Benutzt dafür die bereits vorhandene Funktion \texttt{collatz}.
68+
\item Schreibt euer Programm so um, dass es eine Zahl von der Nutzerin entgegen nimmt und die Anzahl der Schritte ausgibt, bis diese Zahl zu einer 1 wird.
8269
\end{enumerate}
8370

8471
\textbf{Spiel:}
8572
\begin{enumerate}
86-
\item Vertauscht in \texttt{funktion.cpp} die Funktion \texttt{istprim} mit
87-
der Funktion \texttt{main} (verschiebt also die gesamte Funktion
88-
\texttt{istprim} an das Ende der Datei). Versucht, die Datei zu
89-
kompilieren. Was ist die Fehlermeldung des Compilers?
90-
\item Verschiebt die Funktion \texttt{istprim} \emph{in} die
91-
\texttt{main}-Funktion (also irgendwo nach der öffnenden geschweiften
92-
Klammern, aber vor die dazu gehörige schließende). Versucht, die Datei
93-
zu kompilieren. Was ist die Fehlermeldung des Compilers?
94-
\item Schaut euch eure bisherigen Lösungen an. Findet ihr noch häufiger
95-
Stellen, an denen ihr einzelne Teilprogramme in Funktionen auslagern
96-
könnt?
73+
\item Was passiert, wenn ihr in einer Funktion den \texttt{return}-Ausdruck vor dem Ende eurer Funktion benutzt?
74+
\item Vertauscht in \texttt{funktion.cpp} die Funktion \texttt{collatz} mit der Funktion \texttt{main} (verschiebt also die gesamte Funktion \texttt{collatz} an das Ende der Datei).
75+
Versucht, die Datei zu kompilieren.
76+
Was ist die Fehlermeldung des Compilers?
77+
\item Verschiebt die Funktion \texttt{collatz} \emph{in} die \texttt{main}-Funktion (also irgendwo nach der öffnenden geschweiften Klammern, aber vor die dazu gehörige schließende).
78+
Versucht, die Datei zu kompilieren. Was ist die Fehlermeldung des Compilers?
79+
\item Implementiert die Funktion, die $x^n$ umsetzt, ignoriert dabei zunächst negative Exponenten. \\
80+
(\emph{Tipp:} Die Signatur ist bereits oben gegeben, für den Funktionsrumpf könnten sich Schleifen eignen.)
81+
\item Ihr könnt eure Funktion von innerhalb wieder aufrufen. Versucht eure Funktion auf negative Exponenten zu erweitern, indem ihr benutzt, dass gilt $x^{-n} = \frac{1.0}{x^n}$.
82+
\item Schaut euch eure bisherigen Lösungen an.
83+
Findet ihr noch häufiger Stellen, an denen ihr einzelne Teilprogramme in Funktionen auslagern könnt?
9784
\end{enumerate}

basics/intro.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
\chapter{Die Basics}
1+
\chapter*{Die Basics}
22
\pagestyle{empty}
33

44
Im Ersten Kapitel werden wir die Grundlagen der Programmierung lernen.

basics/warning.tex

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,9 @@
9494
er sich gleich verhält, aber schneller läuft. \texttt{-O2} würde
9595
bedeuten, dass relativ stark optimiert wird.
9696

97-
\texttt{collatz.cpp} enthält ein Programm, um die
98-
\emph{Collatz-Vermutung}\footnote{\url{https://de.wikipedia.org/wiki/Collatz-Vermutung}}
99-
zu testen. Kompiliert es mit \texttt{g++ -Wall -O2 -o collatz
100-
collatz.cpp} (probiert es auch einmal ohne \texttt{-O2} oder ohne
101-
\texttt{-Wall}) und schaut euch die resultierende Warning an. Benutzt
102-
gegebenenfalls Google, um heraus zu finden, was sie bedeutet und wie
103-
ihr sie beheben könnt.
97+
\texttt{zaehlen.cpp} enthält ein Programm, um bei einem von der Nutzerin eingegebenen Wort zu zählen, wie oft ein bestimmter Buchstabe (zurzeit \texttt{a} vorkommt).
98+
Kompiliert es mit \texttt{g++ -Wall -O2 -o zaehlen zaehlen.cpp} (probiert es auch einmal ohne \texttt{-O2} oder ohne \texttt{-Wall}) und schaut euch die resultierende Warning an.
99+
Benutzt gegebenenfalls Google, um heraus zu finden, was sie bedeutet und wie ihr sie beheben könnt.
104100
\end{enumerate}
105101

106-
\inputcpp{collatz.cpp}
102+
\inputcpp{zaehlen.cpp}

files/collatz.cpp

Lines changed: 0 additions & 20 deletions
This file was deleted.

files/funktion.cpp

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
1-
#include <iostream>
2-
3-
// bool ist ein neuer Datentyp. Ein Boolean kann genau zwei Werte
4-
// annehmen, „true“ und „false“, repräsentiert also ein einziges
5-
// Bit, beziehungsweise einen Wahrheitswert. In unserem Fall geben
6-
// wir true zurück, wenn die Eingabe eine Primzahl ist und false,
7-
// wenn sie keine ist.
8-
bool istprim(int n) {
9-
int i = 2;
10-
while (i < n) {
11-
if ((n % i) == 0) {
12-
return false;
13-
}
14-
i = i + 1;
15-
}
16-
return true;
17-
}
18-
19-
int main() {
20-
int m;
21-
std::cout << "Gib eine Zahl ein: ";
22-
std::cin >> m;
23-
24-
// Da istprim einen bool zurück gibt, müssen wir nicht
25-
// "istprim(n) == true" schreiben. Diese Schreibweise bedeutet
26-
// das Gleiche
27-
if (istprim(m)) {
28-
std::cout << m << " ist eine Primzahl" << std::endl;
29-
} else {
30-
std::cout << m << " ist keine Primzahl" << std::endl;
31-
}
32-
}
1+
#include <iostream>
2+
3+
int collatz(int x) {
4+
int erg;
5+
6+
if (x % 2 == 0) {
7+
erg = x / 2;
8+
} else {
9+
erg = 3*x + 1;
10+
}
11+
12+
return erg;
13+
}
14+
15+
int main() {
16+
int eingabe;
17+
18+
std::cout << "Mit welcher Zahl moechtest du starten? ";
19+
std::cin >> eingabe;
20+
21+
int x1 = collatz(eingabe);
22+
int x2 = collatz(x1);
23+
int x3 = collatz(x2);
24+
//bis hierin haben keine Ausgaben statt gefunden, aber collatz wurde
25+
//dreimal aufgerufen. Die Zahlen x1, x2 und x3 sind die naechsten
26+
//drei Glieder von x (der von der Nutzerin eingegebenen Zahl) aus
27+
//gesehen.
28+
29+
//Hier werden der Nutzerin nun die Ergebnisse angezeigt:
30+
std::cout << eingabe << " -> " << x1 << " -> "
31+
<< x2 << " -> " << x3 << std::endl;
32+
}

files/zaehlen.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <iostream>
2+
#include <string>
3+
4+
int zaehlen(std::string str, char c) {
5+
int erg;
6+
7+
unsigned i = 0;
8+
// unsigned funktioniert wie int,
9+
// kann allerdings keine negativen
10+
// Werte speichern.
11+
while (i < str.length()) {
12+
if (str[i] == c) {
13+
erg = erg + 1;
14+
}
15+
i = i + 1;
16+
}
17+
18+
return erg;
19+
}
20+
21+
int main() {
22+
std::string wort;
23+
24+
std::cout << "Gib ein Wort ein: ";
25+
std::cin >> wort;
26+
27+
std::cout << "In deinem Wort kommt " << zaehlen(wort, 'a')
28+
<< "-mal der Buchstabe a vor." << std::endl;
29+
}

vorkurs.cls

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@
3131
\newcommand{\lesson}[1]{\section*{#1}\pagestyle{fancy}\addcontentsline{toc}{section}{#1}}
3232
\renewcommand*\thesection{\arabic{section}}
3333

34-
\titlecontents{chapter}[0pt]{\vspace{1em}\large\bf}{\makebox[60pt][l]{Kapitel \thecontentslabel:}\hspace*{10pt}}{}{\titlerule*[1pc]{ }\contentspage}
34+
\titlecontents{chapter}[0pt]{\vspace{1em}\large\textbf}{\makebox[60pt][l]{Kapitel \thecontentslabel:}\hspace*{10pt}}{}{\titlerule*[1pc]{ }\contentspage}
3535
\titlecontents{section}[10pt]{}{\makebox[50pt][l]{Lektion \thecontentslabel:}\hspace*{10pt}}{}{\titlerule*[1pc]{ }\contentspage}
3636

3737
\newcommand{\inputcpp}[1]{\usemintedstyle{vs}\inputminted[label=#1,linenos=true,frame=single]{c++}{files/#1}}
3838
\newcommand{\inputshell}[1]{\usemintedstyle{vs}\inputminted[label=#1,linenos=true,frame=single]{bash}{files/#1}}
3939
\newcommand{\cppsect}[3]{\usemintedstyle{vs}\inputminted[label=#1,linenos=true,frame=single,firstline=#2,lastline=#3,firstnumber=#2]{c++}{files/#1}}
40+
\newcommand{\cppinline}[1]{\usemintedstyle{vs}\mintinline{c++}{#1}}
4041

4142
\newminted{text}{frame=single}

0 commit comments

Comments
 (0)