# Warm-ups (freiwillig)

Quelle: https://inf.zone/exercises/02/warm-ups/

**Wozu das Ganze?**

Die Warm-ups führen die neuen Sprachmittel aus der Vorlesung „2. Arrays“ in kleinen Schritten ein. Sie sind freiwillig und spielen für die [Joker-Regel](https://inf.zone/extras/exam/#joker-regel) keine Rolle. Nutzen Sie sie, wenn Sie bei einer Aufgabe nicht wissen, wie Sie anfangen sollen. Wenn Sie direkt loslegen können, fangen Sie mit den Aufgaben an.

Sie müssen nicht alle Warm-ups machen. Suchen Sie sich in der Tabelle das heraus, was Ihnen für eine Aufgabe fehlt:

| | Übt | Hilft bei |
|---|---|---|
| [Warm-up 1](#warm-up-1) | Strings anlegen | Scrabble, Lesbarkeit |
| [Warm-up 2](#warm-up-2) | Über einen String iterieren | Scrabble, Lesbarkeit |
| [Warm-up 3](#warm-up-3) | Zeichen prüfen mit `isupper` | Scrabble, Lesbarkeit |
| [Warm-up 4](#warm-up-4) | Nur Buchstaben ausgeben | Lesbarkeit |
| [Warm-up 5](#warm-up-5) | Mit Zeichen rechnen: Position im Alphabet | Scrabble |
| [Warm-up 6](#warm-up-6) | Arrays als Nachschlagetabelle | Scrabble |
| [Warm-up 7](#warm-up-7) | Ganzzahl- und Gleitkommadivision | Lesbarkeit |

Legen Sie für die Warm-ups eine eigene Datei an, zum Beispiel `warmup_aufgaben_1.c` für Übung 1, im selben Ordner wie Ihre Übungsaufgaben. Die meisten Warm-ups bauen aufeinander auf: Sie ergänzen die Datei Schritt für Schritt. Lösungen gibt es für die Warm-ups nicht. Unter „Wo zu finden?“ steht jeweils, wo das Thema in Vorlesung und Shorts vorkommt. Mehr dazu im [FAQ zu den Warm-ups](https://inf.zone/faq/uebung-warm-up/).

Mit diesem Gerüst lässt sich die Datei von Anfang an kompilieren:
```c
#include <cs50.h>
#include <stdio.h>

int main(void)
{

    return 0;
}
```

`cs50.h` stellt Funktionen wie `get_string` bereit, `stdio.h` Funktionen wie `printf`.

## Warm-up 1: Strings anlegen

Erstellen Sie einen `string` namens `letters` mit dem Inhalt `"lol HerWdl!o"`.

Geben Sie anschließend den Inhalt an der fünften Position des Strings, also das `H`, mit `printf` aus. Erinnern Sie sich daran, dass die Zählung des Index-Wertes bei `0` beginnt.

**Wo zu finden?**

Bei Problemen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zur Vorlesung [2. Arrays](https://inf.zone/lectures/2-arrays/) sowie das Short zu [Arrays](https://inf.zone/lectures/2-arrays/short-2-5-arrays/) an.

## Warm-up 2: Über einen String iterieren

Erstellen Sie eine Schleife, die über den String iteriert und jeweils die einzelnen `char`-Werte des Strings ohne Zeilenumbruch ausgibt, sodass `lol HerWdl!o` ausgegeben wird. Verwenden Sie `strlen`, um die Länge des Strings abzufragen. Geben Sie im Anschluss einen Zeilenumbruch aus.

Vergessen Sie nicht, `<string.h>` in die Datei einzubinden.

**Wo zu finden?**

Bei Problemen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zur Vorlesung [2. Arrays](https://inf.zone/lectures/2-arrays/) an. Die Funktion und Verwendung von `strlen` finden Sie auch im [CS50-Handbuch](https://manual.cs50.io/3/strlen).

## Warm-up 3: Zeichen prüfen mit `isupper`

In der Vorlesung wurde bereits die Funktion `toupper` aus der `<ctype.h>`-Bibliothek vorgestellt. Eine weitere Funktion ist die `isupper`-Funktion. Lesen Sie sich kurz die entsprechende [Dokumentation](https://manual.cs50.io/3/isupper) durch.

Binden Sie die `<ctype.h>`-Bibliothek in die Datei ein.
Erweitern Sie die Schleife um eine `if`-Bedingung, die dafür sorgt, dass nur die Großbuchstaben des Strings ausgegeben werden.

Die Ausgabe sollte also folgendermaßen aussehen:

```plaintext
HW
```

Welchen booleschen Ausdruck müssten Sie in die `if`-Bedingung schreiben, wenn Ihnen `isupper` nicht zur Verfügung stünde?

Tipp: Überfliegen Sie die Liste der übrigen Funktionen der `<ctype.h>`-Bibliothek (der Filter-Toggle „frequently used in CS50“ sollte standardmäßig aktiviert sein, ansonsten aktivieren). Diese könnten Ihnen in Zukunft nützlich sein.

**Wo zu finden?**

Bei Problemen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zum Programm `uppercase.c` aus der Vorlesung [2. Arrays](https://inf.zone/lectures/2-arrays/) an.

## Warm-up 4: Nur Buchstaben ausgeben

Ändern Sie die `if`-Bedingung aus Warm-up 3, sodass nur alphabetische Zeichen ausgegeben werden:

```plaintext
lolHerWdlo
```

Wechseln Sie einmal kurz das Ausgabeformat von `printf` von `%c` auf `%i`, sodass die `char`-Werte als Integer ausgegeben werden. Erinnern Sie sich, was hinter der Ausgabe steckt?

**Wo zu finden?**

Bei Problemen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zur Vorlesung [2. Arrays](https://inf.zone/lectures/2-arrays/) an. Beachten Sie zudem den Tipp in [Warm-up 3](#warm-up-3).

## Warm-up 5: Mit Zeichen rechnen: Position im Alphabet

Errechnen Sie nun jeweils die Position des Buchstabens im Alphabet (d. h. für `A` die Position `1`, `B` die Position `2` usw.). Erinnern Sie sich, dass Sie direkt mit `char`-Werten rechnen können (z. B. `'A' - 'A' == 0`).

Ändern Sie dazu `printf`, sodass zunächst der Buchstabe gefolgt von einem `: ` ausgegeben wird und anschließend seine Position im Alphabet. Fügen Sie außerdem einen Zeilenumbruch nach jedem Buchstaben ein.

Tipp: Unabhängig von der Groß- oder Kleinschreibung bleibt die Position eines Buchstabens im Alphabet gleich. Sie können den Buchstaben jeweils in einen Kleinbuchstaben (oder Großbuchstaben) umwandeln, bevor Sie seine Position im Alphabet errechnen. Erinnern Sie sich, dass es hierzu die Funktion `tolower` (oder `toupper`) gibt. Dadurch benötigen Sie keine `if`-`else`-Statements und können die Berechnung innerhalb einer Zeile direkt im `printf`-Aufruf durchführen.

Die Ausgabe sollte folgendermaßen aussehen:

```plaintext
l: 12
o: 15
l: 12
H: 8
e: 5
r: 18
W: 23
d: 4
l: 12
o: 15
```

**Wo zu finden?**

Bei Problemen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zum Programm `uppercase.c` aus der Vorlesung [2. Arrays](https://inf.zone/lectures/2-arrays/) an.

## Warm-up 6: Arrays als Nachschlagetabelle

Dann wollen wir uns jetzt noch um die Entschlüsselung der Zeichenfolge `lol HerWdl!o` kümmern.

Kommentieren Sie den bisherigen Code mittels der Blockkommentar-Syntax aus (dann haben Sie all Ihren geschriebenen Code weiterhin in einer Datei zur Verfügung):
```c
/*

// Code aus Warm-up 1 bis 5

*/
```

Und fügen Sie folgenden Code oben in die Datei ein:
```c
#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    string letters = "lol HerWdl!o";

    for (int i = 0, length = strlen(letters); i < length; i++)
    {
        printf("%c", letters[i]);
    }
    printf("\n");
    return 0;
}
```

Dieser Code kommt Ihnen hoffentlich bekannt vor! So (oder so ähnlich) sollte Ihr Code nach Warm-up 2 ausgesehen haben.

Beim Zugriff auf den Array-Index können auch Operationen und Funktionen ausgeführt und verschachtelt werden. Beispielsweise kann man mit `letters[strlen(letters) - 1]` auf das letzte Zeichen in diesem String zugreifen (`strlen` gibt die Anzahl aller Zeichen zurück und da ein Array mit dem `0`-Index beginnt, muss noch eine `1` abgezogen werden).

Um die Zeichenfolge `lol HerWdl!o` zu entwirren, fügen Sie ein `int`-Array namens `map` wie folgt unterhalb der `string`-Deklaration ein:
```c
int map[] = {4, 5, 2, 9, 1, 3, 7, 11, 6, 0, 8, 10};
```
Hinweis: Mit dieser Initialisierungsliste in geschweiften Klammern bekommt das Array bei der Deklaration gleich alle Werte. Die Größe in `[]` können Sie dann weglassen; der Compiler zählt die Elemente selbst.

Statt wie bisher einfach die Buchstaben nacheinander entsprechend dem Schleifen-Index auszugeben, greifen Sie jeweils auf den Wert des `map`-Arrays am aktuellen Schleifen-Index zu. Verwenden Sie nun diesen Wert als Index, um auf das entsprechende Zeichen in `letters` zuzugreifen. Wie eingangs beschrieben, können Sie alle diese Operationen direkt innerhalb der `printf`-Funktion schachteln.

**Erklärung**

Anstatt mit dem Index der Schleife nacheinander auf die einzelnen Zeichen des Strings zuzugreifen, greifen Sie nun auf `map` zu. Als dessen Index verwenden Sie den Index der Schleife, also `map[i]`.

Um dann mit diesem Wert auf den entsprechenden Array-Index von `letters` zuzugreifen, verschachteln wir die Array-Zugriffe zu `letters[map[i]]`. Im ersten Schleifendurchlauf bedeutet dies, dass zunächst `map[0]` abgefragt wird. Dahinter verbirgt sich die Zahl `4`. Diese Zahl ist nun der Index, mit dem wir auf den String zugreifen (d. h. `letters[4]`). Das bedeutet, wir greifen im *ersten* Schleifendurchlauf auf den Inhalt des Strings an der *fünften* Position zu, also dem `H`.

Wahrscheinlich haben Sie es anhand der Buchstaben schon geahnt: Welcher bekannte Ausspruch verbirgt sich hinter der Zeichenfolge?

**Wo zu finden?**

Bei Fragen und Unklarheiten schauen Sie sich zusätzlich zur obigen **Erklärung** am besten noch einmal das Short zu [Arrays](https://inf.zone/lectures/2-arrays/short-2-5-arrays/) an.

## Warm-up 7: Ganzzahl- und Gleitkommadivision

Nun noch ein letzter kleiner Test Ihres Wissens. Überfliegen Sie das folgende Code-Snippet und führen Sie es aus:

```c
#include <stdio.h>
#include <math.h>

int main(void)
{
    int integerA = 11;
    int integerB = 3;
    float floatB = 3;
    int c = 11 / 3;
    float d = 11 / 3;
    float e = 11 / 3.0;
    float f = integerA / floatB;
    float g = (float) 11 / 3;
    float h = integerA / (float) integerB;
    int i = round(11 / 3);
    int j = round(11.0 / 3);
    int k = round(h);
    float l = round(11) / 3;

    printf("int c = 11 / 3;                        --> %i        (printed with %%i)\n", c);
    printf("float d = 11 / 3;                      --> %f (printed with %%f)\n", d);
    printf("float e = 11 / 3.0;                    --> %f (printed with %%f)\n", e);
    printf("float f = integerA / floatB;           --> %f (printed with %%f)\n", f);
    printf("float g = (float) 11 / 3;              --> %f (printed with %%f)\n", g);
    printf("float h = integerA / (float) integerB; --> %f (printed with %%f)\n", h);
    printf("int i = round(11 / 3);                 --> %i        (printed with %%i)\n", i);
    printf("int j = round(11.0 / 3);               --> %i        (printed with %%i)\n", j);
    printf("int k = round(h);                      --> %i        (printed with %%i)\n", k);
    printf("float l = round(11) / 3;               --> %f (printed with %%f)\n", l);

    return 0;
}
```

Wie kommt die jeweilige Ausgabe zustande? Worauf müssen Sie beim Rechnen in C demnach achten? Und warum genau funktioniert eigentlich die letzte Berechnung mit `round` wie gewünscht? Lesen Sie ggf. die Spezifikation von `round` in der [Dokumentation](https://manual.cs50.io/3/round) nach.

Beachten Sie auch, dass zur Verwendung von `round` `<math.h>` eingebunden werden muss.

**Wo zu finden?**

Bei Fragen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zum Programm `scores.c` aus der Vorlesung [2. Arrays](https://inf.zone/lectures/2-arrays/) und insbesondere das Short zu [Datentypen und Variablen](https://inf.zone/lectures/1-c/short-1-1-datentypen/) an.

<br>
