---
fontsize: 8pt
format:
  beamer:
    include-in-header: ../PP_Header.tex
bibliography: ../PP_Referenzen.bib
---


# {.plain}

\center
```{r, echo = F, out.width = "20%"}
knitr::include_graphics("../OvGU_Logo.png")
```

\vspace{1mm}
\huge
Programmieren für Psychologie

\vspace{6mm}
\large
MSc Umweltpsychologie/Mensch-Technik-Interaktion

MSc Klinische Psychologie und Psychotherapie

MSc Psychologie

\vspace{6mm}
\normalsize
Joram Soch | Wintersemester 2026/2027


# {.plain}
\vfill
\center
\huge
\textcolor{black}{(7) Strukturiertes Programmieren}
\vfill


# AGENDA {.plain}
\large
\setstretch{3}
\vfill

Kontrollfluss

Debugging

Programmierübungen

\vfill


# Kontrollfluss ====================================== {.plain}
\AtBeginSection{}
\section{Kontrollfluss}
\setstretch{3}
\large
\vfill

**Kontrollfluss**

Debugging

Programmierübungen

\vfill


# Kontrollfluss
\setstretch{2.5}

\textcolor{darkblue}{Motivation}

\small

Programmiercode wird streng sequentiell Befehl für Befehl ausgeführt.

Manchmal möchten wir von dieser rein sequentiellen Befehlsreihenfolge abweichen.

Die prinzipiellen Werkzeuge dafür sind **Kontrollstrukturen**:

\begin{itemize}
\item \textbf{Konditionale Kontrollstrukturen} legen fest, dass Befehle nur ausgeführt werden, wenn bestimmte Bedingungen erfüllt sind (\texttt{if}, \texttt{switch}).
\item \textbf{Iterative Kontrollstrukturen} wiederholen Codeabschnitte in Schleifen (\texttt{for}, \texttt{while}, \texttt{repeat}).
\end{itemize}

\vfill


# Kontrollstrukturen: `if`-statements

\vfill

\setstretch{1.2}
\textcolor{darkblue}{if-statements}

\small
Ermöglicht die Ausführung eines spezifischen Codeblocks, wenn eine Bedingung \texttt{TRUE} ist.

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = F}
# Pseudocode
if (Bedingung) {
  TrueAktion        # Befehl, der ausgeführt wird, falls Bedingung TRUE ist
}
```

* Wenn `Bedingung` `TRUE` ist, wird `TrueAktion` ausgeführt.
* Wenn `Bedingung` `FALSE` ist, wird `TrueAktion` nicht ausgeführt.

\normalsize
\textcolor{darkblue}{if-else-statements}

\small
Bietet alternative Ausführungsmöglichkeiten, je nachdem, ob eine Bedingung \texttt{TRUE} oder \texttt{FALSE} ist.

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = F}
# Pseudocode
if (Bedingung) {
  TrueAktion        # Befehl, der ausgeführt wird, falls Bedingung TRUE ist
} else {
  FalseAktion       # Befehl, der ausgeführt wird, falls Bedingung FALSE ist
}
```

* Wenn `Bedingung` `TRUE` ist, wird `TrueAktion` ausgeführt.
* Wenn `Bedingung` `FALSE` ist, wird `FalseAktion` ausgeführt.


# Kontrollstrukturen: `if`-statements

