heute widmen wir uns einem ebenfalls sehr wichtigem Thema (wie alle Grundlagen): der if-Anweisung.
Auch hier wieder ein Anfangszenario: Wir wollen einen Getränkeautomaten programmieren, der, je nach Benutzereingabe, zwei verschiedene Getränke geben kann (natürlich bauen wir keinen echten Getränkeautomaten). Der Benutzer erhält anfangs eine Konsolenausgabe, die ihm zwei Optionen gibt: Ein W für Wasser und ein T für Tee. Der Benutzer kann eines dieser Getränke mit Hilfe der Tastatur auswählen können. Falls er keines der beiden ausgewählt hat soll eine Ausgabe erfolgen, in der darauf hingewiesen wird. Andernfalls soll er den Preis erfahren, mit A Abbrechen können und mit Z Zahlen können. Falls er zahlt, bekommt er sein Getränk.
Um dieses Projekt zu realisieren ist es sinnvoll, erste einen sog. Algorithmus zu schreiben. Ein Algorithmus ist die Vorstufe zum Programmcode und soll helfen, das, was man vom Computer will, in diesen umzusetzen. Häufig werden Algorithmen bei komplizierten Programmen eingesetzt, es ist aber durchaus sinnvoll schon früher zu erlernen, wie man einen solchen schreibt. Es folgt der Algorithmus, der sich selbst erklärt:
Der Benutzer wird per Konsolenausgabe vor die Wahl zwischen Tee und Wasser gestellt. Durch Tastendruck wählt er das Getränk aus (W = Wasser, T = Tee)
Wenn der Benutzer W drückt, dann
Sag ihm den Preis und gib ihm die Möglichkeit mit Z zu zahlen, mit A abzubrechen
Wenn der Benutzer Z drückt, dann
starte Zahlvorgang und gib Getränk aus
Andernfalls
breche ab
Wenn der Benutzer T drückt, dann
Sag ihm den Preis und gib ihm die Möglichkeit mit Z zu zahlen, mit A abzubrechen
Wenn der Benutzer Z drückt, dann
starte Zahlvorgang und gib Getränk aus
Andernfalls
breche ab
Wenn der Benutzer keiner der Tasten drückt, dann
Gib Fehlermeldung aus
Konsole offen halten, um dem Benutzer Zeit zu geben, zu lesenDazu brauchen wir die nützliche if-Anweisung, bei der der boolesche Datentyp "bool" eine große Rolle spielt, der im letzten Post näher beschrieben wird.
Doch schreiben wir erste einmal den Anfang des Programms, den wir auch schon schreiben können:
//Benutzerinformation
Console.WriteLine("Herzlich Willkommen bei Ihrem Getränkautomaten!\nSie haben die Wahl zwischen Tee und Wasser.\nUm Tee zu erhalten, drücken Sie bitte \"T\" auf der Tastatur,\num Wasser zu erhalten, drücken Sie bitte \"W\".\nWir warten . . .");
// . noch
// . nicht
// . geschrieben
//Und am Ende, damit die Konsole sich nicht sofort schließt
Console.ReadKey();
Doch nun zu if:
Um eine if-Abfrage zu realisieren, schreiben wir erst einmal das C#-Schlüsselwort if, was dunkelblau dargestellt wird. Danach folgt eine sich öffnende Klammer, der boolesche Ausdruck, dann eine Klammer zu.
In die Zeile darunter wird eine geschweifte Klammer auf ({) und in der nächsten Zeile darunter ein geschweifte Klammer zu (}) geschrieben. Zwischen diese Klammern kommen die C#-Anweisungen, die ausgeführt werden sollen, wenn der boolesche Ausdruck true ergibt. Das Gerüst:
if(boolescher Ausdruck)
{
Anweisungen, die ausgeführt werden wenn der boolesche Ausdruck true ergibt
}
In die Klammern muss jetzt ein boolescher Ausdruck. Wir vergleichen hier die Benutzereingabe, die zuvor mit Console.ReadLine() und in einem string gespeichert wird, mit dem String "W" für Wasser. Damit der Benutzer auch ein kleines w eingeben kann, wenden wir auf Console.ReadLine() die String-Methode ToUpper() an, die alles zu Großbuchstaben macht:
string benutzereingabe = Console.ReadLine().ToUpper();
if (benutzereingabe == "W")
{
}
Den Inhalt der Klammern schreiben wir nachher, wir machen jetzt erste einmal mit dem nächsten Fall weiter.
Wenn der Benutzer nicht W gedrückt hat, soll überprüft werden, ob er vielleicht T gedrückt hat. Um dem Computer zu zeigen, dass zwei Überprüfungen aneinanderhängen, gibt es die else-if-Anweisung. Sie funktioniert wie if, aber dem if ist noch ein else angehängt, wodurch der Computer die beiden if-Abfragen als zusammenhängend betrachtet.
else if (benutzereingabe == "T")
{
}
Nun ist auch der Fall behandelt, wenn der Benutzer T drückt. Doch wie bekommen wir es hin, dass in allen anderen Fällen eine Fehlermeldung ausgegeben wird? Müssen wir dafür alle Möglichkeiten überprüfen, die der Benutzer bei der Eingabe hat? Zum Glück gibt es in C# die else-Anweisung. Falls nach mind. einer if-Anweisung nicht die bisher überprüften Fälle eingetreten sind, tritt else ein. Jetzt macht auch else-if mehr Sinn. Natürlich ist es keine Pflicht, nach jedem if-Block else zu schreiben, aber bei uns bietet sich das an. Beim else-Block gibt es keine booleschen Ausdrücke in Klammern mehr:
else
{
}
Im else-Teil können wir gleich die Fehlermeldung ausgeben, also:
else
{
Console.WriteLine("Ihre Eingabe (" + benutzereingabe + ") konnte leider keinem Getränk zugeordnet werden!\nBitte starten Sie das Programm erneut.");
}
Unser Code bisher:
namespace Getränkeautomat
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Herzlich Willkommen bei Ihrem Getränkautomaten!\nSie haben die Wahl zwischen Tee und Wasser.\nUm Tee zu erhalten, drücken Sie bitte \"T\" auf der Tastatur,\num Wasser zu erhalten, drücken Sie bitte \"W\".\nWir warten . . .");
//Die Benutzereingabe wird in Großbuchstaben umgewandelt und in der string-Variablen "benutzereingabe" gespeichert
string benutzereingabe = Console.ReadLine().ToUpper();
//falls der Benutzer ein "W" eingegeben hat...
if (benutzereingabe == "W")
{
//...mach das hier
}
//falls der Benutzer kein "W" eingegeben hat wird hierher gesprungen, wo überprüft wird,
//ob der Benutzer ein T eingegeben hat. Falls das true ergibt...
else if (benutzereingabe == "T")
{
//...wird das hier abgearbeitet
}
//falls die beiden oberen Fälle false ergeben, wird hierher gesprungen. Da wir im else-Teil
//für alle anderen Fälle sorgen, ist hier keine Klammer mit booleschem Ausdruck notwendig.
//Hier wird auch der Sinn von else-if klar, denn wenn man zweimal nur if schreiben würde, würde hier
//auch bei Eingabe von "W" ein Fehlermeldung ausgegeben werden.
else
{
Console.WriteLine("Ihre Eingabe (" + benutzereingabe + ") konnte leider keinem Getränk zugeordnet werden!\nBitte starten Sie das Programm erneut.");
}
Console.ReadKey();
}
}
}
Auch hier gibt es wieder Layoutfehler.
Jetzt müssen wir uns noch um die Auswahlmöglichkeiten innerhalb des if- und des else-if-Blocks kümmern:
Jeweils soll der Benutzer eine Meldung bekommen, die den Erfolg der Getränkeauswahl ausgibt. Dann soll er die Möglichkeit zwischen Zahlen und Abbrechen bekommen. Sollte der Benutzer einen anderen Buchstaben als A für Abbrechen oder Z für Zahlen eingeben, wird ebenfalls abgebrochen.
In C# ist es möglich, if-Anweisungen zu verschachteln. Hier ist der gesamte Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Getränkeautomat
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Herzlich Willkommen bei Ihrem Getränkautomaten!\nSie haben die Wahl zwischen Tee und Wasser.\nUm Tee zu erhalten, drücken Sie bitte \"T\" auf der Tastatur,\num Wasser zu erhalten, drücken Sie bitte \"W\".\nWir warten . . .");
//Die Benutzereingabe wird in Großbuchstaben umgewandelt und in der string-Variablen "benutzereingabe" gespeichert
string benutzereingabe = Console.ReadLine().ToUpper();
//falls der Benutzer ein "W" eingegeben hat...
if (benutzereingabe == "W")
{
//...mach das hier
Console.WriteLine("Wenn Sie zahlen wollen, geben Sie bitte ein Z ein:");
string benutzereingabe2 = Console.ReadLine().ToUpper();
if (benutzereingabe2 == "Z")
{
Console.WriteLine("Der Zahlvorgang wurde gestartet...");
Thread.Sleep(1000);
Console.WriteLine("Sie haben erfolgreich gezahlt!");
}
else
{
Console.WriteLine("Abbrechen...");
}
}
//falls der Benutzer kein "W" eingegeben hat wird hierher gesprungen, wo überprüft wird,
//ob der Benutzer ein T eingegeben hat. Falls das true ergibt...
else if (benutzereingabe == "T")
{
//...wird das hier abgearbeitet
Console.WriteLine("Wenn Sie zahlen wollen, geben Sie bitte ein Z ein:");
string benutzereingabe2 = Console.ReadLine().ToUpper();
if (benutzereingabe2 == "Z")
{
Console.WriteLine("Der Zahlvorgang wurde gestartet...");
Thread.Sleep(1000);
Console.WriteLine("Sie haben erfolgreich gezahlt!");
}
else
{
Console.WriteLine("Abbrechen...");
}
}
//falls die beiden oberen Fälle false ergeben, wird hierher gesprungen. Da wir im else-Teil
//für alle anderen Fälle sorgen, ist hier keine Klammer mit booleschem Ausdruck notwendig.
//Hier wird auch der Sinn von else-if klar, denn wenn man zweimal nur if schreiben würde, würde hier
//auch bei Eingabe von "W" ein Fehlermeldung ausgegeben werden.
else
{
Console.WriteLine("Ihre Eingabe (" + benutzereingabe + ") konnte leider keinem Getränk zugeordnet werden!\nBitte starten Sie das Programm erneut.");
}
Console.ReadKey();
}
}
}Auch hier ist eine neue Anweisung dabei: Thread.Sleep(1000); Diese Anweisung hält das Programm (Thread) für 1000 Millisekunden an. Damit diese Anweisung überhaupt verfügbar ist, muss in den using-Statements "using System.Threading;" hinzugefügt werden, wodurch der Compiler alle "Vokabeln" lernt, die im Namespace "System.Threading" verfügbar sind. Wenn man das weglassen würde, müsste man jedes Mal "System.Threading.Thread.Sleep(1000);" geschrieben werden. Wir werden später, bei der Objektorientierung, noch einmal auf Namespaces eingehen.
Nun sind wir auch in der Lage, unseren Taschenrechner fertig zu programmieren. Der gesamte Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Taschenrechner
{
class Program
{
static void Main(string[] args)
{
double ergebnis;
Console.WriteLine("Geben Sie die erste Zahl ein:");
double zahl1 = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Bitte geben Sie nun die zweite Zahl ein:");
double zahl2 = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Bitte geben Sie nun die Operation ein:");
string operation = Console.ReadLine();
if (operation == "+")
{
ergebnis = zahl1 + zahl2;
Console.WriteLine("Ergebnis: " + ergebnis.ToString());
}
else if (operation == "-")
{
ergebnis = zahl1 - zahl2;
Console.WriteLine("Ergebnis: " + ergebnis.ToString());
}
else if (operation == "/" || operation == ":")
{
ergebnis = zahl1 / zahl2;
Console.WriteLine("Ergebnis: " + ergebnis.ToString());
}
else if (operation == "*" || operation == "x" || operation == "X")
{
ergebnis = zahl1 * zahl2;
Console.WriteLine("Ergebnis: " + ergebnis.ToString());
}
else
{
Console.WriteLine("Ungültige Eingabe!");
}
Console.ReadKey();
}
}
}
Auch hier ist wieder etwas unbekanntes dabei: In bestimmten if-Anweisungen steht ein doppeltes | (AltGr + <). Das bedeutet in C# ein "Oder", d.h., wenn eine der beiden booleschen Ausdrücke "true" ergibt, werden die Anweisungen ausgeführt. Das ist hier sinnvoll, da es auch Benutzer gibt, die statt "/" ":" eingeben. Auch ein "Und" kann man programmieren: "&&". Hierbei müssen alle Bestimmungen zutreffen, damit die folgenden Anweisungen ausgeführt werden. Natürlich kann man auch mehrere "Und"s oder "Oder"s hintereinander hängen.
Um hier auch korrekte Ergebnisse bei der Division zu gewährleisten werden doubles verwendet, da sonst z.B. bei der Operation 1/3 bei Verwendung eines int 0 statt 0,333333333... ausgegeben wird, da gerundet wird. Dementsprechend muss auch die Anweisung "Convert.ToInt32" in "Convert.ToDouble" geändert werden. Allerdings gilt für den Benutzer die Einschränkung für Programmierer nicht, sodass dieser ein deutsches Komma auch wirklich als Trennzeichen zwischen Ganzzahl und Nachkommastellen verwenden kann. Das ist aber von der Spracheinstellung des Systems abhängig.
Der Rest des Programmcodes erklärt sich selbst.
Bis zum nächsten mal,
Julian