Programmieren in C#
Ziel dieses Tutorials ist, die Grundlagen der Programmierung anhand der Programmiersprache C# (sprich: „C-sharp“) zu lernen. Programmieren läuft immer wie folgt ab:
- Man schreibt seinen Code …
- und führt diesen dann aus.
Am einfachsten geht dies mithilfe einer IDE (Integrated Development Environment). Dies ist ein Programm, in welchem man seinen Code schreiben kann und welches einem auf allfällige Fehler (Bugs) aufmerksam macht. Per Knopf- oder Tastendruck kann der Code dann ausgeführt werden.
1. Einführung
1.1 Installation & Hello World
Um C# zu programmieren, verwenden wir die IDE Visual Studio (kurz: VS) von Microsoft. Achtung: Nicht zu verwechseln mit dem Visual Studio Code!
- Lade die Community Edition (gratis) des Visual Studios von der Website https://visualstudio.microsoft.com/de/ herunter …
- … und installiere sie.
- Starte dann das VS und beginne ein neues C# Konsolenprojekt und gib ihm einen Namen.
- Diese Projekt enthält bereits Code, der wie unten angezeigt aussehen sollte.
- Dieses Programm ist das bekannteste Programm der Welt: Hello World. Alles was dieses Programm macht, ist die Nachricht
Hello World!
im Ausgabefenster, genannt Konsole oder Terminal, auszugeben. Drücke, um das Programm auszuführen auf den (grünen) Pfeil oder F5.
using System; namespace MyProject { class MainClass { public static void Main(string[] args) { Console.WriteLine("Hello World!"); } } }
Doch was macht dieses Programm genau? Was die Zeilen wie using System;
oder class MainClass
bedeuten, besprechen wir später. Für den Moment ist nur folgendes wichtig: Sobald das Programm ausgeführt wird, wird der Code, der in der Main-Methode drin steht, ausgeführt - und zwar von oben nach unten. Dies ist der Code, der in den innersten geschwungenen Klammern steht. In diesem Beispiel ist dies nur genau eine Zeile: Console.WriteLine("Hello World!");
Dies gibt den Befehl, den String (bedeutet Text in der Informatik) Hello World!
in die Konsole zu schreiben.
1.2 Tipps
- Um eine gute Programmierer*in zu werden benötigt es Übung, Übung und nochmals Übung!
- Im Internet findest du sehr viele Informationen zum Thema C#. Nutze dies! Zum Beispiel: schriftliche Tutorials, YouTube-Tutorials, Diskussionen in Foren, …
- Verändere das vorgegebene Gerüst des Programms nicht. Lasse also z.B. Zeilen wie
class MainClass
unverändert. - Projektnamen: Benenne ein bestehendes Projekt nicht um, da dies zu Fehlern führen wird. Umgehe das Problem wie folgt: Erstelle ein neues Projekt mit dem richtigen Namen und copy-paste den von dir geschriebenen Code (und nicht das Gerüst darum herum) ins neue Projekt.
- Lese Fehlermeldungen. Schreibst du Code, der nicht den vorgegebenen Regeln von C# entspricht, weigert sich VS, das Programm auszuführen. Du erhältst dann eine Fehlermeldung. Diese Meldungen sind oft sehr hilfreich und helfen dir, das Problem zu identifizieren und zu beheben.
- Erhöhe deinen nerdigen Coolness-Faktor, in dem du …
- … deinen Code komplett auf Englisch schreibst
- … möglichst wenig die Maus brauchst und alles mit der Tastatur mit Shortcuts erledigst!
- In allen Programmiersprachen gibt es Stil-Konventionen, an die man sich halten sollte. In C# sollten Projektnamen, Variablennamen usw. folgende Regeln befolgen:
- Verwende CamelCase. Nenne dein erstes Projekt zum Beipiel
HelloWorld
und nichthello_world
. - Vermeide Leerschläge, also nicht:
Hello World
(in Strings sind Leerzeichen natürlich völlig ok) - Vermeide Umlaute, also nicht:
HelloWörld
- Weitere Tipps und Shortcuts werden in den unteren Kapiteln in grün angezeigt.
- Viele Personen machen ihre ersten Programmiererfahrungen in Python. Deshalb werden immer wieder Vergleiche zwischen Python und C# gezogen. Alle solche sind in der gleichen Farbe dargestellt.
1.3 Ausgabe in Konsole
Wie bereits oben gesehen, kann man mit Console.WriteLine();
etwas in der Konsole ausgeben:
Console.WriteLine(7); // Zahl ausgeben Console.WriteLine("Hello World!"); // String ausgeben Console.WriteLine("Die Zahl " + 7 + " ist eine Primzahl");
- In Zeile 1 wird die Zahl
7
ausgegeben. - In Zeile 2 wird der Text
Hello World
ausgegeben. Beachte, dass man hier zwingend Anführungs- und Schlusszeichen anbringen muss. Eine Textzeile wird in der Informatik als String bezeichnet. - In Zeile 3 werden Strings und eine Zahl mit dem
+
-Symbol miteinander verknüpft. - Beachte, dass jede Linie mit einem Semikolon
;
beendet werden muss. - Mit zwei Slashes
\\
kann man dem Code einen Kommentar hinzufügen. Ein solcher ist kein Programmcode und wird beim Ausführen ignoriert. Damit kann man seinem Code Anmerkungen anfügen, damit dieser besser verständlich wird. - Shortcut: Tippe nur
cw
+ Tab und schon stehtConsole.WriteLine();
da! Hurray! - Das
Console.WriteLine();
entspricht demprint()
in Python. Kommentare in C# schreibt man mit\\
, in Python mit#
.
2. Variablen
Variablen geben einem die Möglichkeit, Information wie zum Beispiel Zahlen temporär zu speichern. Eine Variable hat immer einen Datentyp, von denen es eine grosse Anzahl gibt in C#. Möchte man Text ausgeben, so arbeitet man mit Strings. Möchte man eine Rechnung mit ganzen Zahlen (Zahlen ohne Nachkommastellen) ausführen, arbeitet man mit ints (von integer). Möchte man aber Nachkommastellen anzeigen können, verwendet man doubles.
Beachte, dass C# eine typensichere Sprache ist. Möchtest du eine Variable mit Namen a
haben, die eine ganze Zahl speichern soll, so musst du die Variable mit ihrem Typ explizit deklarieren:
int a; // Deklaration der Variablen a vom Type int a = 7; // Variable a wird den Wert 7 zuweisen Console.WriteLine(a);
- In Zeile 1 wird die Variable deklariert. Diese soll vom Typ
int
, also ein Integer (ganze Zahl, also keine Kommazahl), sein. Dabei soll sie den Namena
tragen. - In Zeile 2 weisen wir der Variablen
a
den Wert7
zu. - In Zeile 3 greifen wir auf diese Variable zurück und geben deren Wert in der Konsole aus. Es wird die Zahl
7
in der Konsole angezeigt.
Übrigens kann man die ersten beiden Zeilen auch in eine zusammenfassen:
int a = 7; // Kombination von Deklaration und Wertzuweisung einer Variablen
Zusammengefasst hat eine Variable:
- einen Namen (z.B.
a
) - einen Typ (z.B.
int
) - einen Wert (z.B.
7
)
C# ist eine typensichere Sprache. Dies bedeutet, dass wir einer Variablen ausschliesslich Werte zuordnen können, die ihrem Typ entspricht. Betrachten wir folgenden Code:
int a = 7; a = 9; // erlaubt a = 3.14; // nicht erlaubt, gibt einen Fehler
In Zeile 2 wird der Wert der Variablen geändert. Dies ist kein Problem, da 9
ein Integer ist. Zeile 3 ist aber problematisch, da man versucht, a
eine Gleitkommazahl zuzuordnen. Dieser Code ist nicht ausführbar - versucht man es trotzdem, wird man eine Fehlermeldung erhalten.
Möchtest du eine Gleitkommazahl oder einen String in einer Variablen speichern, musst du dazu passende Datentypen wählen:
double b = 3.14; // Gleitkommazahlen heissen Doubles in C# string c = "Ich bin ein String!"; // Variable vom Typ String
Neben den hier erwähnten Datentypen int, double und string gibt es noch weitere. Einige davon wirst du im Verlaufe dieses Dossiers kennenlernen.
Python ist eine nicht typensichere Programmiersprache. Dort kann eine Variable beliebig ihren Typ ändern. Folgender Code würde in Python ohne Probleme funktionieren:
# Dies ist Python-Code, NICHT C#! a = 42 # hier ist a ein int a = 1.23 # hier wird a zu einem float umdeklariert a = "And now I am a string!" # ... und hier zu einem String
Solche Umdeklarationen sind in C# NICHT möglich! Ist a
einmal ein int, so bleibt es ein solcher.
In C# kann man auch rechnen. Hier ein Beispiel mit den gängigsten Rechenoberationen:
int a = 7; int b = 15; Console.WriteLine(a + b); // Addition Console.WriteLine(a - b); // Subtraktion Console.WriteLine(a * b); // Multiplikation Console.WriteLine(a / b); // Division int result = a + b; // Addition, Resultat in neue Variable schreiben Console.WriteLine(result);
Übersicht mathematische Operatoren:
Operator | Beschreibung |
---|---|
+ | Additionsoperator (Summe x + y ) oder Vorzeichenoperator (+x ) |
- | Subtraktionsoperator (Differenz x - y ) oder Vorzeichenoperator (-x ) |
* | Multiplikationsoperator multipliziert zwei Operanden (x * y ). |
/ | Divisionsoperator (x/y ), Ganzzahldivision bei ints, mit Nachkommateil bei doubles |
% | Restwertoperator (x % y ), gibt Rest der Ganzzahldivision |
++ | Inkrementoperation (x++ oder ++x ), erhöht Wert von x um 1 |
-- | Dekrementoperation (x-- oder --x ), verringert Wert von x um 1 |
2.1 Aufgaben A
Aufgabe A1
Welche der folgenden Namen sind zulässig für Variablen in C#? Begründe warum (nicht):
iamavariable
42
g
IchPinEyneWariaple
secret number
_hans
!number
int
iAmAVariable
Aufgabe A2
Spiele mit den oben gelernten Datentypen. Deklariere Variablen, weise ihnen Werte zu, mache Rechnungen, gib Resultate in der Konsole aus … Tobe dich aus und habe Spass!
Aufgabe A3
Speichere die Zahl 1000000000
als int in einer Variablen.
- Berechne nun das Doppelte, das Dreifache, Vierfache, … dieser Variablen und gebe jeweils das Resultat aus. Was fällt dir auf? Begründe.
- Nenne ein konkretes Beispiel für eine Aufgabe, bei der dies zu Problemen führen kann.
- Was lernst du daraus für deine Programmierprojekte? Wie kann man das Problem umgehen?
Aufgabe A4
Welchen Wert hat der grösste und welchen Wert der kleinste int, den man in C# darstellen kann? Woher kommt dies? Begründe ganz genau.
Aufgabe A5
Mit Console.WriteLine()
kann man etwas in der Konsole ausgeben. Ähnlich kann man mit Console.ReadLine()
in der Konsole etwas eingeben und diesen Inhalt dann in einer Variablen speichern. Die Benutzer*In soll der Reihe nach aufgefordert werden, zuerst denn Vornamen, dann den Nachnamen und dann das Alter einzugeben. Alle Werte sollen dann in einer Variablen gespeichert werden. Danach soll ein Sätzli ausgegeben werden, welches alle eingegebenen Werte beinhaltet, zum Beispiel: Hello Fritz Fischer. You are 42 years old!
Achtung: Beim eingeben des Alters wird ein Problem auftreten. Versuche mithilfe des Internets, selbst eine Lösung dafür zu finden!
Aufgabe A6
Berechne oder bestimme mithilfe der Rechenoperatoren. Verwende ausschliesslich ints. Schreibe also 45
und nicht 45.0
:
- Berechne die Ganzzahldivision $10023 / 45 = ?$, bestimme also Ganzzahlquotient und Rest.
- Ist 1346 durch 17 teilbar?
3. Logik
Beim Programmieren kommt man oft in die Situation, wo man Entscheidungen treffen muss. Zum Beispiel soll, je nach dem was der Benutzer eintippt, ein anderer Code ausgeführt werden.
3.1 If-else if-else-Anweisung
Am einfachsten ist die sogenannte if-Anweisung: Damit kann man überprüfen ob (also if) eine gewisse Bedingung (condition) erfüllt ist oder nicht. Dieser Befehl hat die Form
if (CONDITION) { // Codeblock in geschwungenen Klammern wird nur ausgeführt, wenn die BEDINGUNG erfüllt ist. }
Damit können wir herausfinden, ob der Wert einer Variablen positiv ist:
int x = 5; if (x >= 0) // checks if x greater equal zero { // code block gets executed ONLY if condition above is satisfied Console.WriteLine("x is greater equal zero!"); }
Falls der Wert von x
auf eine negative Zahl gesetzt wird, wird in der Konsole nichts ausgegeben. Schön wäre aber, dass uns mitgeteilt würde, dass die Zahl negativ ist. Dies erreicht man mit einer if-else-Anweisung:
int x = -5; if (x >= 0) // checks if x greater equal zero { // code block gets executed ONLY if condition above is satisfied Console.WriteLine("x is greater equal zero!"); } else { // code block gets executed ONLY if condition above is NOT satisfied Console.WriteLine("x is negative!"); }
Der Codeblock im else wird nur dann ausgeführt, wenn die Bedingung beim if nicht erfüllt wird.
Falls wir den Fall $x = 0$ separat behandeln möchten, verwenden wir eine if-else if-else-Anweisung:
int x = 0; if (x > 0) // checks if x greater zero { Console.WriteLine("x is positive!"); } else if (x == 0) // checks if x equal zero but only if first condition is not satisfied { Console.WriteLine("x is zero!"); } else { // gets executed if none of the above conditions are satisfied Console.WriteLine("x is negative!"); }
Beachte, dass man beliebig viele else if haben kann. Die allgemeine Form ist also:
if (CONDITION 1) { // code block if CONDITION 1 satisfied } else if (CONDITION 2) { // code block if CONDITION 2 satisfied } else if (CONDITION 3) { // code block if CONDITION 3 satisfied } ... else { // code block if NONE of the above conditions are satisfied }
3.2 Vergleichsoperatoren
Für die Bedingungen stehen folgende Vergleichsoperatoren zur Verfügung:
Operator | Beschreibung |
---|---|
a == b | (Vergleichsoperator) prüft, ob der Ausdruck a dem Ausdruck b entspricht, und gibt in diesem Fall true zurück. |
a != b | Ergebnis der Operation ist true , wenn a ungleich b ist. |
a > b | Ergebnis der Operation ist true , wenn a grösser b ist. |
a >= b | Ergebnis der Operation ist true , wenn a grösser oder gleich b ist. |
a < b | Ergebnis der Operation ist true , wenn a kleiner b ist. |
a <= b | Ergebnis der Operation ist true , wenn a kleiner oder gleich b ist. |
Bemerkungen:
- Eine Bedingung ist vom Datentyp Boolean, für den es genau zwei Möglichkeiten gibt: Er kann entweder erfüllt sein (
true
) oder nicht (false
). Vergewissere dich selbst, dass zum BeispielConsole.WriteLine(3 == 5);
den Wertfalse
undConsole.WriteLine(3 < 5);
den Werttrue
ausgibt. Den Wert, der eine Bedingung annimmt, kann man auch wieder in einer Variablen speichern, z.B.Boolean boo = (3 == 5);
- Beachte auch, dass Verschachtelungen gar kein Problem sein. Zum Beispiel kannst du im Codeblock von einem else ein neues if-else if-else haben.
- Beachte den Unterschied zwischen dem einfachen (
=
) und doppelten (==
) Gleichheitszeichen:- Das einfache Gleichheitszeichen ist ein Zuweisungsoperator:
x = 7
bedeutet, dass der Variablen auf der linken Seite der Wert auf der rechten Seite zugewiesen wird. - Das doppelte Gleichheitszeichen ist ein Vergleichsoperator: er überprüft, ob links und rechts das gleiche steht. Falls ja, nimmt die Bedingung den Wert
true
. Falls nicht, nimmt es den Wertfalse
an. Das doppelte Gleichheitszeichen in der Informatik entspricht also in etwa dem normalen Gleichheitszeichen in der Mathe, zum Beispiel beim Lösen von Gleichungen.
In Python sieht das entsprechende if-else if-else-Statement wie folgt aus:
# Python Code! if CONDITION 1: # code block if CONDITION 1 satisfied elif CONDITION 2: # code block if CONDITION 2 satisfied elif CONDITION 3: # code block if CONDITION 3 satisfied ... else: #code block if NONE of the above conditions are satisfied
Beachte, dass in Python Codeblocks durch Einrückungen (Tab) festgelegt werden. In C# ist die Einrückung komplett egal, stattdessen werden geschwungene Klammern verwendet.
Shortcut: Alles wieder schön einzurücken (rein visuell, hat keinen Einfluss auf Code): Ctrl + K, Ctrl + D
3.3 Logische Operatoren
Es können auch mehrere Vergleichsoperatoren miteinander verknüpft werden. Verknüpft man mehrere solche mit dem AND-Operator&&
so ist die Bedingung genau dann true, wenn sämtliche Vergleichsoperatoren true sind.
Verwendet man den OR-Operator ||
, so ist die Bedingung true, wenn mindestens ein Vergleichsoperator true ist.
Die entsprechenden logischen Operatoren in Python sind and
und or
.
Aufgaben B
Aufgaben B1
Schreibe ein Programm, welches die Benutzer*In auffordert eine ganze Zahl einzugeben. Die Zahl soll auf vier Fälle untersucht werden und eine entsprechende Nachricht soll ausgegeben werden. Die vier Fälle sind:
- 42: The answer to the ultimate question of life, the universe and everything!
- positive Zahlen (ausser 42)
- Null
- negative Zahlen
Falls du den 42-Joke nicht verstehst, bist du noch nicht nerdy genug und musst dringend The Hitchhiker's Guide to the Galaxy lesen oder schauen!
Aufgaben B2
- Schreibe für einen Online-Alkoholhändler ein einfaches Programm, bei dem die Kund*In ihren Namen und ihr Alter eingeben muss und dann eine personalisierte Antwort darüber erhält, ob sie alt genug ist für einen Einkauf, je nachdem, welches Alter sie eingetippt hat, zum Beispiel: „Liebe(r) Ruthild, leider bist du nicht alt genug für einen Einkauf bei uns.“ !
- Erweitere dein Programm: Die Kund*In wird auch nach dem Geschlecht gefragt. Je nach Eingabe soll dann die Anrede angepasst werden: „Liebe Ruthild, leider bist du nicht alt genug für einen Einkauf bei uns.“ oder „Lieber Hans-Joseph, viel Spass beim Einkaufen!“
4. Debugging
Der Debugger erlaubt es einem, den Code eine Zeile nach der anderen auszuführen. Damit kann man einfach nachvollziehen, was der Code wo macht und welche Variable wann und wo welchen Wert annimmt. Dies ist besonders wertvoll, um Fehler (also Bugs) im Code zu finden - deshalb nennt man diesen Modus den Debugger!
Zuerst musst du einen oder mehrere Breakpoints setzen: Klicke dazu beim Code links von der Zeilennummer auf den Rand, dann erscheint ein roter Punkt, genannt Breakpoint. Führst du den Code nun im Debug-Modus aus, so pausiert die Ausführung des Codes beim ersten Breakpoint. Nun kannst du mit F10 den weiteren Code Zeile-für-Zeile ausführen. Mit F5 lässt du den Code wieder weiterlaufen bis er zu einem weiteren Breakpoint oder dem Ende gelangt.
Im Fenster Lokale Variablen siehst du, welche Variablen im Code vorkommen und welche Werte sie zum aktuellen Zeitpunkt gerade haben.
Shortcuts:
- F5: Code bis zum Ende/nächsten Breakpoint ausführen
- F10: Code Zeile-für-Zeile ausführen
4.1 Aufgaben C
Aufgabe C1
Öffne eines deiner bisherigen Projekt mit möglichst viel Code.
- Setze eine Breakpoint und führe den Code aus. Gehe dann mit F10 Schritt-für-Schritt durch den Code.
- Setze mehrere Breakpoints und finde heraus, wie du mit F10 und F5 den Code ausführen kannst.
5. Schleifen
Schleifen (loops) kommen dann zum Zug, wenn wir einen gewissen Codeblock mehrfach hintereinander ausführen wollen. Dabei gibt es zwei unterschiedliche Arten von Schleifen:
- While-Schleife: wird solange ausgeführt, wie eine gegebene Bedingung erfüllt ist.
- For-Schleife: wird eine fest vorgegebene Anzahl-Mal ausgeführt, praktisch, wenn man z.B. etwas hochzählen möchte
5.1 While-Schleifen
Eine while-Schleife hat immer folgende Form:
while (CONDITION) { // code block that gets executed as long as CONDITION is satisfied }
Der Codeblock in den geschwungenen Klammern wird solange wiederholt, wie die Bedingung (condition) erfüllt ist, solange also die Bedingung true
ist.
Ein Fehler, der einem beim Programmieren gerne passiert, sind Endlosschleifen (infinite loop). Dies sind while-Schleifen, deren Bedingung immer erfüllt ist, die Schleife wird also solange ausgeführt, bis die Benutzer*In den Code manuell abbricht. Ein Beispiel für eine Endlosschleife ist folgender Code:
while (true) { Console.WriteLine(42); }
Für die Bedingung einer while-Schleife kann man die Gleicheng Bedingungen wie bei if-Anweisungen (siehe Vergleichsoperatoren) verwenden.
Eine while-Schleife in Python sieht wie folgt aus:
# PYTHON CODE while true: # Code block in while-loop
Beachte, dass in Python der Codeblock, der zur Schleife gehört, per Tab eingerückt wird. In C# wird der entsprechende Codeblock innerhalb der geschwungenen Klammern geschrieben.
Shortcut: Tippe while + 2xTab, um das Grundgerüst einer for-Schleife zu erzeugen. Passe es dann entsprechend an.
While-Schleifen sind sehr praktisch, wenn man im Vorfeld nicht genau weiss, wie oft der Codeblock in der Schleife wiederholt werden soll. Zum Beispiel könnte man ein Quizspiel programmieren, in dem die Benutzer*In solange weiterspielen darf, bis sie einen Fehler macht. Dies kann bereits bei der ersten Frage sein, es kann aber auch erst bei Frage 42 sein - man weiss es nicht im Vorfeld. Weiss man hingegen bereits im Vorfeld, wie oft der Inhalt wiederholt werden soll, sind for-Schleifen sehr praktisch …
5.2 For-Schleifen
Eine for-Schleife führt einen Codeblock eine fest vorgegebene Anzahl Mal durch und hat folgenden Aufbau:
for (VARIABLE WITH STARTING VALUE; VARIABLE WITH CONDITION; VARIABLE IN/DECREMENT) { // Code block }
Sie kommt also dann zur Anwendung, wenn man schon im Vorhinein genau weiss, wie oft die Schleife ausgeführt werden soll.
Folgender Code zum Beispiel gibt $7\times$ hintereinander die Zahl $42$ aus.
for (int i = 0; i < 7; i++) { Console.WriteLine("42"); }
Für die for-Schleife wird hier die Variable i
(vom Typ int) mit Anfangswert $0$ festgelegt. Beim ersten Durchlauf der Schleife hat i
also den Wert $0$. Beim zweiten Durchlauf hat i
dann den Wert $1$, da wir mit i++
vorgeben, dass i
bei jedem durchlauf um $1$ erhöht wird. Dies geschieht solange, wie die Bedingung (hier: i < 7
) erfüllt ist. Die Variable i
kann man natürlich auch im Codeblock verwenden. Folgender Code gibt zum Beispiel alle Zahlen von $0$ bis und mit $6$ in der Konsole aus:
for (int i = 0; i < 7; i++) { Console.WriteLine(i); }
Der entsprechende Code in Python sieht wie folgt aus:
# PYTHON CODE for i in range(7): print(i)
Shortcut: Tippe for + 2xTab, um das Grundgerüst einer for-Schleife zu erzeugen. Passe die genauen Details dann entsprechend an.
5.3 Break & continue
Mithilfe von break und continue kann man jederzeit aus einer Schleife ausbrechen:
- Die break Anweisung steht irgendwo im Codeblock der Schleife, meist in Verbindung mit einer if Abfrage. Läuft das Programm in sie hinein, bricht sie die Schleife ab und man springt zum Code nach der Schleife.
- Die continue Anweisung bricht den aktuellen Schleifendurchgang ab und springt wieder zum Beginn der Schleife.
5.4 Aufgaben D
Aufgabe D1
- Gib alle ganzen Zahlen von $10$ bis und mit $20$ aus …
- mithilfe einer for-Schleife
- mithilfe einer while-Schleife
- Gib alle geraden Zahlen von $2$ bis und mit $20$ aus …
- mithilfe einer for-Schleife
- mithilfe einer while-Schleife
- Gib alle ganzen Zahlen von $-1$ bis und mit $-10$ in absteigender Reihenfolge aus …
- mithilfe einer for-Schleife
- mithilfe einer while-Schleife
Aufgabe D2
Wandle in eine while-Schleife um:
for (int k = 7; k < 13; k++) { Console.WriteLine(2*k); }
Aufgabe D3
Betrachte folgenden Code:
int x = 5; while (x < 10) { Console.WriteLine(x); x++; }
- Was macht der Code? Versuche es herauszufinden, ohne den Code auszuführen.
- Schreibe nun den Code so um, dass die Schleife das unten angezeigt Grundgerüst hat. Verwende die break Anweisung, um aus der Schleife auszubrechen.
... while (true) { ... }
Aufgabe D4
- Die Benutzer*In wird aufgefordert, eine positive ganze Zahl einzugeben. Dieses Spiel soll solange wiederholt werden, bis sie eine negative Zahl eingibt. Das Spiel wird dann abgebrochen.
- Beim Programmieren muss man immer damit rechnen, dass die Benutzer*In nicht das macht, was sie sollte (manchmal aus Unwissenheit, manchmal aus purer Bosheit)! Hier zum Beispiel könnte die Benutzerin etwas eintippen, was nicht in eine Zahl umgewandelt werden kann. Aktuell würde dies wahrscheinlich dein Programm crashen. Dieses Problem kann man damit beheben, in dem man den Fehler abfängt (exception handling), und zwar mit einer try-catch-Anweisung. Finde mithile einer Internetsuche heraus, wie dies funktioniert und schreibe dir einen kurzen Eintrag dazu in deine Unterlagen. Nutze dann dein neu erlangtes Wissen, um dein Programm aus dem vorherigen Punkt so anzupassen, dass es robust gegen renitente Benutzer*Innen ist.
Aufgabe D5
Schreibe ein einfache Quiz-Game, um deine Kopfrechenfähigkeiten zu trainieren. Die Benutzer*In soll solange weiterspielen können, bis sie einen Fehler begeht, dann ist Game Over! Die Rechnungen sollen einfache Additionen von zwei ganzen Zahlen sein, wobei diese Zahlen per Zufall ausgewählt werden (siehe Codebeispiel unten). Der Benutzer*In soll also die Rechnung präsentiert werden und dann das eingetippte Resultat mit dem tatsächlichen Resultat verglichen werden.
Folgender Code gibt einem $10$ Zufallszahlen im Bereich $1$ bis $5$ aus und dient als Beispiel dafür, wie man Zufallszahlen generiert:
Random rand = new Random(); for (int i = 0; i < 10; i++) { Console.WriteLine(rand.Next(1, 6)); }
Aufgabe D6
Mache eine Kopie von deinem Mathe-Quiz und erweitere es Schritt-für-Schritt:
- Am Schluss soll der Spielstand ausgegeben werden.
- Man soll solange spielen können, bis man drei Fehler gemacht hat.
- Neben Aufgaben zur Addition sollen auch Aufgaben zur Subtraktion und Multiplikation, wenn du möchtest auch zur Ganzzahldivision vorkommen. Welche Operation in einer Aufgabe vorkommt, soll per Zufall bestimmt werden.
- Gestalte das Spiel schön. Gib jeweils den Spielstand aus, bereinige die Konsole nach jedem Durchgang (
Console.Clear();
), …
6. Algorithmen
Ein Algorithmus ist eine eindeutige Handlungsanweisung für die Lösung von Problemen. Algorithmen bestehen aus endlich vielen, wohldefinierten Einzelschritten. Ein Algorithmus ist also ein Lösungsweg, eine Verarbeitungsvorschrift, die so präzise formuliert ist, dass sie einem Computer beigebracht (durch Programmieren) werden kann. Ein Algorithmus ist gewissermassen wie ein Rezept, welches aber vollständig klar formuliert und keinerlei Spielraum für Freiheiten lässt.
Gerade in der Mathematik sind Algorithmen sehr wichtig. Es gibt zum Beispiel Algorithmen für das Erkennen von Primzahlen oder das bestimmen des ggTs. In diesem Kapitel wollen wir einige solche Algorithmen anschauen und dabei unsere Programmierskills verbessern.
Auftrag:
Schreibe für deine Kolleg*In auf Papier einen möglichst guten Algorithmus, der sie vom aktuellen Platz zum (a) Wasserhahn / (b) Haupteingang der Schule bringt. Gehe dabei aus, dass sie maximal einen Meter weit sieht! Danach soll sie den Algorithmus genau so ausführen, wie er auf dem Papier steht!
6.1 Aufgaben E
Aufgabe E1
Die berühmte Fibonacci-Folge besteht aus den Zahlen $$1,1,2,3,5,8,13,21,\ldots$$ Wie sehen die nächsten Folgenglieder aus? Schreibe ein Programm, welches die Folgenglieder der Fibonacci-Folge bestimmt.
Aufgabe E2
- Primzahlen sind positive ganze Zahlen, die nur durch sich selbst und $1$ teilbar sind, also $2,3,5,7,11,13,\ldots$. Schreibe ein Programm, in dem die Benutzer*In eine ganze Zahl eingeben soll. Das Programm überprüft, ob es sich bei der Zahl um eine Primzahl handelt oder nicht und gibt eine entsprechende Rückmeldung.
- Mache eine Kopie deines Programms. Nun soll eine Zahl eingegeben werden und sämtliche kleiner gleich dieser Zahl ausgegeben werden.
Aufgabe E3
Mithilfe des Euklidschen Algorithmus kann man den grössten gemeinsamen Teiler (ggT) von zwei natürlichen Zahlen bestimmen.
- Studiere, wie der Algorithmus funktioniert: https://www.lernhelfer.de/schuelerlexikon/mathematik/artikel/euklidischer-algorithmus.
- Rechne von Hand auf (digitalem) Papier in paar Beispiele durch.
- Implementiere den Euklidschen Algorithmus.
Zusatzaufgaben
Auf der Website https://projecteuler.net gibt es viele interessante Aufgaben, die man programmiererisch lösen soll. Erstelle einen Account und logge dich ein. Studiere eine Aufgabe, schreibe ein Programm, um sie zu lösen und gib deine Lösung auf der Website ein. Du erhältst dann eine Rückmeldung darüber, ob dein Resultat korrekt ist oder nicht.
7. Arrays & Listen
Bisher haben wir Zahlen nur in Variablen speichern können, die jeweils den Wert einer einzelnen Zahl speichern können. Als nächstes schauen wir deshalb Arrays und Listen an. Diese erlauben es uns mehrere Werte in einer einzigen Variablen zu speichern, anstatt für jeden Wert eine eigene Variable zu deklarieren.
Ein Array deklariert man wie folgt:
int[] arr; // declare arr = new int[3]; // initialize
In der ersten Zeile wird die Variable deklariert. Wir sagen dem Programm, dass die Variable mit Namen arr
ein Array (wegen den eckigen Klammern []
) sein soll, welches ints beinhalten soll. In der zweiten Zeile wird die Variable initialisiert: Dazu verwenden wir das Keyword new
. Wir sagen hier dem Programm, das das Array genau 3 Elemente beinhalten soll. Der entsprechende Speicherplatz wird dann im RAM dafür bereitgestellt.
Die beiden Zeilen können auch in einem Schritt erledigt werden:
int[] arr = new int[3]; // declare and initialize
Bei einem int-Array werden sämtliche Werte per Default auf $0$ gesetzt. Wir können aber auch gleich mit der Deklarierung und Initialisierung Werte zuweisen:
int[] arr = new int[3] {7,13,42}; // declare, initialize and set values
Auf die Werte eines Arrays kann über eckige Klammern zugegriffen werden:
arr[0] = 42; // set value of first element to 42 Console.WriteLine(arr[0]); // access first element of array and print in console
ACHTUNG: Beachte, dass man in C# und den meisten anderen Programmiersprachen bei 0 zu zählen beginn!. Das erste Element hat also den Index 0 usw. Dementsprechend folgender Joke:
Für Arrays muss bei der Initialisierung angegeben werden, wie viele Elemente es enthalten soll, damit der entsprechende Speicherplatz reserviert werden kann. Aus diesem Grund ist die Grösse eines Arrays unveränderbar! Dies ist oft aber unpraktisch, da man oft zu Beginn nicht weiss, wie viele Elemente man speichern möchte. Für solche sind Arrays wegen ihrer fixen Grösse unpraktisch. Stattdessen verwendet man dann Listen:
List<int> myList = new List<int>();
Beachte, dass du mit using System.Collections.Generic;
den Namespace System.Collections.Generic einbinden musst, um Listen überhaupt verwenden zu können.
Listen können dann wie folgt manipuliert werden:
myList.Add(7); // add element 7 at end of list, increases length of list by 1 myList.Insert(3, 19); // insert element 19 at index 3 myList.RemoveAt(3); // remove element at index 3, decreases length by 1 myList.Remove(42); // remove first occurrence of element 42 myList.RemoveAll(item => item == 42); // remove ALL occurrences of element 42 Console.WriteLine(myList.Count); // outputs length of list
Beachte, dass Listen deutlich langsamer sind als Arrays. Verwende also wann immer möglich Arrays.
Um sämtlichen Elemente eines Arrays oder einer Liste in der Konsole auszugeben, kann man die Liste mit einer for- oder foreach-Schleife durchgehen:
// OPTION 1: for-loop for (int i = 0; i < myList.Count; i++) { Console.WriteLine(myList[i]); } // OPTION 2: foreach-loop foreach (var item in myList) { Console.WriteLine(item); }
Zusammengefasst:
- Verwende Arrays wenn die Grösse im Vorfeld bekannt ist …
- und Listen falls nicht.
7.1 Aufgaben F
Aufgabe F1
Erstelle jeweils ein Array mit dem vorgegebenen Namen, welches die ersten 20 Folgenglieder der angegebenen Zahlenfolge enthält. Befülle sämtlichen Arrays in einer einzigen Schleife:
- Natürlichen Zahlen (
naturalNumbers
): $1,2,3,...,20$ - Geraden Zahlen (
evenNumbers
): $2,4,6,...,40$ - Quadratzahlen (
squareNumbers
): $1,4,9,16,25,...$
Aufgabe F2
Erstelle jeweils ein Array mit dem vorgegebenen Namen, welches die ersten 20 Folgenglieder der angegebenen Zahlenfolge enthält. Tipp: Recycle deinen Code aus vorherigen Aufgaben.
- Primzahlen (
primeNumbers
): $2,3,5,...$ - Fibonacci-Zahlen (
fibonacciNumbers
): $1,1,2,3,5,...$
Aufgabe F3
Die Benutzer*In wird aufgefordert, eine Zahl einzugeben. Sämtliche Zahlen der Fibonacci-Folge, die kleiner gleich dieser Zahl sind, sollen gespeichert werden. Macht es hier Sinn, ein Array oder eine Liste zu verwenden? Warum?
Zusatzaufgaben
Weiter an den Aufgaben von ProjectEuler.
8. Funktionen
In Programmen muss oft an unterschiedlichen Stellen der gleiche Code ausgeführt werden. Anstelle von copy-paste bietet es sich an, diesen Code in eine Funktion zu verschieben. Ist eine Funktion einmal programmiert, so kann man sie beliebig oft aufrufen. In C# haben Funktionen folgende Form:
static <data type output> MyFunction(<data type input> <variable name input>) { # CODE return <output>; }
In jedem C#-Programm kommt eine spezielle Funktion vor: die Main-Methode (Methoden und Funktionen sind sehr ähnlich - mehr dazu zu einem späteren Zeitpunkt). Dies ist die Funktion, die beim Ausführen des Programms zuerst ausgeführt wird. Alle weiteren Funktionen sollen parallel zur Main-Methode und nicht innerhalb dieser geschrieben werden.
Bemerkungen:
- Der Datentyp des Outputs muss in der Deklaration der Funktion angegeben werden. Ein passendes return-Statement ist dann zwingend.
- Funktionen, die nichts zurückgeben werden mit void gekennzeichnet.
- Eine Funktion kann beliebig viele Inputs (auch Argumente genannt) haben.
Beispiele:
static void SayHi(string name) { Console.WriteLine("Hello, dear " + name + "!"); // void-function: does something (print to console in this case) // but doesn't return anything } static int Square(int x) { return x * x; // takes one argument (x) of type int, does something with it // and returns result (another int) } static void Main(string[] args) { SayHi("Jerry"); int sq = Square(3); Console.WriteLine(sq); }
8.1 Aufgaben G
Aufgabe G1
In dieser ersten Aufgabe geht es darum, möglichst viele, kurze Funktionen zu schreiben. Rufe sämtliche programmierte Funktionen für verschiedene Inputs auf.
- Schreibe eine Funktion
AnswerToEverything
, die keine Argumente entgegennimmt und nichts zurück gibt. Es soll nur die Zahl $42$ in die Konsole geschrieben werden. - Schreibe eine Funktion
Sum
, die zwei ints entgegennimmt und die Summe von diesen berechnet. - Schreibe eine Funktion
isEven
vom Typ Boolean, die einen int entgegen nimmt. Falls dieser gerade (even) ist, wirdtrue
und ansonstenfalse
zurückgegeben.
Aufgabe G2
Schreibe eine Funktion FahrenheitToCelsius
, die eine Temperatur als Gleitkommazahl von Fahrenheit in Celsius umrechnet und zurück gibt.
Wieviel Grad sind 212 Fahrenheit?
Tipp: https://de.wikipedia.org/wiki/Grad_Fahrenheit#Umrechnung
Aufgabe G3
Primzahlen immer wieder
- Schreibe eine Funktion
isPrime
vom Typ Boolean, die einen int entgegen nimmt. Die Funktion entscheidet dann darüber, ob die Zahl prim ist oder nicht und gibt einen entsprechenden Output heraus:true
falls sie prim ist und ansonstenfalse
. - Gehe nun in einer Schleife alle Zahlen von 2 bis 100 durch. Entscheide mithilfe der Funktion von oben für jede Zahl, ob sie prim ist oder nicht. Falls ja, gib die Zahl in der Konsole aus.
Aufgabe G4
Die meisten Programmiersprachen kommen mit vielen vorprogrammierten Utility-Functions daher, die einem das Leben vereinfachen. Ziel dieser Aufgabe ist es, diese Utility-Functions selbst zu programmieren, und dabei nur die rudimentärsten Befehle wie Schleifen oder if-else zu verwenden. Es sollen auch keine Listen sondern nur Arrays verwendet werden. Natürlich sollen selbst programmierte Utility-Functions verwendet werden dürfen.
- Funktion
Length
, die die Länge eines Strings bestimmt und zurück gibt. - Funktion
NumberOfChar
, die überprüft, wie oft ein bestimmter Buchstabe (Typ: char) in einem String vorkommt. - Funktion
PositionsOfChar
, die in einem Array sämtliche Positionen eines Buchstaben in einem String angibt.
9. Projekt: Hangman
Ziel: Programmiere das bekannte Hangman-Game als Konsolengame.
Tipps: Definiere, wann sinnvoll, Funktionen.
Version 1: Basics
- Eine Person soll das Wort, welches der Spieler erraten soll, eingeben. Natürlich soll dieses in einer Variablen gespeichert werden.
- Zeige nun mithilfe von Underlines _ an, aus wie vielen Buchstaben das gesuchte Wort besteht.
- Der Spieler soll nun Buchstaben raten und eingeben. Kommt ein Buchstabe im gesuchten Wort vor, so wird der entsprechende Underline ersetzt. Tipp: Verwende
char c = Console.ReadKey().KeyChar;
um einzelne Buchstaben einzugeben, ohne Enter drücken zu müssen. - Gross- und Kleinschreibweise soll keine Rolle spielen.
- Sobald das gesamte Wort erraten wurde, wird dem Spieler gratuliert.
Version 2: Gameplay
- Zähle mit, wie viele Versuche der Spieler braucht. Teile dem Spieler am Schluss die Anzahl Versuche mit.
- Lege eine maximale Anzahl versuche fest. Benötigt der Spieler zu viele Versuche, soll Game Over ausgegeben werden.
- Gibt der Spieler einen Buchstaben erneut ein, soll der Versuch ignoriert werden und nicht als Fehlversuch zählen.
Version 3: Grafische Darstellung
Ziel ist nun, dass die Anzahl Versuche durch den hänging Man graphisch dargestellt werden.
- Definiere dazu eine Funktion, die die Anzahl Versuche entgegen nimmt und die zugehörige Grafik in die Konsole schreibt:
- 0 - nur Galgen
- 1 - Kopf
- 2 - Kopf, Oberkörper
- 3 - Kopf, Oberkörper, ein Bein
- 4 - Kopf, Oberkörper, beide Beine
- 5 - Kopf, Oberkörper, beide Beine, ein Arm
- 6 - HangMan
- Verbessere und fine-tune nun dein Spiel so, dass es gut funktioniert und hübsch aussieht.
** Version 4: OOP
Nur für Fortgeschrittene mit Vorwissen in OOP
- Programmiere Hangman mit OOP.
- Implementiere mindestens zwei Klassen:
- Spielelogik
- Ausgabe
- Schreibe nach jeder Runde für die Ausgabe nicht den ganzen Bildschirm neu, sondern immer nur die Zeichen, die sich tatsächlich ändern.
- Der letzte angefügte Körperteile soll jeweils in einer anderen Farbe angezeigt werden.
- Die Klassen dürfen statisch sein.
- Eingabe und Programmfluss können direkt in Main() liegen.