\textcolor{darkcyan}{Beispiele}

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = T}
x <- 3
if (x > 0) {
  print("x ist größer als 0")
}
```

\vspace{2mm}
```{r, echo = T, eval = T}
y <- -3
if (y > 0) {
  print("y ist größer als 0")
} else {
  print("y ist nicht größer als 0")
}
```


# Wiederholung: Logische Operatoren

\setstretch{1.6}

\small
* Die Boolesche Algebra und R kennen zwei *logische Werte*: TRUE und FALSE
* Bei Auswertung von Relationsoperatoren ergeben sich logische Werte

\begin{center}
\begin{tabular}{l|l}
Relationsoperator & Bedeutung                     \\ \hline
$==$              & Gleich                        \\
$!=$              & Ungleich                      \\
$<$, $>$          & Kleiner, Größer               \\
$<=$, $>=$        & Kleiner gleich, Größer gleich \\
$\vert$           & ODER                          \\
$\&$              & UND                           \\
\end{tabular}
\end{center}

\vfill
* $<,<=,>,>=$ werden zumeist auf numerische Werte angewendet.
* $==,!=$ werden zumeist auf beliebige Datenstrukturen angewendet.
* $\vert$  und $\&$ werden zumeist auf logische Werte angewendet.
* $\vert$ implementiert das inklusive *oder*. Die Funktion xor() implementiert das exklusive ODER.


# Kontrollstrukturen: `if`-statements

\textcolor{darkcyan}{Beispiele}

\tiny
\setstretch{1.1}

\vfill
```{r, echo = T, eval = T}
x <- 3
y <- 2

# Logisches UND/ODER
if (x > 0 || y > 0) {
  print("Es sind beide, oder eine der beiden Variablen größer 0.")
} else {
  print("Keine der Variablen ist größer 0.")
}
```

\vfill
```{r, echo = T, eval = T}
# Logisches UND
if (x > 0 && y > 0) {
  print("x und y sind beide größer 0.")
} else {
  print("Es sind nicht beide Variablen x und y größer 0, aber vielleicht eine der beiden.")
}
```

\vfill
```{r, echo = T, eval = T}
# Exklusives ODER
if (xor(x > 0, y > 0)) {
  print("Genau eine der 2 Variablen x und y ist größer 0, aber nicht beide.")
} else {
  print("Es sind entweder keine der Variablen x und y oder beide größer 0.")
}
```


# Kontrollstrukturen: `if`-statements

\textcolor{darkblue}{Häufige Fehler bei Bedingungen}

\small
Bei `if`-statements muss die Bedingung einem einzigen logischen Wert entsprechen.

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = F}
#| error: true
# Bedingung ist kein logischer Wert
if ("x") { print(1) }
# Error: argument is not interpretable as logical

# Bedingung ist NA
if (NA) { print(1) }
# Error: missing value where TRUE/FALSE needed

# Bedingung hat Länge > 1
if (c(TRUE, FALSE)) { print(1) }
# Error: the condition has length > 1
```
\vfill


# Kontrollstrukturen: `switch`-statements

\textcolor{darkblue}{Motivation}

\small
Wenn wir mehrere ähnliche Bedingungen überprüfen möchten, von denen immer nur eine zutrifft, können kombinierte \texttt{if-else}-Statements schnell unübersichtlich und schwer lesbar werden. In solchen Fällen bietet sich das \texttt{switch}-Statement als strukturierte und kompakte Alternative an.

\vfill
\footnotesize
```{r, echo = T, eval = T}
x <- 2
if (x == 1) {
  print("Aktion 1")
} else if(x == 2) {
  print("Aktion 2")
} else if(x == 3) {
  print("Aktion 3")
} else if(x == 4) {
  print("Aktion 4")
}
```
\vfill


# Kontrollstrukturen: `switch`-statements

\textcolor{darkblue}{switch-statement}

