Ihr Notizbuch wird viele Notizen haben, und vorher wissen Sie nicht, wie viele. Für jede Notiz eine eigene Variable anzulegen, geht nicht. Sie brauchen eine Variable, die beliebig viele Werte aufnimmt: eine Liste.

Eine Liste anlegen und füllen

C#
// einkauf.cs
List<string> einkauf = ["Brot", "Milch"];
einkauf.Add("Äpfel");
Console.WriteLine($"Auf der Liste stehen {einkauf.Count} Dinge.");
Console.WriteLine($"Das erste ist {einkauf[0]}, das letzte {einkauf[einkauf.Count - 1]}.");
foreach (string ding in einkauf)
{
    Console.WriteLine($"- {ding}");
}
Auf der Liste stehen 3 Dinge.
Das erste ist Brot, das letzte Äpfel.
- Brot
- Milch
- Äpfel

Der Reihe nach:

  • List<string> ist der Typ „Liste von Texten“. In den spitzen Klammern steht, was in der Liste liegt. Eine Liste von ganzen Zahlen wäre List<int>.
  • In eckigen Klammern stehen die Einträge, mit denen die Liste beginnt. Eine leere Liste schreiben Sie als [].
  • Add hängt einen Eintrag hinten an.
  • Count ist die Anzahl der Einträge.
  • einkauf[0] ist der erste Eintrag. Listen zählen ab 0, nicht ab 1. Der letzte Eintrag hat deshalb die Nummer Count - 1.
  • foreach geht die Liste von vorn bis hinten durch. In jedem Durchlauf steht der aktuelle Eintrag in der Variablen ding.

Fragen Sie nach einer Nummer, die es nicht gibt, etwa einkauf[3] bei drei Einträgen, bricht das Programm mit einer ArgumentOutOfRangeException ab. Prüfen Sie Nummern deshalb vorher gegen Count.

Nummerieren mit for

Menschen zählen ab 1, Listen ab 0. Wenn Sie Einträge mit Nummern zeigen wollen, nehmen Sie for und rechnen eins dazu:

C#
// nummeriert.cs
List<string> aufgaben = ["Steuer abgeben", "Fahrrad flicken", "Oma anrufen"];
for (int i = 0; i < aufgaben.Count; i++)
{
    Console.WriteLine($"{i + 1}. {aufgaben[i]}");
}
1. Steuer abgeben
2. Fahrrad flicken
3. Oma anrufen

Die Bedingung heißt i < aufgaben.Count, nicht <=. Bei drei Einträgen läuft i also von 0 bis 2, genau die gültigen Nummern.

Einträge entfernen

C#
// entfernen.cs
List<string> aufgaben = ["Steuer abgeben", "Fahrrad flicken", "Oma anrufen"];
aufgaben.Remove("Fahrrad flicken");
aufgaben.RemoveAt(0);
foreach (string aufgabe in aufgaben)
{
    Console.WriteLine(aufgabe);
}
Console.WriteLine(aufgaben.Contains("Oma anrufen"));
Oma anrufen
True

Remove sucht einen Eintrag mit genau diesem Text und entfernt ihn. RemoveAt entfernt den Eintrag an einer Nummer, hier die 0, also den ersten. Die Einträge dahinter rücken auf. Contains sagt, ob ein Eintrag mit genau diesem Text in der Liste steht.

Suchen

Für eine Suche in Notizen ist „genau dieser Text“ zu streng. Sie wollen alle Einträge, in denen ein Suchwort irgendwo vorkommt, egal ob groß oder klein geschrieben. Das kann Contains auch für einen einzelnen Text:

C#
// suchen.cs
List<string> notizen = ["Zahnarzt am Dienstag", "Brot kaufen", "Dienstreise vorbereiten", "Geburtstag von Tom"];
string suche = "dienst";
int treffer = 0;
foreach (string notiz in notizen)
{
    if (notiz.Contains(suche, StringComparison.OrdinalIgnoreCase))
    {
        Console.WriteLine(notiz);
        treffer++;
    }
}
Console.WriteLine($"{treffer} Treffer für \"{suche}\".");
Zahnarzt am Dienstag
Dienstreise vorbereiten
2 Treffer für "dienst".

notiz.Contains(suche, ...) fragt, ob das Suchwort in diesem einen Text vorkommt. StringComparison.OrdinalIgnoreCase sagt: „Groß- und Kleinschreibung nicht beachten.“ Der Name ist lang, aber Ihr Editor ergänzt ihn, sobald Sie die ersten Buchstaben tippen.

Neben Listen gibt es Arrays, geschrieben etwa string[] tage = ["Mo", "Di", "Mi"];. Sie funktionieren ähnlich, haben aber eine feste Länge. Für Daten, die wachsen sollen, ist die Liste die bessere Wahl. Arrays begegnen Ihnen in Lektion 10 wieder.

Übung 1

