1 / 108

Programmierung mit JavaScript

Programmierung mit JavaScript. Klaus Becker 2005. Programmierung mit JavaScript.

Télécharger la présentation

Programmierung mit JavaScript

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Programmierung mit JavaScript Klaus Becker 2005

  2. Programmierung mit JavaScript <script type="text/javascript"><!-- var groesse, gewicht, bmi; function berechnen() { groesse = document.formular.eGroesse.value; gewicht = document.formular.eGewicht.value; bmi = gewicht/(groesse*groesse); document.formular.aBMI.value = bmi; }//--></script> document:Dokument formular:Formular : A eGroesse: Eingabefeld : A eGewicht: Eingabefeld : A bRechnen: Button value="Berechnen"onClick="berechnen()" : A aBMI: Eingabefeld

  3. Teil 1 Interaktive Web-Seiten

  4. Body-Mass-Index http://www.actifit.ch/ActifitWomenOnly/Pages/bmi.htm Eingabefeld Button

  5. Body-Mass-Index Darstellung der Web-Seite ...<script language="javascript">...function detBMI(aWeight, aHeight) { aHeight = aHeight / 100; return Math.round(aWeight/eval(aHeight * aHeight));}... </script>... Ausschnitt aus dem Quelltext

  6. Browser als JavaScript-Interpreter Der Browser zeigt die ausgelieferte Webseite an und führt das integrierte JavaScript-Programm (bei Bedarf) aus. http://www.actifit.ch/ActifitWomenOnly/Pages/bmi.htm www.actifit.ch Fordert ein Dokument an Browser (Client) WWW-Server (Server) http Liefert das Dokument aus ...<script language="javascript">...function detBMI(aWeight, aHeight) { aHeight = aHeight / 100; return Math.round(aWeight/eval(aHeight * aHeight));}... </script>... ActifitWomenOnly/Pages/bmi.htm

  7. Zielsetzung Ziel ist es, anhand einer vereinfachten Version den Aufbau einer interaktiven Web-Seite zu verstehen. Vereinfachte Webseite

  8. Quelltext zur Webseite <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="content-type" content="text/html; charset=iso-8859-1"><title>BMI</title><script type="text/javascript">...</script> </head><body><h2>Berechnen Sie Ihren BMI-Wert!</h2><form action ="" name="formular"><p>Groesse (in m): <input type="text" name="eGroesse" value="2.00"></p><p>Gewicht (in kg): <input type="text" name="eGewicht" value="100"></p><p><input type="button" name="bRechnen" value="Berechnen" onClick="berechnen()"></p><p>BMI: <input type="text" name="aBMI"></p></form></body></html>

  9. Struktur der Webseite <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="content-type" content="text/html; charset=iso-8859-1"><title>BMI</title><script type="text/javascript">...</script> </head><body><h2>Berechnen Sie Ihren BMI-Wert!</h2><form action ="" name="formular"><p>Groesse (in m): <input type="text" name="eGroesse" value="2.00"></p><p>Gewicht (in kg): <input type="text" name="eGewicht" value="100"></p><p><input type="button" name="bRechnen" value="Berechnen" onClick="berechnen()"></p><p>BMI: <input type="text" name="aBMI"></p></form></body></html> document:Dokument : Überschrift ... : Zeichen : Zeichen : Zeichen formular:Formular eGroesse:Eingabefeld ... : Absatz : Zeichen eGewicht:Eingabefeld : Absatz bRechnen:Button : Absatz aBMI:Eingabefeld : Absatz enthält ... ...

  10. Objekthierarchie document:Dokument <!DOCTYPE HTML ...><html>...</html> : Überschrift ... : Zeichen : Zeichen : Zeichen formular:Formular <form action ="" name="formular">...</form> <input type="text"name="eGroesse" value="2.00"> eGroesse:Eingabefeld : A Objektname <input type="text"name="eGewicht" value="100"> Objekttyp eGewicht:Eingabefeld : A <input type="button"name="bRechnen" ...> bRechnen:Button : A <input type="text"name="aBMI"> aBMI:Eingabefeld : A enthält ... ...

  11. Eigenschaften von Objekten document:Dokument title = ... formular:Formular <form action =""name="formular">...</form> action =... eGroesse:Eingabefeld : A <input type="text"name="eGroesse"value="2.00"> value = "2.00"... Attribut Attributwert

  12. Ereignisbehandlung <script type="text/javascript"><!-- var groesse, gewicht, bmi;function berechnen() { groesse = document.formular.eGroesse.value; gewicht = document.formular.eGewicht.value; bmi = gewicht/(groesse*groesse); document.formular.aBMI.value = bmi; }//--></script> document:Dokument formular:Formular : A eGroesse: Eingabefeld : A eGewicht: Eingabefeld Wenn der Benutzer auf den Button drückt, löst er ein Ereignis aus, das vom sog. „Eventhandler“ bearbeitet wird. Dieser Eventhandler veranlasst, die Javascript-Funktion „berechnen()“ auszuführen. : A bRechnen: Button value="Berechnen"onClick="berechnen()" : A aBMI: Eingabefeld

  13. Variablen <script type="text/javascript"><!--var groesse, gewicht, bmi; function berechnen() { groesse = document.formular.eGroesse.value; gewicht = document.formular.eGewicht.value; bmi = gewicht/(groesse*groesse); document.formular.aBMI.value = bmi; }//--></script> document:Dokument formular:Formular eGroesse: Eingabefeld : A value = "2.00" eGewicht: Eingabefeld : A value = "100" groesse: : A bRechnen: Button gewicht: aBMI: Eingabefeld : A bmi: value = ""

  14. Zugriff auf Attributwerte <script type="text/javascript"><!-- var groesse, gewicht, bmi; function berechnen() { groesse = document.formular.eGroesse.value; gewicht = document.formular.eGewicht.value; bmi = gewicht/(groesse*groesse); document.formular.aBMI.value = bmi; }//--></script> document:Dokument title = ... formular:Formular action = ... eGroesse:Eingabefeld : A groesse: value = "2.00"... gewicht: bmi: document.formular.eGroesse.value : "2.00"

  15. Kopieren der Eingabewerte <script type="text/javascript"><!-- var groesse, gewicht, bmi; function berechnen() {groesse = document.formular.eGroesse.value; gewicht = document.formular.eGewicht.value; bmi = gewicht/(groesse*groesse); document.formular.aBMI.value = bmi; }//--></script> document:Dokument formular:Formular eGroesse: Eingabefeld : A value = "2.00" eGewicht: Eingabefeld : A value = "100" "2.00" groesse: : A bRechnen: Button "100" gewicht: aBMI: Eingabefeld : A bmi: value = ""

  16. Verarbeitung <script type="text/javascript"><!-- var groesse, gewicht, bmi; function berechnen() { groesse = document.formular.eGroesse.value; gewicht = document.formular.eGewicht.value;bmi = gewicht/(groesse*groesse); document.formular.aBMI.value = bmi; }//--></script> document:Dokument formular:Formular eGroesse: Eingabefeld : A value = "2.00" eGewicht: Eingabefeld : A value = "100" "2.00" groesse: : A bRechnen: Button "100" gewicht: aBMI: Eingabefeld : A 25.0 bmi: value = ""

  17. Kopieren des Ausgabewerts <script type="text/javascript"><!-- var groesse, gewicht, bmi; function berechnen() { groesse = document.formular.eGroesse.value; gewicht = document.formular.eGewicht.value; bmi = gewicht/(groesse*groesse);document.formular.aBMI.value = bmi; }//--></script> document:Dokument formular:Formular eGroesse: Eingabefeld : A value = "2.00" eGewicht: Eingabefeld : A value = "100" "2.00" groesse: : A bRechnen: Button "100" gewicht: aBMI: Eingabefeld : A 25.0 bmi: value = "25.0"

  18. EVA-Prinzip <script type="text/javascript"><!-- var groesse, gewicht, bmi; function berechnen() {// Eingabe groesse = document.formular.eGroesse.value; gewicht = document.formular.eGewicht.value;// Verarbeitung bmi = gewicht/(groesse*groesse); // Ausgabe document.formular.aBMI.value = bmi; }//--></script> E V A Viele Programme lassen sich nach dem EVA-Prinzip entwerfen: Man versucht, die Verarbeitungsprozesse nach dem Muster „Eingabe, Verarbeitung, Ausgabe“ zu gliedern.

  19. Algorithmus JavaScript-Programm <script type="text/javascript"><!-- var groesse, gewicht, bmi; function berechnen() {// Eingabe groesse = document.formular.eGroesse.value; gewicht = document.formular.eGewicht.value;// Verarbeitung bmi = gewicht/(groesse*groesse); // Ausgabe document.formular.aBMI.value = bmi; }//--></script> Eingabe: groesse, gewicht bmi = gewicht/(groesse*groesse) Ausgabe: bmi Algorithmus Struktur und Verhalten eines Programms lassen sich oft besser verstehen, wenn man den zu Grunde liegenden Algorithmus herausstellt.

  20. Algorithmus Algorithmus zur Berechnung des BMI-Werts: E Eingabe: groesse, gewicht bmi = gewicht/(groesse*groesse) Ausgabe: bmi V A Struktur und Verhalten eines Programms lassen sich oft besser verstehen, wenn man den zu Grunde liegenden Algorithmus herausstellt.

  21. Übung Ziel ist es, ein interaktives Programm zur Flächeninhaltsberechnung zu entwickeln. Verhaltensbeschreibung: Eingabe: Länge und Breite eines Rechtecks Ausgabe: Umfang und Flächeninhalt des Rechtecks Entwerfen Sie zunächst - eine geeignete Benutzungsoberfläche und- einen Algorithmus zum gewünschten Verhalten. Entwickeln Sie anschließend das Programm in Analogie zum BMI-Programm.

  22. Übung Ziel ist es, ein interaktives Programm zur Umrechnung eines Euro-Betrags in US-Dollar zu entwickeln. Entwerfen Sie zunächst - eine Verhaltensbeschreibung (Eingaben und Ausgaben), - eine geeignete Benutzungsoberfläche und- einen Algorithmus zum gewünschten Verhalten. Entwickeln Sie anschließend das Programm in Analogie zum BMI-Programm. Hinweis: Aktuelle Kursdaten finden Sie unter http://dollar-kurse.de.

  23. Teil 2 Variablenkonzept

  24. Mäusepopulation Wir betrachten die Entwicklung einer Mäusepopulation. Die Population wird unterteilt in junge Mäuse, erwachsene Mäuse und alte Mäuse. Wir gehen von den folgenden Annahmen aus: - In einem Simulationsschritt wird die Hälfte der jungen Mäuse erwachsen. - In einem Simulationsschritt erzeugt jede erwachsene Maus (im Durchschnitt) 4 junge Mäuse. Nur ein Drittel der erwachsenen Mäuse wird in einem Simulationsschritt alt. - In einem Simulationsschritt erzeugt jede alte Maus (im Durchschnitt) 2 junge Mäuse. Alle alten Mäuse sterben innerhalb dieses Simulationsschrittes.

  25. Mäusepopulation jung 6 erw. 9 alt 12 Schritt 0 1/2 1/3 4 2 i  i+1 jung 60 erw. 3 alt 3 Schritt 1

  26. Entwicklung der Mäusepopulation Schritt Anzahl der Anzahl der Anzahl der jungen Mäuse erw. Mäuse alten Mäuse 0 6 9 12 1 60 = 4*9 + 2*12 3 = 6:2 3 = 9:3 2 18 = 4*3 + 2*3 30 = 60:2 1 = 3:3 3 122 = 4*30 + 2*1 9 = 18:2 10 = 30:3 4 56 = 4*9 + 2*10 61 = 122:2 3 = 9:3 5 250 = 4*61 + 2*3 28 = 56:2 20,3.. = 61:3 ... Zielsetzung: Automatisierung der Berechnung der jeweils nächsten Mäusepopulation

  27. Berechnungsmodell Die zu verarbeitenden Daten werden in Speicherzellen abgelegt und mit Hilfe von Variablen verwaltet. Speicherzelle Schritt : 0 jung : 6.0 erwachsen : 9.0 alt : 12.0 Variablenname Variablenwert Variablenzustand {Schritt: [0]; jung: [6.0]; erwachsen: [9.0]; alt: [12.0]}

  28. Berechnungsmodell Eine Veränderung eines Speicherzelleninhalts kann mit Hilfe einer Wertzuweisung (an die entsprechende Variable) erfolgen. {Schritt: [0]; jung: [6.0]; erwachsen: [9.0]; alt: [...]} Variablenzustand vorher alt  12.0 Wertzuweisung {Schritt: [0]; jung: [6.0]; erwachsen: [9.0]; alt: [12.0]} Variablenzustand nachher Variablenzustand vorher {Schritt: [0]; jung: [6.0]; erwachsen: [9.0]; alt: [12.0]} Wertzuweisung erwachsen  jung / 2 {Schritt: [0]; jung: [6.0]; erwachsen: [3.0]; alt: [12.0]} Variablenzustand nachher {Schritt: [0]; jung: [6.0]; erwachsen: [3.0]; alt: [12.0]} Variablenzustand vorher Schritt  Schritt +1 Wertzuweisung {Schritt: [1]; jung: [6.0]; erwachsen: [3.0]; alt: [12.0]} Variablenzustand nachher

  29. Struktur einer Wertzuweisung Struktur einer Wertzuweisung (vorläufig): Eine Wertzuweisung besteht aus einer Variablen (der ein Wert zugewiesen wird) und einem Term (der den zuzuweisenden Wert festlegt). alt = 12.0 erwachsen = jung / 2 Wertzuweisungen in JavaScript Schritt = Schritt + 1 Variable  Term Wertzuweisung - Struktur

  30. Auswertung einer Wertzuweisung Auswertung einer Wertzuweisung: Der Wert des Terms (rechte Seite der Wertzuweisung) wird bzgl. des aktuellen Variablenzustands ermittelt und der Variablen (linke Seite der Wertzuweisung) als neuer Wert zugewiesen. Der Inhalt der zur Variablen gehörenden Speicherzelle wird dabei überschrieben. Schritt : 0 Variablenzustand vorher Schritt  Schritt + 1 Variable  Term 1 Schritt : 1 Variablenzustand nachher

  31. Berechnung einer neuen Population vorherDie eingeführten Variablen beschreiben die Anfangspopulation. {Schritt: [0]; jung: [6.0]; erwachsen: [9.0]; alt: [12.0]} nachherDie Variablen beschreiben die Population nach einem Simulationsschritt. {Schritt: [1]; jung: [60.0]; erwachsen: [3.0]; alt: [3.0]} Problemspezifikation Algorithmus Schritt  Schritt + 1 jung  erwachsen*4 + alt*2 erwachsen  jung / 2 alt  erwachsen / 3 Vorschlag für einen Algorithmus

  32. Trace-Tabelle Mit Hilfe einer Trace-Tabelle kann man die einzelnen Berechnungsschritte verfolgen. Trace-Tabelle Wertzuweisung Schritt  Schritt + 1 jung  erwachsen*4 + alt*2 erwachsen  jung / 2 alt  erwachsen / 3 Variablenzustand Schritt jung erw. alt 0 6.0 9.0 12.0 1 6.0 9.0 12.0 1 60.0 9.0 12.0 1 60.0 30.0 12.0 1 60.030.0 10.0 Nicht korrekt!

  33. Reihenfolge von Wertzuweisungen Trace-Tabelle Wertzuweisung Schritt  Schritt + 1 hilf  erwachsen*4 + alt*2 alt  erwachsen / 3 erwachsen  jung / 2 jung  hilf Variablenzustand Schritt jung erw. alt hilf 0 6.0 9.0 12.0 1 6.0 9.0 12.0 1 6.0 9.0 12.0 60.0 1 6.0 9.0 3.0 60.0 1 6.0 3.0 3.0 60.0 1 60.0 3.0 3.0 60.0 korrekt! Beachte: Bei der Datenverarbeitung mit Hilfe von Wertzuweisungen muss man auf die Reihenfolge der Wertzuweisungen achten.

  34. Algorithmus Algorithmus zur Berechnung des jeweils nächsten Populationszustands: E Eingabe: Schritt, jung, erwachsen, alt Schritt  Schritt + 1 hilf  erwachsen*4 + alt*2 alt  erwachsen / 3 erwachsen  jung / 2 jung  hilf Ausgabe: Schritt, jung, erwachsen, alt V A

  35. Aufgabe Testen Sie den folgenden Implementierungsversuch (siehe „Maeuse1“). var Schritt, jung, erwachsen, alt, hilf; function berechnen() { // Eingabe Schritt = document.formular.eSchritt.value; jung = document.formular.eJung.value; erwachsen = document.formular.eErwachsen.value; alt = document.formular.eAlt.value; // Verarbeitung Schritt = Schritt + 1; hilf = erwachsen*4 + alt*2; alt = erwachsen/3; erwachsen = jung/2; jung = hilf; // Ausgabe document.formular.eSchritt.value = Schritt; document.formular.eJung.value = jung; document.formular.eErwachsen.value = erwachsen; document.formular.eAlt.value = alt; }

  36. Aufgabe Führen Sie das Testprogramm „Typentest“ aus. Deuten Sie die Ergebnisse. Wie lässt sich hiermit das fehlerhafte Verhalten des Programms „Maeuse1“ erklären? Welche Möglichkeiten gibt es, den Fehler zu beheben?

  37. Programmtest: Maeuse1 function berechnen() { // Eingabe Schritt = document.formular.eSchritt.value; jung = document.formular.eJung.value; erwachsen = document.formular.eErwachsen.value; alt = document.formular.eAlt.value; // Verarbeitung Schritt = Schritt + 1; hilf = erwachsen*4 + alt*2; alt = erwachsen/3; erwachsen = jung/2; jung = hilf; // Ausgabe document.formular.eSchritt.value = Schritt; document.formular.eJung.value = jung; document.formular.eErwachsen.value = erwachsen; document.formular.eAlt.value = alt; } Hier stimmt etwas nicht!

  38. Programm: Typentest ... document.write("Deklaration: var a: <br>"); document.write("a hat den Datentyp <i>"+typeof(a)+"</i>.<br><br>"); a = 1; document.write("Anweisung: a = 1: <br>"); document.write("a hat den Datentyp <i>"+typeof(a)+"</i>.<br><br>"); a = "1"; document.write('Anweisung: a = "1": <br>'); document.write("a hat den Datentyp <i>"+typeof(a)+"</i>.<br><br>"); a = a+1; document.write("Anweisung: a = a+1: <br>"); document.write("a hat den Datentyp <i>"+typeof(a)+"</i>.<br><br>"); a = a*1; document.write("Anweisung: a = a*1: <br>"); document.write("a hat den Datentyp <i>"+typeof(a)+"</i>.<br><br>"); a = "1"; document.write('Anweisung: a = "1": <br>'); document.write("a hat den Datentyp <i>"+typeof(a)+"</i>.<br><br>"); a = parseInt(a); document.write("Anweisung: a = parseInt(a): <br>"); document.write("a hat den Datentyp <i>"+typeof(a)+"</i>.<br><br>") ...

  39. Datentypen Ein Datentyp legt einen Wertebereich und die Grundoperationen fest, die mit den Elementen des Wertebereichs durchgeführt werden können. Datentyp: number (JavaScript) Der Datentyp number beschreibt ganze Zahlen wie 1 oder -1 und Dezimalzahlen wie 3.14 oder -2.1. Beachte, dass der Wertebereich insgesamt endlich ist. Operationen: 3 + 2  53 – 2  13 * 2  63 / 2  1.53 % 2  1 (Rest bei ganzzahliger Division) Datentyp: string (JavaScript) Der Datentyp string beschreibt Zeichenketten wie "hallo" oder "Anweisung: a = 2". Grundoperation: "2" + "5"  "25" (Konkatenation)

  40. Zahl oder Zeichenkette? ... function berechnen() { Schritt = document.formular.eSchritt.value; jung = document.formular.eJung.value; erwachsen = document.formular.eErwachsen.value; alt = document.formular.eAlt.value; Schritt = Schritt + 1; hilf = erwachsen*4 + alt*2; alt = erwachsen/3; erwachsen = jung/2; jung = hilf; document.formular.eSchritt.value = Schritt; document.formular.eJung.value = jung; document.formular.eErwachsen.value = erwachsen; document.formular.eAlt.value = alt; } ... <form action ="" name="formular"> <p>Anzahl der Simulationsschritte: <input type="text" name="eSchritt" value="0"> </p> Schritt  "0" "0" + 1  ? 0 + 1  1 "0" + "1"  "01" Zeichenkette

  41. Automatische Typumwandlung ... function berechnen() { Schritt = document.formular.eSchritt.value; jung = document.formular.eJung.value; erwachsen = document.formular.eErwachsen.value; alt = document.formular.eAlt.value; Schritt = Schritt + 1; hilf = erwachsen*4 + alt*2; alt = erwachsen/3; erwachsen = jung/2; jung = hilf; document.formular.eSchritt.value = Schritt; document.formular.eJung.value = jung; document.formular.eErwachsen.value = erwachsen; document.formular.eAlt.value = alt; } ... <form action ="" name="formular"> <p>Anzahl der Simulationsschritte: <input type=text name="eSchritt" value="0"> </p> Eingabe: string Umwandlung: string  number Umwandlung: number  string Ausgabe: string 7

  42. Explizite Typumwandlung ... function berechnen() { Schritt = parseInt(document.formular.eSchritt.value); jung = parseInt(document.formular.eJung.value); erwachsen = parseInt(document.formular.eErwachsen.value); alt = parseInt(document.formular.eAlt.value); Schritt = Schritt + 1; hilf = erwachsen*4 + alt*2; alt = erwachsen/3; erwachsen = jung/2; jung = hilf; document.formular.eSchritt.value = Schritt; document.formular.eJung.value = jung; document.formular.eErwachsen.value = erwachsen; document.formular.eAlt.value = alt; } ... <form action ="" name="formular"> <p>Anzahl der Simulationsschritte: <input type=text name="eSchritt" value="0"> </p> parseInt: string  number Eingabe: string Autom. Umwandlung: number  string Ausgabe: string

  43. JavaScript und Typen JavaScript ist nicht typisiert. Der Typ einer Variablen wird bei einer Variablendeklaration nicht festgelegt. JavaScript wandelt Typen automatisch um. JavaScript versucht, aus dem Kontext (z. B. durchzuführende Operationen) zu erschließen, von welchem Typ die zu verarbeitenden Werte sind. Hierdurch kann es zu automatischen Typumwandlungen kommen. Vorteil: Beim Programmieren mit JavaScript muss man sich oft nicht um Typen kümmern. Das macht die Sache einfacher. Nachteil: Fehler sind manchmal schwer zu finden. Die Klarheit leidet durch die nicht im Text angezeigten Umwandlungsoperationen.

  44. Aufgabe Ergänzen Sie im Programm „Maeuse1“ die erforderlichen Typumwandlungen. Testen Sie anschließend das neue Programm.

  45. Teil 3 Kontrollstrukturen

  46. Bisher: Sequentielle Algorithmen BMI-Berechnung Mäusepopulation Eingabe: gewicht, groesse bmi  gewicht/(groesse*groesse); Ausgabe: bmi Eingabe: Schritt, jung, erwachsen, alt Schritt  Schritt + 1 hilf  erwachsen*4 + alt*2 alt  erwachsen / 3 erwachsen  jung / 2 jung  hilf Ausgabe: Schritt, jung, erwachsen, alt

  47. Variationen zur BMI-Berechnung Das Programm zur Berechnung des BMI-Werts soll dem Benutzer weitere Informationen in Abhängigkeit des berechneten Werts liefern.

  48. Zweiseitige Fallunterscheidung

  49. Zweiseitige Fallunterscheidung function berechnen() { groesse = parseFloat(document.formular.eGroesse.value); gewicht = parseFloat(document.formular.eGewicht.value); bmi = gewicht/(groesse*groesse); if (bmi < 19) { bewertung = "Untergewicht"; } else { if (bmi > 26) { bewertung = "Übergewicht"; } else { bewertung = "Normalgewicht"; }; }; document.formular.aBMI.value = bmi; document.formular.aBewertung.value = bewertung; }

  50. Einseitige Fallunterscheidung

More Related