\small
Vereinfacht die Auswahl zwischen mehreren Alternativen, ohne eine lange Verkettung von \texttt{if-else}-Statements zu verwenden.

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = F}
# Pseudocode
switch(
  x,                                # Variable, die geprüft wird
  Aktion 1,                         # Ausführung, wenn x == 1
  Aktion 2,                         # Ausführung, wenn x == 2
  Aktion 3,                         # Ausführung, wenn x == 3
  Aktion 4                          # Ausführung, wenn x == 4
)
```
\vfill


# Kontrollstrukturen: `switch`-statements

\vspace{2mm}
\small
\setstretch{1.2}
Wenn der Input numerisch gegeben ist, wird die Position des entsprechenden Falls ausgewählt.

\vspace{2mm}
\footnotesize
\setstretch{1.0}
```{r, echo = T, eval = T}
x <- 2
switch(
  x,                               # switch Variable
  print("Aktion 1"),               # 1. Aktion
  print("Aktion 2"),               # 2. Aktion
  print("Aktion 3"),               # 3. Aktion
  print("Aktion 4")                # 4. Aktion
)
```

\vspace{2mm}
\small
\setstretch{1.2}
Wenn der Input als character gegeben ist, wird der Fall anhand des Namens ausgewählt.

\vspace{2mm}
\footnotesize
\setstretch{1.0}
```{r, echo = T, eval = T}
x <- "a"
switch(
  x,                               # switch Variable
  a = print("Aktion 1"),           # 1. Aktion
  b = print("Aktion 2"),           # 2. Aktion
  c = print("Aktion 3"),           # 3. Aktion
  d = print("Aktion 4")            # 4. Aktion
)
```

\vspace{2mm}
\footnotesize
\setstretch{1.0}
\textbf{Anmerkung}: Jedes `if`-statement lässt sich äquivalent als `switch`-statement formulieren und umgekehrt. `if`-statements sind in der Praxis häufiger. Bei vielen Fallunterscheidungen können `switch`-statements die Lesbarkeit verbessern.


# Kontrollstrukturen: `for`-Schleifen

\textcolor{darkblue}{for-Schleifen}

\small
Wiederholt einen Codeblock für jedes Element in einer Sequenz oder Sammlung.

\footnotesize
```{r, echo = T, eval = F}
# Pseudocode
for (item in sequenz) {
  Aktion                           # Aktion, die wiederholt werden soll
}
```
\vfill

\normalsize
\textcolor{darkcyan}{Beispiel}

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = T}
for (i in 1:3) {
  print(i)                         # Aktion, die wiederholt werden soll
}
```
\vfill


# Kontrollstrukturen: `for`-Schleifen

\textcolor{darkblue}{Hinweise zur Verwendung}

\small
Die Aktion innerhalb der Schleife muss nicht auf das `item` Bezug nehmen:

\vspace{1mm}
\footnotesize
```{r, echo = T, eval = T}
for (i in 1:3) {
  print("a")
}
```

\vspace{1mm}
\small
Bei iterativem Speichern sollte die Datenstruktur vorab in ihrer endgültigen Größe erstellt ("präallokiert") werden, um den Speicherplatz zu reservieren.

\vspace{1mm}
\footnotesize
\setstretch{1.0}
```{r, echo = T, eval = T}
# Iterative Auffüllen eines Vektors mit Mittelwerten
ns    <- 3                        # Anzahl an Simulationen
x_bar <- rep(NaN, ns)             # Speicherstruktur

for (i in 1:ns) {                 # Iterationsindizes sind typischerweise i,j,k
  x        <- rnorm(12)           # Realisierung von 12 Z-Variablen
  x_bar[i] <- mean(x)             # Mittelwert der i-ten Realisierung
  print(x_bar)                    # Iterative Anzeige zur Demonstration
}
```


# Kontrollstrukturen: `for`-Schleifen

\small
Bei Vektoren mit variablen Einträgen ist die Funktion `seq_along()` hilfreich, die Indizes von 1 bis zur Länge eines Vektors erzeugt.

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = T}
mu    <- c(0,5,50)                   # Drei Erwartungswertparameter
X_bar <- rep(NaN, ns)                # Speicherstruktur