Schreiben Sie namen.cs. Das Programm fragt so lange nach Namen, bis eine leere Zeile kommt, und sammelt sie in einer Liste. Danach schreibt es, wie viele Namen es sind, und listet sie nummeriert auf.

Lösung 1

C#
// namen.cs
List<string> namen = [];
while (true)
{
    Console.Write("Name (leer = fertig): ");
    string name = Console.ReadLine() ?? "";
    if (name == "")
    {
        break;
    }
    namen.Add(name);
}

Console.WriteLine($"{namen.Count} Namen:");
for (int i = 0; i < namen.Count; i++)
{
    Console.WriteLine($"{i + 1}. {namen[i]}");
}
Name (leer = fertig): Ada
Name (leer = fertig): Linus
Name (leer = fertig): Grace
Name (leer = fertig):
3 Namen:
1. Ada
2. Linus
3. Grace

Die Liste wird vor der Schleife angelegt, damit sie nach der Schleife noch da ist, genau wie die Summe in Lektion 6.

Übung 2

Erinnern Sie sich an die Anleitung für den wörtlichen Helfer aus Lektion 1? Jetzt schreiben Sie sie in C#. Nehmen Sie diese Liste:

List<int> zahlen = [4, 17, 9, 23, 8];

Schreiben Sie groesste.cs, das die größte Zahl findet und ausgibt, ohne fertige Hilfsmittel, nur mit einer Schleife und einem if. Geben Sie danach auch den Durchschnitt aus.

Lösung 2

C#
// groesste.cs
List<int> zahlen = [4, 17, 9, 23, 8];
if (zahlen.Count == 0)
{
    Console.WriteLine("Die Liste ist leer.");
}
else
{
    int groesste = zahlen[0];
    int summe = 0;
    foreach (int zahl in zahlen)
    {
        if (zahl > groesste)
        {
            groesste = zahl;
        }
        summe += zahl;
    }
    double durchschnitt = (double)summe / zahlen.Count;
    Console.WriteLine($"Die größte Zahl ist {groesste}.");
    Console.WriteLine($"Der Durchschnitt ist {durchschnitt}.");
}
Die größte Zahl ist 23.
Der Durchschnitt ist 12,2.

Das ist Schritt für Schritt die Anleitung aus Lektion 1, einschließlich der leeren Liste. Für den Durchschnitt teilen Sie die Summe (61) durch die Anzahl (5). Wären beide int, ergäbe das nach der Ganzzahl-Division aus Lektion 4 nur 12. (double)summe macht aus der Summe vorher eine Zahl mit Nachkommastellen. Wie in Lektion 4 steht dort je nach Spracheinstellung 12,2 oder 12.2.

C# bringt für solche Aufgaben auch fertige Werkzeuge mit, etwa zahlen.Max(). Sie lernen sie im Aufbaukurs kennen. Einmal selbst geschrieben, wissen Sie aber, was darin passiert.

Übung 3

Schreiben Sie liste-durchsuchen.cs. Es beginnt mit einer Liste von fünf Notizen Ihrer Wahl, fragt nach einem Suchwort und zeigt alle Notizen, die es enthalten, egal ob groß oder klein geschrieben. Gibt es keinen Treffer, schreibt es „Nichts gefunden.“

Lösung 3

C#
// liste-durchsuchen.cs
List<string> notizen = ["Zahnarzt am Dienstag", "Brot kaufen", "Dienstreise vorbereiten", "Geburtstag von Tom", "Reifen wechseln"];
Console.Write("Wonach suchen Sie? ");
string suche = Console.ReadLine() ?? "";
bool gefunden = false;
foreach (string notiz in notizen)
{
    if (notiz.Contains(suche, StringComparison.OrdinalIgnoreCase))
    {
        Console.WriteLine($"- {notiz}");
        gefunden = true;
    }
}
if (!gefunden)
{
    Console.WriteLine("Nichts gefunden.");
}
Wonach suchen Sie? brot
- Brot kaufen

Statt eines Zählers merkt sich hier eine bool-Variable, ob es mindestens einen Treffer gab. Beides ist richtig. Was passiert, wenn Sie gar nichts eingeben und gleich Enter drücken? Ein leerer Text steckt in jedem Text, also erscheinen alle Notizen. Für eine Suche ist das sogar praktisch. Im Notizbuch werden Sie es trotzdem abfangen.

Was Sie jetzt können

  • Sie legen eine List<string> oder List<int> an, auch leer mit [].
  • Sie fügen mit Add hinzu, zählen mit Count, lesen mit [nummer] und entfernen mit Remove und RemoveAt.
  • Sie wissen, dass Listen ab 0 zählen, und zeigen trotzdem Nummern ab 1 an.
  • Sie gehen mit foreach und for über eine Liste.
  • Sie suchen mit Contains und StringComparison.OrdinalIgnoreCase.
  • Sie haben Ihren ersten Algorithmus selbst geschrieben.

Weiterlesen