Jetzt setzen Sie alles zusammen, was Sie gelernt haben: Variablen, Eingaben, Verzweigungen, Schleifen, Listen und Methoden. Das Ergebnis ist ein Notizbuch auf der Konsole. Sie schreiben Notizen hinein, lassen sie sich anzeigen, suchen darin und löschen, was erledigt ist. In der nächsten Lektion lernt es, sich die Notizen über das Programmende hinaus zu merken.
Die Kladde
Kaufleute führten früher ein Buch für den ersten Entwurf, die Kladde. Was am Tag geschah, stand zuerst dort, erst danach sauber im Hauptbuch. Ihr Notizbuch ist der erste Baustein eines Übungsprojekts der Akademie, das diesen Namen trägt. In den Aufbaukursen wächst es weiter: zuerst zu einem Programm mit Kontakten und Terminen, später zu einer Anwendung im Browser. Alle Personen und Daten darin sind erfunden.
Erst planen, dann tippen
Bevor Sie die erste Zeile schreiben, überlegen Sie, was das Programm können soll und wie man es bedient. Das Notizbuch zeigt ein Menü, liest eine Auswahl, tut das Gewählte und zeigt das Menü wieder, bis jemand beendet:
1 Neue Notiz
2 Alle Notizen zeigen
3 Suchen
4 Notiz löschen
0 Beenden
Ihre Wahl:
Daraus ergibt sich der Aufbau:
- Eine Liste
List<string>hält die Notizen. - Eine Schleife zeigt das Menü, bis „0“ gewählt wird.
- Eine Kette aus if und else if entscheidet, was bei welcher Auswahl passiert.
- Für jeden Menüpunkt gibt es eine eigene Methode:
NeueNotiz,ZeigeAlle,Suche,Loesche. So bleibt das Hauptprogramm kurz, und jede Methode hat eine Aufgabe.
Sie bauen das in Schritten. Nach jedem Schritt läuft das Programm, und Sie probieren es aus. So finden Sie einen Fehler dort, wo Sie ihn gerade gemacht haben, statt am Ende in hundert Zeilen zu suchen.
Schritt 1: das Gerüst
Das Gerüst zeigt das Menü und reagiert auf die Auswahl, kann aber noch nichts. Legen Sie notizbuch.cs an:
// notizbuch.cs
Console.WriteLine("Ihr Notizbuch");
bool weiter = true;
while (weiter)
{
ZeigeAuswahl();
string wahl = (Console.ReadLine() ?? "0").Trim();
if (wahl == "0")
{
weiter = false;
}
else if (wahl == "1" || wahl == "2" || wahl == "3" || wahl == "4")
{
Console.WriteLine("Das baue ich gleich.");
}
else
{
Console.WriteLine("Diese Auswahl gibt es nicht.");
}
}
Console.WriteLine("Bis bald!");
static void ZeigeAuswahl()
{
Console.WriteLine();
Console.WriteLine("1 Neue Notiz");
Console.WriteLine("2 Alle Notizen zeigen");
Console.WriteLine("3 Suchen");
Console.WriteLine("4 Notiz löschen");
Console.WriteLine("0 Beenden");
Console.Write("Ihre Wahl: ");
}
Starten Sie es und probieren Sie eine 1, eine 7 und zum Schluss die 0:
Ihr Notizbuch
1 Neue Notiz
2 Alle Notizen zeigen
3 Suchen
4 Notiz löschen
0 Beenden
Ihre Wahl: 1
Das baue ich gleich.
1 Neue Notiz
2 Alle Notizen zeigen
3 Suchen
4 Notiz löschen
0 Beenden
Ihre Wahl: 7
Diese Auswahl gibt es nicht.
1 Neue Notiz
2 Alle Notizen zeigen
3 Suchen
4 Notiz löschen
0 Beenden
Ihre Wahl: 0
Bis bald!
Zwei Dinge sind hier mit Absicht so gebaut:
- Die Schleife läuft, solange
weiterwahr ist. Die Auswahl 0 setztweiterauf falsch, und nach dem Durchlauf endet die Schleife. Einebool-Variable mit sprechendem Namen ist hier leichter zu lesen alswhile (true)mitbreak. ?? "0": Kommt keine Eingabe mehr, gilt das als „Beenden“. Ohne diesen Fall würde das Programm in einer Endlosschleife immer wieder das Menü zeigen.
Schritt 2: Notizen anlegen und zeigen
Jetzt bekommt das Notizbuch seine Liste und die ersten zwei Methoden. NeueNotiz liest einen Text und legt ihn ab, aber nur, wenn er
nicht leer ist:
// Ausschnitt aus notizbuch.cs
static void NeueNotiz(List<string> notizen)
{
Console.Write("Notiz: ");
string text = (Console.ReadLine() ?? "").Trim();
if (text == "")
{
Console.WriteLine("Eine leere Notiz lege ich nicht an.");
return;
}
notizen.Add(text);
Console.WriteLine($"Notiert. Anzahl der Notizen: {notizen.Count}");
}
Das return mitten in der Methode beendet sie vorzeitig. Das ist ein bewährtes Muster: Erst die Fälle abfangen, in denen nichts zu tun
ist, dann die eigentliche Arbeit. So steht die eigentliche Arbeit nicht tief eingerückt in einem else.
ZeigeAlle zeigt die Notizen nummeriert, ab 1 gezählt, oder einen Hinweis, wenn es noch keine gibt:
// Ausschnitt aus notizbuch.cs
static void ZeigeAlle(List<string> notizen)
{
if (notizen.Count == 0)
{
Console.WriteLine("Noch keine Notizen.");
return;
}
for (int i = 0; i < notizen.Count; i++)
{
Console.WriteLine($"{i + 1}. {notizen[i]}");
}
}
Beide Methoden bekommen die Liste als Parameter. Die Liste selbst wird im Hauptprogramm angelegt, einmal, vor der Schleife. Weil eine
Liste nicht kopiert wird, wenn man sie übergibt, arbeiten alle Methoden an derselben Liste: Was NeueNotiz hinzufügt, sieht ZeigeAlle.
So sieht das ganze Programm nach Schritt 2 aus:
// notizbuch.cs
List<string> notizen = [];
Console.WriteLine("Ihr Notizbuch");
bool weiter = true;
while (weiter)
{
ZeigeAuswahl();
string wahl = (Console.ReadLine() ?? "0").Trim();
if (wahl == "1")
{
NeueNotiz(notizen);
}
else if (wahl == "2")
{
ZeigeAlle(notizen);
}
else if (wahl == "0")
{
weiter = false;
}
else if (wahl == "3" || wahl == "4")
{
Console.WriteLine("Das baue ich gleich.");
}
else
{
Console.WriteLine("Diese Auswahl gibt es nicht.");
}
}
Console.WriteLine("Bis bald!");
static void ZeigeAuswahl()
{
Console.WriteLine();
Console.WriteLine("1 Neue Notiz");
Console.WriteLine("2 Alle Notizen zeigen");
Console.WriteLine("3 Suchen");
Console.WriteLine("4 Notiz löschen");
Console.WriteLine("0 Beenden");
Console.Write("Ihre Wahl: ");
}
static void NeueNotiz(List<string> notizen)
{
Console.Write("Notiz: ");
string text = (Console.ReadLine() ?? "").Trim();
if (text == "")
{
Console.WriteLine("Eine leere Notiz lege ich nicht an.");
return;
}
notizen.Add(text);
Console.WriteLine($"Notiert. Anzahl der Notizen: {notizen.Count}");
}
static void ZeigeAlle(List<string> notizen)
{
if (notizen.Count == 0)
{
Console.WriteLine("Noch keine Notizen.");
return;
}
for (int i = 0; i < notizen.Count; i++)
{
Console.WriteLine($"{i + 1}. {notizen[i]}");
}
}
So testen Sie
Testen heißt nicht, einmal zu schauen, ob es irgendwie läuft. Testen heißt, gezielt auszuprobieren, ob das Programm in jedem Fall das Richtige tut, auch in den unbequemen Fällen. Gehen Sie nach Schritt 2 diese Liste durch:
- Gleich nach dem Start die 2: Steht dort „Noch keine Notizen.“?
- Eine Notiz anlegen, dann die 2: Steht sie mit der Nummer 1 da?
- Eine zweite Notiz anlegen: Heißt es „Anzahl der Notizen: 2“?
- Eine Notiz anlegen und nur Enter drücken: Kommt der Hinweis auf die leere Notiz, und bleibt die Anzahl gleich?
- Eine Notiz aus lauter Leerzeichen: Wird sie ebenfalls abgelehnt?
- Als Auswahl ein Wort oder eine 9: Kommt „Diese Auswahl gibt es nicht.“, ohne Absturz?
Bei Fall 2 sieht das so aus:
Ihre Wahl: 1
Notiz: Zahnarzt am Dienstag
Notiert. Anzahl der Notizen: 1
1 Neue Notiz
2 Alle Notizen zeigen
3 Suchen
4 Notiz löschen
0 Beenden
Ihre Wahl: 2
1. Zahnarzt am Dienstag
Im Aufbaukurs schreiben Sie solche Prüfungen als automatische Tests, die bei jeder Änderung von selbst laufen. Die Denkweise ist dieselbe.
Übung 1
Bauen Sie den Menüpunkt 3 ein: eine Methode Suche, die nach einem Suchwort fragt und alle Notizen zeigt, die es enthalten, egal ob
groß oder klein geschrieben. Zeigen Sie bei jedem Treffer die Nummer, die die Notiz in der ganzen Liste hat; die brauchen Sie gleich
zum Löschen. Am Ende steht die Zahl der Treffer. Ein leeres Suchwort lehnt die Methode ab.
Lösung 1
Die neue Methode:
// Ausschnitt aus notizbuch.cs
static void Suche(List<string> notizen)
{
Console.Write("Suchwort: ");
string suchwort = (Console.ReadLine() ?? "").Trim();
if (suchwort == "")
{
Console.WriteLine("Ohne Suchwort suche ich nicht.");
return;
}
int treffer = 0;
for (int i = 0; i < notizen.Count; i++)
{
if (notizen[i].Contains(suchwort, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"{i + 1}. {notizen[i]}");
treffer++;
}
}
Console.WriteLine($"Treffer: {treffer}");
}
Die Suche nimmt for statt foreach, weil sie die Nummer i + 1 braucht. Im Hauptprogramm kommt ein Zweig dazu, und die 3 fällt aus
„Das baue ich gleich“ heraus. Das ganze Programm:
// notizbuch.cs
List<string> notizen = [];
Console.WriteLine("Ihr Notizbuch");
bool weiter = true;
while (weiter)
{
ZeigeAuswahl();
string wahl = (Console.ReadLine() ?? "0").Trim();
if (wahl == "1")
{
NeueNotiz(notizen);
}
else if (wahl == "2")
{
ZeigeAlle(notizen);
}
else if (wahl == "3")
{
Suche(notizen);
}
else if (wahl == "0")
{
weiter = false;
}
else if (wahl == "4")
{
Console.WriteLine("Das baue ich gleich.");
}
else
{
Console.WriteLine("Diese Auswahl gibt es nicht.");
}
}
Console.WriteLine("Bis bald!");
static void ZeigeAuswahl()
{
Console.WriteLine();
Console.WriteLine("1 Neue Notiz");
Console.WriteLine("2 Alle Notizen zeigen");
Console.WriteLine("3 Suchen");
Console.WriteLine("4 Notiz löschen");
Console.WriteLine("0 Beenden");
Console.Write("Ihre Wahl: ");
}
static void NeueNotiz(List<string> notizen)
{
Console.Write("Notiz: ");
string text = (Console.ReadLine() ?? "").Trim();
if (text == "")
{
Console.WriteLine("Eine leere Notiz lege ich nicht an.");
return;
}
notizen.Add(text);
Console.WriteLine($"Notiert. Anzahl der Notizen: {notizen.Count}");
}
static void ZeigeAlle(List<string> notizen)
{
if (notizen.Count == 0)
{
Console.WriteLine("Noch keine Notizen.");
return;
}
for (int i = 0; i < notizen.Count; i++)
{
Console.WriteLine($"{i + 1}. {notizen[i]}");
}
}
static void Suche(List<string> notizen)
{
Console.Write("Suchwort: ");
string suchwort = (Console.ReadLine() ?? "").Trim();
if (suchwort == "")
{
Console.WriteLine("Ohne Suchwort suche ich nicht.");
return;
}
int treffer = 0;
for (int i = 0; i < notizen.Count; i++)
{
if (notizen[i].Contains(suchwort, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"{i + 1}. {notizen[i]}");
treffer++;
}
}
Console.WriteLine($"Treffer: {treffer}");
}
Mit drei Notizen und dem Suchwort „dienst“:
Ihre Wahl: 3
Suchwort: dienst
1. Zahnarzt am Dienstag
3. Dienstreise planen
Treffer: 2
Übung 2
Bauen Sie den Menüpunkt 4 ein: eine Methode Loesche. Sie zeigt zuerst alle Notizen, fragt dann nach der Nummer und entfernt diese
Notiz. Eine Nummer, die es nicht gibt, oder eine Eingabe, die keine Zahl ist, führt zu einem Hinweis, nicht zu einem Absturz. Danach
sagt das Programm, welche Notiz gelöscht wurde.
Denken Sie an zwei Dinge: Die Menschen zählen ab 1, die Liste ab 0. Und bei einer leeren Liste gibt es nichts zu löschen.
Lösung 2
Die neue Methode:
// Ausschnitt aus notizbuch.cs
static void Loesche(List<string> notizen)
{
ZeigeAlle(notizen);
if (notizen.Count == 0)
{
return;
}
Console.Write("Welche Nummer löschen? ");
string eingabe = Console.ReadLine() ?? "";
if (!int.TryParse(eingabe, out int nummer) || nummer < 1 || nummer > notizen.Count)
{
Console.WriteLine($"Bitte eine Nummer von 1 bis {notizen.Count}.");
return;
}
string text = notizen[nummer - 1];
notizen.RemoveAt(nummer - 1);
Console.WriteLine($"Gelöscht: {text}");
}
Loesche ruft ZeigeAlle auf, damit man die Nummern vor Augen hat. Eine Methode darf also eine andere benutzen. Die Bedingung mit
TryParse prüft drei Dinge auf einmal: ob eine Zahl kam, ob sie mindestens 1 ist und ob es so viele Notizen gibt. Erst danach wird aus
der Nummer der Platz in der Liste, nummer - 1. Der Text wird vor dem Entfernen gemerkt, damit die Meldung ihn nennen kann.
Das Hauptprogramm ruft für die 4 jetzt Loesche auf, und kein Menüpunkt muss mehr warten. Das ist der Stand am Ende dieser Lektion:
// notizbuch.cs
List<string> notizen = [];
Console.WriteLine("Ihr Notizbuch");
bool weiter = true;
while (weiter)
{
ZeigeAuswahl();
string wahl = (Console.ReadLine() ?? "0").Trim();
if (wahl == "1")
{
NeueNotiz(notizen);
}
else if (wahl == "2")
{
ZeigeAlle(notizen);
}
else if (wahl == "3")
{
Suche(notizen);
}
else if (wahl == "4")
{
Loesche(notizen);
}
else if (wahl == "0")
{
weiter = false;
}
else
{
Console.WriteLine("Diese Auswahl gibt es nicht.");
}
}
Console.WriteLine("Bis bald!");
static void ZeigeAuswahl()
{
Console.WriteLine();
Console.WriteLine("1 Neue Notiz");
Console.WriteLine("2 Alle Notizen zeigen");
Console.WriteLine("3 Suchen");
Console.WriteLine("4 Notiz löschen");
Console.WriteLine("0 Beenden");
Console.Write("Ihre Wahl: ");
}
static void NeueNotiz(List<string> notizen)
{
Console.Write("Notiz: ");
string text = (Console.ReadLine() ?? "").Trim();
if (text == "")
{
Console.WriteLine("Eine leere Notiz lege ich nicht an.");
return;
}
notizen.Add(text);
Console.WriteLine($"Notiert. Anzahl der Notizen: {notizen.Count}");
}
static void ZeigeAlle(List<string> notizen)
{
if (notizen.Count == 0)
{
Console.WriteLine("Noch keine Notizen.");
return;
}
for (int i = 0; i < notizen.Count; i++)
{
Console.WriteLine($"{i + 1}. {notizen[i]}");
}
}
static void Suche(List<string> notizen)
{
Console.Write("Suchwort: ");
string suchwort = (Console.ReadLine() ?? "").Trim();
if (suchwort == "")
{
Console.WriteLine("Ohne Suchwort suche ich nicht.");
return;
}
int treffer = 0;
for (int i = 0; i < notizen.Count; i++)
{
if (notizen[i].Contains(suchwort, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"{i + 1}. {notizen[i]}");
treffer++;
}
}
Console.WriteLine($"Treffer: {treffer}");
}
static void Loesche(List<string> notizen)
{
ZeigeAlle(notizen);
if (notizen.Count == 0)
{
return;
}
Console.Write("Welche Nummer löschen? ");
string eingabe = Console.ReadLine() ?? "";
if (!int.TryParse(eingabe, out int nummer) || nummer < 1 || nummer > notizen.Count)
{
Console.WriteLine($"Bitte eine Nummer von 1 bis {notizen.Count}.");
return;
}
string text = notizen[nummer - 1];
notizen.RemoveAt(nummer - 1);
Console.WriteLine($"Gelöscht: {text}");
}
Testen Sie das Löschen an den Grenzen: die Nummer 0, die höchste Nummer, eine Nummer darüber, ein Wort, und das Löschen in einer leeren Liste.
Was Sie jetzt können
- Sie planen ein Programm, bevor Sie es schreiben: was es kann, wie man es bedient, welche Teile es braucht.
- Sie bauen ein Menü aus einer Schleife, einer
bool-Variablen und einer Kette ausifundelse if. - Sie geben eine Liste an Methoden weiter, die alle an derselben Liste arbeiten.
- Sie fangen leere und falsche Eingaben ab, bevor die eigentliche Arbeit beginnt.
- Sie erweitern ein Programm in Schritten und testen nach jedem Schritt, auch die unbequemen Fälle.
Weiterlesen
- Guided project - Develop conditional branching and looping structures in C#: ein angeleitetes Projekt von Microsoft Learn, ebenfalls mit Menü und Schleifen.