# Simulationsiterationen
for(i in seq_along(mu)){             # Iterationsindizes sind typischerweise i,j,k
  X         <- rnorm(12, mu[i], 1)   # Realisierung von 12 N(\mu,1) Variablen
  X_bar[i]  <- mean(X)               # Mittelwert der i-ten Realisierung
  print(X_bar)                       # Anzeige zur Demonstration
}
```

\small
\vspace{2mm}
Dies ist robuster als `1:length(mu)`, da `seq_along()` bei leeren Vektoren korrekt einen leeren Vektor zurückgibt.
\vfill


# Kontrollstrukturen: Geschachtelte `for`-Schleifen

\normalsize
\textcolor{darkblue}{Geschachtelte Schleifen}

\small
Bei geschachtelten `for`-Schleifen werden für jede Iteration der äußeren Schleife alle Iterationen der inneren Schleife durchlaufen.

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = T}
n_i <- 2                             # Anzahl der Iterationen äußere Schleife
n_j <- 3                             # Anzahl der Iterationen innere Schleife
for(i in 1:n_i){                     # Äußere Schleife
  for (j in 1:n_j){                  # Innere Schleife
    print(c(i,j))                    # Anzeigen der Iterationsindizes [i,j]
    }
}
```
\vfill


# Kontrollstrukturen: Geschachtelte `for`-Schleifen

\textcolor{darkcyan}{Beispiel: Matrix befüllen}

\small
Geschachtelte Schleifen eignen sich zum Befüllen von Matrizen.

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = T}
# Matrix zeilenweise mit Spaltenindizes befüllen
n <- 4                                   # Zeilenanzahl
m <- 5                                   # Spaltenanzahl
A <- matrix(rep(NaN, n*m), nrow = n)     # Matrixvorallokation

for (i in 1:n) {                         # Äußere Schleife: iterieren der Zeilenindizes
  for (j in 1:m) {                       # Innere Schleife: iterieren der Spaltenindizes
    A[i, j] <- j                         # Element = Spaltenindex
  }
}
print(A)
```
\vfill


# Kontrollstrukturen: Geschachtelte `for`-Schleifen

\textcolor{darkcyan}{Beispiel: Matrix befüllen (fortgeführt)}

\vspace{2mm}
\footnotesize
```{r, echo = T, eval = T}
# Matrix zeilenweise mit Zeilenindizes befüllen
n <- 4                                   # Zeilenanzahl
m <- 5                                   # Spaltenanzahl
B <- matrix(rep(NaN, n*m), nrow = n)     # Matrixvorallokation

for (i in 1:n) {                         # Äußere Schleife: iterieren der Zeilenindizes
  for (j in 1:m) {                       # Innere Schleife: iterieren der Spaltenindizes
    B[i, j] <- i                         # Element = Zeilenindex
  }
}
print(B)
```
\vfill


# Kontrollstrukturen: Geschachtelte `for`-Schleifen

\textcolor{darkcyan}{Beispiel: Matrix befüllen (fortgeführt)}

\small
Kombination von geschachtelten Schleifen mit `if`-statement:

\vspace{2mm}
\footnotesize
\setstretch{1.1}
```{r, echo = T, eval = T}
# Eine Matrix mit Spaltenindizes befüllen, wenn Spaltenindex >= Zeilenindex

n <- 4                                 # Zeilenanzahl
m <- 5                                 # Spaltenanzahl
C <- matrix(rep(NaN, n*m), nrow = n)   # Matrixvorallokation

