# Warm-ups (freiwillig)

Quelle: https://dev.inf.zone/exercises/05/warm-ups/

**Wozu das Ganze?**

Die Warm-ups führen die neuen Sprachmittel aus der Vorlesung „3. Algorithmen“ in kleinen Schritten ein. Sie sind freiwillig, zählen nicht für die Bonuspunkte und sind nicht prüfungsrelevant. 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) | Structs definieren | Mehrheitswahl, Stichwahl |
| [Warm-up 2](#warm-up-2) | Arrays von Structs | Mehrheitswahl, Stichwahl |
| [Warm-up 3](#warm-up-3) | Suchen mit `strcmp` | Mehrheitswahl, Stichwahl |
| [Warm-up 4](#warm-up-4) | Arrays in Structs | Stichwahl |
| [Warm-up 5](#warm-up-5) | Schleifen vorzeitig verlassen mit `break` | Stichwahl |

Legen Sie für die Warm-ups eine eigene Datei an, zum Beispiel `warmup_aufgaben_2.c` für Übung 2, 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://dev.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: Structs definieren

In C kann man eine `struct` definieren, um zusammengehörige Informationen besser zu verwalten.

Die nachfolgend definierte `struct` enthält etwa einen `string` namens `name` und einen `int` namens `age`. Durch die Verwendung von `typedef` wird diese `struct` als ein uns zusätzlich zur Verfügung stehender Datentyp `person` definiert *(Details dazu folgen später im Kurs; hier sind sie noch nicht nötig)*.

```c
// Person has name and age
typedef struct
{
    string name;
    int age;
} person;

int main(void)
// ...
```
Kopieren Sie diese `struct`-Definition in Ihre Datei oberhalb der `main`-Funktion.

Erstellen Sie in der `main`-Funktion eine Variable vom Typ `person` namens `person1` und weisen Sie den Membern (d. h. `name` und `age`) die Werte `Bob` und `37` zu.

Geben Sie diese anschließend mit
```c
printf("Name: %s\nAlter: %i\n", /* zu ergänzen */);
``` 
aus:
```plaintext
Name: Bob
Alter: 37
```

**Wo zu finden?**

Bei Problemen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zur Vorlesung [3. Algorithmen](https://dev.inf.zone/lectures/3-algorithmen/) an.

## Warm-up 2: Arrays von Structs

Deklarieren Sie ein Array als **globale** Variable vom Typ `person` namens `people` der Größe `MAX_PEOPLE`. Legen Sie daher außerdem eine globale Konstante namens `MAX_PEOPLE` mit dem Wert `3` an. [Erinnern Sie sich](https://dev.inf.zone/lectures/1-c/short-1-6-magic-numbers/), dass Sie eine symbolische Konstante mittels `#define [NAME] [WERT]` erstellen können.

Verwenden Sie das folgende Snippet, um dem Array in der `main`-Funktion entsprechende Werte zuzuweisen:
```c
    people[0] = person1;

    people[1].name = "Alice";
    people[1].age = 31;
    
    people[2].name = "Eve";
    people[2].age = 32;
```

Geben Sie anschließend die Daten der zweiten Person mit dem entsprechend angepassten `printf` wie zuvor aus:
```plaintext
Name: Alice
Alter: 31
```

**Wo zu finden?**

Bei Problemen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zur Vorlesung [3. Algorithmen](https://dev.inf.zone/lectures/3-algorithmen/) an. Das Anlegen von symbolischen Konstanten wurde im Short zu den [Magic Numbers](https://dev.inf.zone/lectures/1-c/short-1-6-magic-numbers/) erklärt.

Sie haben den Unterschied zwischen lokalen und globalen Variablen noch nicht verstanden? Dann ist jetzt ein guter Zeitpunkt, um noch einmal das entsprechende Short [Scope](https://dev.inf.zone/lectures/2-arrays/short-2-2-scope/) anzusehen.

## Warm-up 3: Suchen mit `strcmp`

Erstellen Sie eine Funktion `void find_person_with_name(string name)`, die über das Array `people` iteriert und die Person mit dem eingegebenen Namen sucht. Erinnern Sie sich an die Funktion `strcmp` zum Vergleichen von Strings (erfordert die Einbindung von `<string.h>`). Was gibt `strcmp` zurück, wenn zwei Strings gleich sind?

Wenn der Name in dem `people`-Array gefunden wurde, geben Sie den Namen und das Alter wie zuvor aus (verschieben Sie dazu einfach das `printf` aus der `main`-Funktion und passen Sie es an). Anschließend können Sie die Funktion sofort mit `return;` beenden. Wenn der Name nach dem Durchlaufen der Schleife nicht gefunden wurde, soll `Der Name wurde nicht gefunden.\n` vor dem `return`en der Funktion ausgegeben werden.

Die Funktion können Sie in der `main`-Funktion mit `find_person_with_name(argv[1]);` aufrufen. Den gesuchten Namen übergeben Sie also einfach als Kommandozeilenargument. Auf eine Verifizierung der Argumente können Sie im Rahmen dieser Warm-ups verzichten. Sie müssen jedoch noch die Signatur der `main`-Funktion anpassen, um Kommandozeilenargumente entsprechend verarbeiten zu können.

**Tipp: Text ins Terminal kopieren, frühere Befehle wiederholen**

Mit `Strg+Shift+C` und `Strg+Shift+V` (bei Windows, ansonsten rechter Mausklick in das Terminalfenster) kann man Text in die Kommandozeile kopieren. Zuvor genutzte Befehle kann man mit den Pfeiltasten (hoch/runter) oder `Strg+R` erneut aufrufen.

Bei der Eingabe `Eve` sollte folgendes ausgegeben werden:
```plaintext
Name: Eve
Alter: 32
```

Bei der Eingabe `Mallory` sollte folgendes ausgegeben werden:
```plaintext
Der Name wurde nicht gefunden.
```

Bei der Eingabe `bob` sollte folgendes ausgegeben werden (`strcmp` ist *case-sensitive*!):
```plaintext
Der Name wurde nicht gefunden.
```

**Wo zu finden?**

Bei Problemen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zu den verschiedenen Versionen des Programms `search.c` aus der Vorlesung [3. Algorithmen](https://dev.inf.zone/lectures/3-algorithmen/) sowie das Short zur [Linearen Suche](https://dev.inf.zone/lectures/3-algorithmen/short-3-1-lineare-suche/) an. Die Funktion und Verwendung von `strcmp` finden Sie auch im [CS50 Handbuch](https://manual.cs50.io/3/strcmp).

Sie haben noch nicht verstanden, wie Sie Argumente über die Kommandozeile übergeben und in Ihrem Programm verarbeiten können? Dann ist jetzt ein guter Zeitpunkt, um noch einmal das entsprechende Short [Kommandozeilenargumente](https://dev.inf.zone/lectures/2-arrays/short-2-6-cmdlineargs/) anzusehen.

## Warm-up 4: Arrays in Structs

Ergänzen Sie die eingangs angelegte `struct`-Definition um ein `string`-Array namens `hobbies`. Die maximale Anzahl von `hobbies` soll über eine Konstante `MAX_HOBBIES` auf `3` festgesetzt werden.

So sollte Ihre angepasste `struct` aussehen:
```c
#define MAX_PEOPLE 3
#define MAX_HOBBIES 3

// Person has name, age and hobbies
typedef struct
{
    string name;
    int age;
    string hobbies[MAX_HOBBIES];
} person;
```

Diesem Member können Sie mit dem folgenden Snippet Werte zuweisen:
```c
    people[0].hobbies[0] = "Programmieren";
    people[0].hobbies[1] = "Kochen";
    people[0].hobbies[2] = "Lesen";

    people[1].hobbies[0] = "Schwimmen";
    people[1].hobbies[1] = "Lesen";
    people[1].hobbies[2] = "Programmieren";

    people[2].hobbies[0] = "Fotografie";
    people[2].hobbies[1] = "Programmieren";
    people[2].hobbies[2] = "Kartenspiele";
```

Schreiben Sie eine Funktion `int count_hobby(string hobby)`, die über den Datensatz iteriert und zählt, wie viele Personen das gesuchte Hobby ausüben. Wird das Hobby bei einer der Personen gefunden, geben Sie wie zuvor die Daten zu dieser Person (d.h. `name` und `age`, nicht die `hobbies`) aus. Geben Sie am Ende die entsprechende Häufigkeit des Hobbys zurück.

**Pseudocode**

Sie können sich an dem folgenden (etwas detaillierteren) Pseudocode orientieren.
Die Funktion benötigt folgende Elemente:
-   Eine Variable `count`, die beim Finden des Hobbys erhöht wird.
-   Eine Schleife, die über das `people`-Array iteriert.
    -   Eine darin verschachtelte Schleife, die für jede `person` im `people`-Array über die `hobbies` dieser `person` iteriert.
        -   Eine Bedingung, die prüft, ob ein Hobby dieser `person`, d.h. `people[i].hobbies[j]`, mit dem gesuchten Hobby übereinstimmt.
            -   Im Falle von `true`: Die Erhöhung von `count` um `1`.
            -   Den `printf`-Aufruf, den Sie von `find_person_with_name()` übernehmen können.
-   Die Rückgabe von `count` am Ende.

Die Funktion können Sie in der `main`-Funktion mit `int count = count_hobby(argv[1]);` aufrufen. Das gesuchte Hobby übergeben Sie wieder als Kommandozeilenargument. Geben Sie schließlich das Ergebnis mit
```c
printf("Das Hobby %s wurde %i mal gefunden.\n", argv[1], count);
```
aus – und kommentieren Sie am besten noch den Aufruf von `find_person_with_name()` aus.

Bei der Eingabe von `Programmieren`:
```plaintext
Name: Bob
Alter: 37
Name: Alice
Alter: 31
Name: Eve
Alter: 32
Das Hobby Programmieren wurde 3 mal gefunden.
```

Bei der Eingabe von `Kartenspiele`:
```plaintext
Name: Eve
Alter: 32
Das Hobby Kartenspiele wurde 1 mal gefunden.
```

Bei der Eingabe von `Backen`:
```plaintext
Das Hobby Backen wurde 0 mal gefunden.
```

**Wo zu finden?**

Bei Problemen und Unklarheiten schauen Sie sich am besten noch einmal die Folien und Notizen zur Vorlesung [3. Algorithmen](https://dev.inf.zone/lectures/3-algorithmen/) sowie das Short zur [Linearen Suche](https://dev.inf.zone/lectures/3-algorithmen/short-3-1-lineare-suche/) an. Vollziehen Sie ggf. noch einmal den Code von [Warm-up 3](#warm-up-3) nach. Welcher Unterschied besteht? Wie müssen Sie das Vorgehen anpassen?

## Warm-up 5: Schleifen vorzeitig verlassen mit `break`

Erhöhen Sie `MAX_HOBBIES` von `3` auf `5`.

Fügen Sie den Hobby-Arrays die folgenden Werte hinzu:
```c
    people[0].hobbies[3] = "Programmieren";
    people[0].hobbies[4] = "Kochen";

    people[1].hobbies[3] = "Schwimmen";
    people[1].hobbies[4] = "Programmieren";

    people[2].hobbies[3] = "Kartenspiele";
    people[2].hobbies[4] = "Fotografie";
```

Wie Sie vielleicht bemerkt haben, enthält der Datensatz nun Duplikate. Eine Person hat das gleiche Hobby mehrmals in ihrem Hobby-Array. Dies würde die Zählung verfälschen, da gezählt werden soll, wie viele Personen ein bestimmtes Hobby haben. 

Ergänzen Sie `count_hobby()` so, dass sobald ein Hobby bei einer Person gezählt wurde, die Zählung für diese Person sofort beendet wird, um Doppelzählungen zu vermeiden.

Tipp: Erinnern Sie sich daran, dass man mit `break;` das Durchlaufen einer Schleife vorzeitig beenden kann.

Bei der Eingabe von `Programmieren`:
```plaintext
Name: Bob
Alter: 37
Name: Alice
Alter: 31
Name: Eve
Alter: 32
Das Hobby Programmieren wurde 3 mal gefunden.
```

Bei der Eingabe von `Kartenspiele`:
```plaintext
Name: Eve
Alter: 32
Das Hobby Kartenspiele wurde 1 mal gefunden.
```

Bei der Eingabe von `Backen`:
```plaintext
Das Hobby Backen wurde 0 mal gefunden.
```

**Wo zu finden?**

Die Verwendung von `break` wurde im Short zu [Schleifen](https://dev.inf.zone/lectures/1-c/short-1-4-schleifen/) erklärt.

<br>