for (i in 1:n) {                       # Äußere Schleife: Iterieren der Zeilenindizes
  for (j in 1:m) {                     # Innere Schleife: Iterieren der Spaltenindizes
    if (j >= i) {                      # Bedingung: Spaltenindex >= Zeilenindex
      C[i, j] <- j                     # Element = Spaltenindex für j >= i
    } else {
      C[i, j] <- 0                     # Element = 0 für j < i
    }
  }
}
print(C)
```


# Kontrollstrukturen: `while` -Schleifen

\textcolor{darkblue}{while-Schleifen}

\small
Führt einen Codeblock wiederholt aus, solange eine Bedingung den Wert \texttt{TRUE} hat.

\vspace{2mm}
\footnotesize
\setstretch{1.1}
```{r, echo = T, eval = F}
while (Bedingung) {
  TrueAktion            # TrueAktion wird ausgeführt, solange Bedingung == TRUE
}
```
\vfill

\normalsize
\textcolor{darkcyan}{Beispiel}

\vspace{2mm}
\footnotesize
\setstretch{1.1}
```{r, echo = T, eval = T}
i <- 5
while (i < 11) {
  print(i)
  i <- i + 1
}
```


# Kontrollstrukturen: `repeat` -Schleifen

\setstretch{1.3}

\normalsize
\textcolor{darkblue}{repeat-Schleifen}

\small
Wiederholt einen Codeblock unbegrenzt oft, bis eine \texttt{break}-Anweisung die Schleife beendet.

\vspace{2mm}
\footnotesize
\setstretch{1.1}
```{r, echo = T, eval = F}
# Pseudocode
repeat {
  Aktion                # Aktion wird ausgeführt, bis ein break Befehl evaluiert wird
}
```
\vfill

\normalsize
\textcolor{darkcyan}{Beispiel}

\vspace{2mm}
\footnotesize
\setstretch{1.1}
```{r, echo = T, eval = T}
i <- 1
repeat {
  print(i)
  i <- i + 1
  if (i == 5) {
    break
  }
}
```


# Debugging ====================================== {.plain}
\AtBeginSection{}
\section{Debugging}
\setstretch{3}
\large
\vfill

Kontrollfluss

**Debugging**

Programmierübungen

\vfill


# Debugging

\setstretch{1.5}

\vfill
\justifying
"Als Debuggen (dt. Entwanzen) oder Fehlerbehebung bezeichnet man in der Informatik den Vorgang, in einem Computerprogramm Fehler oder unerwartetes Verhalten zu diagnostizieren und zu beheben. Die Suche von Programmfehlern (sogenannten Bugs) ist eine der wichtigsten und anspruchsvollsten Aufgaben der Softwareentwicklung und nimmt einen großen Teil der Entwicklungszeit in Anspruch."

\vfill
\flushright
\textit{Wikipedia}


# \textit{print} debugging

\small
Gezieltes Einfügen von \texttt{print}-Anweisungen im Code an den Stellen, an denen bestimmte Variablenwerte oder Zwischenergebnisse inspiziert werden sollen. Diese Methode hilft, die Ausführungsschritte und den aktuellen Zustand des Programms besser zu verstehen.
\vfill

\textcolor{darkcyan}{Beispiel}

\vspace{2mm}
\footnotesize
```{r, eval = F, echo = T}
#| label: print()
#| error: true
# Fehlerhaftes Skript
meine_Liste    <- list("1", 2, "drei", TRUE)
listen_element <- meine_Liste[2]
rechenergebnis <- exp(listen_element)
print(rechenergebnis)
```

```{r, eval = T, echo = F}
#| error: true
# Fehlerhaftes Skript
meine_Liste    <- list("1", 2, "drei", TRUE)
listen_element <- meine_Liste[2]
rechenergebnis <- exp(listen_element)
print(rechenergebnis)
```

\textbf{Problem}: Die Variable \texttt{listen\_element} scheint \texttt{non-numeric} zu sein.


# \textit{print} debugging

\small
\textcolor{darkcyan}{Beispiel (fortgeführt)}

\footnotesize
\textbf{Problemanalyse}: Im Folgenden wird die Variable \texttt{listen\_element} über den Printbefehl \texttt{cat()} inspiziert.

\vfill
```{r, eval = F, echo = T}
#| error: true
# Fehlerhaftes Skript mit print-debugging
meine_Liste    <- list("1", 2, "drei", TRUE)
listen_element <- meine_Liste[2]
cat(                                           # print debugging
  "listen_element:", listen_element,           # Ausgabe des Werts der Variable
  "Typ:", typeof(listen_element)               # Ausgabe des Typs der Variable
)
rechenergebnis <- exp(listen_element)
print(rechenergebnis)
```

```{r, eval = T, echo = F}
#| error: true
# Debugging
meine_Liste    <- list("1", 2, "drei", TRUE)
listen_element <- meine_Liste[2]
print(paste("listen_element:", listen_element, "Typ:", typeof(listen_element)))
rechenergebnis <- exp(listen_element)
print(rechenergebnis)
```

\vfill
\textbf{Ergebnis}:
\texttt{listen\_element} ist vom Typ \texttt{list}, obwohl wir den Wert eines einzelnen Elements der Liste erwarten.

\textbf{Fehlerursache}:
Falsche Indizierung der Liste: Es wurde \texttt{[]} verwendet, statt der korrekten \texttt{[[]]}, um auf das Element der Liste zuzugreifen. \texttt{[]} gibt eine Liste zurück, während \texttt{[[]]} den tatsächlichen Wert des Elements extrahiert.


# Debugging mit \texttt{browser()}

\vspace{2mm}
\setstretch{1.4}

\small
Die `R base` Funktion `browser()` pausiert die Ausführung des Programms und erlaubt das Inspizieren der aktuellen Umgebung (*Global Environment*). Variablenwerte, Funktionen und andere Elemente können interaktiv geprüft werden, um den Ursprung von Fehlern einzugrenzen.

\textcolor{darkcyan}{Beispiele}

\vspace{2mm}
\footnotesize
\setstretch{1.1}
```{r, eval = F, echo = T}
#| label: browser()
# Beispiel 1
var_1    <- 1
var_2    <- 3
ergebnis <- c()
browser()                                  # Pausiert Skript
print("Das Ergebnis ist: ", ergebnis)
ergebnis <- var_1 + var_2
browser()                                  # Pausiert Skript

# Beispiel 2
for (i in 1:5) {
  print(i + 2)
  browser()                                # Pausiert Skript in jeder Iteration
}
```

\small
\setstretch{1.4}

Über das Argument `expr` kann auch eine Bedingung als boolesche Operation spezifiziert werden.

Mit \fbox{Enter} wird die Exekution fortgeführt.

Mit \fbox{Q} wird der browser beendet.


# Programmierübungen ====================================== {.plain}
\AtBeginSection{}
\section{Programmierübungen}
\setstretch{3}
\large
\vfill

Kontrollfluss

Debugging

**Programmierübungen**

\vfill


# Programmierübungen

\footnotesize
\setstretch{1.5}

\begin{enumerate}
\justifying
\item Erstellen Sie R-Code, der überprüft, ob eine Zahl positiv, negativ oder null ist, und geben Sie eine entsprechende Nachricht aus.
\item Erstellen Sie R-Code, der eine numerische Eingabe für einen Wochentag akzeptiert und den vollständigen Namen des Wochentages ausgibt (z.B. 1 für Montag, 2 für Dienstag, usw.).
\item Schreiben Sie ein R-Skript, das die Zahlen von 1 bis 10 ausgibt. Jede Zahl soll in einer neuen Zeile stehen.
\item Schreiben Sie ein R-Skript mit einer \texttt{while}-Schleife, das beginnend bei 1, so lange aufeinanderfolgende Zahlen ausgibt, bis die Summe aller ausgegebenen Zahlen größer als 20 ist.
\item Erstellen Sie mithilfe geschachtelter \texttt{for}-Schleifen eine 3x3 Matrix, deren Elemente die Summe aus Zeilen- und Spaltenindex enthalten.
\item Der untenstehende Code soll in jeder Iteration der Schleife das Quadrat eines Elements aus dem Vektor \texttt{zahlen} ausgeben (d.h. in der ersten Iteration \texttt{1}, in der zweiten \texttt{4}, usw.). Stattdessen werden in jeder Iteration fünf Werte ausgegeben. Ihre Aufgabe ist es, den Fehler zu finden. Verwenden Sie dazu \texttt{print()} und \texttt{browser()} als Debugging-Methoden, um den Fehler zu identifizieren.
\end{enumerate}

\vfill
\footnotesize
\setstretch{1.1}
```{r, echo = F, eval = T}
zahlen <- c(1, 2, 3, 4, 5)
for (zahl in zahlen) {
  quadrat <- zahlen^2
  print(quadrat)
}
```
