Anfang gespielt wird. Mein Name ist Timo. Ich habe
einige Durchgänge bei SE1 schon als Betreuer mitgemacht, dieses Jahr nicht.
Also ihr werdet mich nicht in den Übungen sehen,
aber ich will euch trotzdem Angebote machen,
wie ihr weiter oder mehr lernen könnt.
Und zwar für einige vielleicht gemerkt haben,
in den Übungen ist das erste Level von SE1 abgeschlossen.
Ja, also irgendwie müssten alle die Übungsblätter dazu erledigt haben.
Jetzt ist so ein bisschen die Frage,
die wir uns stellen. Habt ihr überhaupt Level 1?
Was ist das? Level 1? Habt ihr das verstanden?
Habt ihr
das mitbekommen
Könnt ihr damit was anfangen? Und ich glaube,
das schöne Beispiel hier oben, was man sieht zum Super Mario 1,
was die meisten vielleicht nicht mehr gespielt haben,
aber trotzdem kennen, das ist das Level 1. Und alle Leute,
die das gespielt haben, wissen trotzdem einige Jahre später,
können sie sofort zu dem Level,
zu den Bildern anfangen und wissen sie,
wie das Level eigentlich so aufgebaut war, wie das so funktioniert hat,
wie man da vielleicht Probleme hatte oder sonstiges.
Und dieses Gefühl wollen wir euch auch irgendwie geben und deswegen,
wenn wir dieses Semester erstmalig etwas anbieten,
nämlich Online-Selbsttest zu jedem Level,
was ihr in den Übungen oder auch in der Vorlesung erreichen werdet,
Und das Ganze soll möglichst klausurähnlich stattfinden.
Also ihr werdet dann wirklich online einen Test durchführen können.
Der wird jeweils 30 Minuten dauern für jedes Level.
Und ihr werdet dort klausurähnliche Fragen kennenlernen. Und es wird auch so sein,
dass man, glaube ich, hinterher sagen kann,
wenn man das gut erledigt hat, kann man relativ guten Gefühl,
mit einem guten Gefühl auch zu der Klausur später gehen.
Das Ganze wird im Olat stattfinden. Wer kennt das?
Olat? Okay, doch einige, das sind wahrscheinlich die Nebenfachstudierenden.
Oder wie kommt es, dass das so ein bisschen bekannt ist?
Also das ist so ein bisschen Konkurrenz-Plattformen zum Kommen Sie,
was ja, glaube ich,
in SE1
häufiger verwendet wird
Und wir werden das Ganze in diesem Urlaub anwenden.
Also wir haben da auch einen Lernraum eingerichtet. Und unter
dem Link werdet ihr ab nächsten Montag etwas sehen können.
Und zwar genau so ein Selbsttest für 30 Minuten.
Und es wird so sein, dass ihr euch mit dem
Steen-Account anmelden müsst. Wir wissen noch nicht so ganz,
ob das gut oder schlecht ist.
Das müsst ihr dann uns auch hinterher vielleicht am besten sagen.
Ihr müsst euch klarmachen, ich bin sozusagen der Ansprechpartner für all diese extra Lernaktivitäten.
Also ihr könnt mich jederzeit per E-Mail anfragen und mir
irgendwelche Bedenken oder Sorgen oder sonstiges schreiben zu dem Thema Selbsttest
und zu später noch vorgestellten anderen Lernmodulen,
die auch noch kommen werden
Jetzt mal einen kurzen Einblick in diese Selbsttestvariante.
So soll das Ganze ungefähr aussehen. Es wird Fragen geben
. Ich hoffe, ihr könnt ihn ganz gut lesen.
Und jetzt momentan sind wir nur eine Frage.
Also eine Testfrage, die ihr beantworten könntet.
Ich möchte aber lieber Axel fragen, was ist denn jetzt,
ja, was kannst du auch mal was machen?
Folgendes. Das kann ich nicht beantworten. Oha. Also
Axel weiß nicht so ganz, üblich ist halt dann,
dass man ein Publikumsjoker hat.
Ich ziehe die Publikumsjoker
Ich habe zufällig diese Frage dabei. Ja,
ihr könnt ja meinem abstimmen hier. Los. Gebt
eure Stimme ab. Da sind wieder ein paar Stimmen.
Juhu. Es gibt eine Meinung dazu
Das ist noch ein bisschen zäh so. Okay,
ich halte das mal an, 100 reicht erst mal.
Es ging nur darum, dass ihr seht,
dass das hier natürlich auch wieder eine Storesi-Abfrage geben wird heute.
Ich habe noch mehr Fragen für die heutigen, für den heutigen Stoff.
Das ist ja eine klassische Level-1-Frage, ja. Und wenn wir uns das jetzt mal angucken,
was hier die Lösung ist, wir können ja erst mal gucken,
wie die Verteilung so war,
da sagen ziemlich viele zwölf, ziemlich viele sagen A,
0 und dann gibt es noch einige,
die sagen 13.
Die richtige Antwort ist 13. Okay,
wieder mal ein überraschender Effekt an dieser Stelle
Wir gucken also auch hier mal,
wenn ich jetzt hier die 13 anklicke und dann irgendwie sage,
Test abschließen, dann müsste mir irgendwie, ja,
ja, ich will das abschließen.
Und dann Testergebnisse werden gespeichert. Und jetzt sieht man normalerweise
auch ein Bewertungswerkzeug irgendwie. Das klappt dir noch nicht so gut.
Wir sind noch am Bauen. Aber das wird nicht nur noch eine Frage sein,
sondern wir werden tatsächlich einen gewissen Umfang haben,
den ihr dann in 30 Sekunden ungefähr, in 30 Minuten ungefähr ganz gut schaffen könnt.
Und das wird alles nur zu Level 1 sein.
Okay. Genau. Ihr könnt bei diesen Fragen
auch Kommentare abgeben
Und da ist es dann irgendwie ganz hilfreich,
wenn ihr uns dann noch sagt,
blöde Frage oder zu einfach oder zu schwer.
Also da könnt ihr durchaus dann auch diese Fragen kommentieren,
innerhalb der 30 Minuten. Das wäre auch für uns ganz hilfreich,
wenn wir da auch ein bisschen Feedback kriegen zur Schwierigkeit der Fragen.
Gut, das wollen wir wirklich schließen hier.
Das Olat-Zeug kann jetzt zu. Und wir sind wieder in
der Vorlesung. Ja, willkommen zur sechsten Vorlesung
Vielen Dank, Timo. Wie gesagt, Timo steht dann
auch zukünftig dafür zur Verfügung. Ab Montag geht das weiter
. Danke. Ich glaube, das ist eine ganz,
das ist eine ganz coole Sache, die da jetzt möglich wird.
Das ist tatsächlich durch Fördermittel ermöglicht, dass Timo da
jetzt bezahlt werden kann für das, was er macht.
Und das ist das sogenannte Lehrlabor hier der Minfakultät, eine sehr,
sehr schöne Einrichtung, die uns das hier auch ermöglicht.
Wir wollen da jetzt zusammen was aufbauen und es wäre,
wie gesagt, gut, wenn ihr da auch mit dazukommt.
Gut. Ja, strukturierte Programmierung heute das Thema. Was
wir uns ansehen werden, ist zum einen bedingte Anweisung.
Also Fallunterscheidungen im allgemeineren Sinne. Sowas wie bedingte Anweisungen oder
auch so Case-Switch-Geschichten in Java. Also einfach Verzweigung und Mehrfachverzweigung
. Und wir werden uns natürlich schleifen ansehen müssen.
Schleifen in Java. Das ist etwas,
was sehr zentral ist, wenn man programmieren will.
Die andere Möglichkeit, Wiederholungen zu programmieren, nämlich mit Rekursion.
Die sehen wir uns nächste Woche an. Das heißt also,
in dieser Woche und in der nächsten Woche
werden wir uns einfach damit beschäftigen,
wie man denn
sehr systematisch Wiederholungen programmieren kann
Insbesondere natürlich in Java. Okay, dazu muss ich nochmal wieder so
ein bisschen einordnen, was wir jetzt hier uns ansehen wollen.
Ich habe schon auf verschiedenen Folien so versucht,
so ein Gefühl dafür zu geben,
dass es so etwas gibt wie den Kontrollfluss.
Wir haben gesagt, so ein objektnotiertes System,
da fließt der Kontrollfluss so durch die Objekte, die beteiligt sind.
Haben wir immer so angedeutet mit so einem roten Pfeil.
Und der Kontrollfluss bestimmt eigentlich die Reihenfolge in der Dinge ausgeführt werden.
Das heißt, was ihr schon kennt,
ist zwischen den Anweisungen einer Methode,
also in dem Rumpf einer Methode
werden die Anweisungen
sequenziell ausgeführt
Einfach. Innerhalb einer Anweisung haben wir vor zwei Wochen gesehen,
gibt es sowas wie Ausdrücke.
Und da ist es einfach auch wichtig zu verstehen,
wie innerhalb eines Ausdrucks eine Reihenfolge existiert durch die Präzedenzen der Operatoren zum Beispiel.
Also das sind Dinge, die da auch eine Rolle spielen.
Und natürlich zwischen den Methoden. Also wenn eine Methode aufgerufen wird,
wechselt der Kontrollfluss zu einer Methode,
da wird die Methode abgearbeitet und dann wieder zur Aufrufstelle zurück.
Das ist, das sind die Kontrollflussmechanismen, die wir bisher
kennengelernt haben. Und ganz wichtig an der Stelle wieder,
wir haben hier immer noch das vereinfachte Modell, dass es nur einen Prozess gibt.
Also sozusagen dieser rote Pfeil immer genau an einer Stelle ist,
in unseren Objekten,
irgendeine Methode eines Objektes wird jetzt gerade ausgeführt und dann irgendwann
die nächste und
so weiter
Okay. Jetzt ist es in der imperativen Programmierung,
man sieht wieder diesen gestreiften Burschenau oben in der Ecke,
in der imperativen Programmierung so,
dass es bedingte Anweisungen gibt und Schleifen.
Das ist etwas, was ihr möglicherweise auch schon gehört habt.
Da gibt es tatsächlich eine sehr schöne Darstellungsform.
Die ist zwar inzwischen eigentlich veraltet in gewisser Weise,
aber für imperative Programmierung immer noch sehr hilfreich.
Nämlich so, wie man so Anweisungen in einem Programm
auch grafisch darstellen kann. Das ist so aus Zeiten,
als die Rechnung noch nicht so grafische Displays hatten,
da sah das dann irgendwie so aus,
dass man dann so Kästchen zeichnete mit so Pfeilen dazwischen
Ich meine hier, wenn ich eine einfache Anweisung,
die gebe ich so in so einen eckigen Kasten an.
Und dann läuft hier der Kontrollfluss so durch,
kommt also oben rein und läuft unten weiter.
Also wenn wir uns mal den Text so vorstellen von oben nach unten.
Also wenn ich eine Sequenz habe von zwei Anweisungen,
dann wird das üblicherweise so dargestellt, kontrollfluss geht rein,
dann wird die Anweisung ausgeführt und dann geht es beim nächsten rein.
Und dann wird da der Kontrollfluss verlässt, auch diese Anweisung B wieder.
Das sind einfache Anweisungen in ihrer Sequenz. Dann gibt es
die Fallunterscheidung. Tatsächlich hier der Kontrollfluss geht rein,
hier ist so eine bedingte Verzweigung, wenn die Bedingung zutrifft,
wird hier Anweisung A ausgeführt, wenn die Bedingung nicht zutrifft,
wird hier einfach drumherum gegangen.
Hier wird sowas wieder zusammengeführt,
der Kontroll
Das gibt es auch mit einem Elz, also wenn das nicht zutrifft,
im Elzfall wird dann hier was anderes gemacht, A oder B.
Und die Wiederholung ist dann auch wieder relativ intuitiv.
Es gibt hier so einen Einstieg über den Kontrollfluss,
der fließt hier rein, die Bedingung wird geprüft, nehmen wir an,
sie trifft zu, dann geht der Kontrollfluss hier weiter,
die Anweisung A wird ausgeführt und dann hat man hier so eine richtig schöne Veranschaulichung des Begriffs Schleife.
Hier schleift jetzt sozusagen der Pfeil hoch, geht wieder hoch,
jetzt wird die Bedingung wiedergeprüft und irgendwann,
wenn die Bedingung nicht mehr zutrifft,
also es können jetzt hier mehrere Schleifen durch Steuern dafür stattfinden,
dann geht das hier raus und es ist zu Ende an dieser Stelle.
Gut, das ist nur erstmal so für die Intuition
ganz hilfreich
Es gibt dann auch noch sogenannte Strukturgramme, eine alternative Darstellungsform,
die vor allen Dingen auch aus den Zeiten stammt,
als man keine grafischen Displays hatte,
weil so Pfeile waren immer schwierig früher für Computerleute,
die zu zeichnen.
Deswegen sind das hier eben solche, auch solche Kästchen für einzelne Anweisungen.
Sequenzen werden einfach aneinander geklappt und dann hat man hier so
Verzweigungen entsprechend mit entweder A oder wenn es auch ein ALs gibt,
auch ein B.
Und hier so Schleifen eher so in dieser Form.
Diese Notation werden wir gleich nochmal so ein bisschen verwenden,
wenn wir auf Schleifen eingehen.
Okay, in der Geschichte der Programmiersprachen ist das
ziemlich viel diskutiert worden,
welche Kontrollstrukturen man braucht
Und es gibt da so theoretische Untersuchungen,
die zwei Menschen 1966 veröffentlicht haben, dass alle Algorithmen,
also alles das, was man so programmatisch beschreiben kann,
auch in Flussdiagrammen ausgedrückt werden kann.
Und dass das D-Diagramme sind. Also tatsächlich auch dich entsprechende Kontrollanweisungen implementierbar sind.
Also so ein D-Diagramm sieht man ja dann ja so aus,
entweder eine einfache Anweisung ist ein D-Diagramm oder A und B sind die Diagramme.
Nee, wenn auch A und B-Diagramme sind,
dann ist auch die Sequenz hier ein D-Diagramm FC,
Then A,
End und FC sind A,
LSB End und Wild CDU
A sind D-Diagramme
Damit kann man alles programmieren, was man braucht.
Also das ist tatsächlich nachgewiesen worden, dass man eigentlich nicht viel mehr braucht,
wenn man sich ein bisschen mit theoretischer Informatik beschäftigt,
was ja einige von euch noch tun werden.
Dann ist es einfach so, dass man eigentlich nicht viel mehr braucht,
als so diese Sequenz von Anweisungen und dann die bedingte Anweisung vergleicht mit Null und eine Waldschleife.
Das heißt, wenn man sich überlegt, wie die Geschichte damals war,
in den 60er Jahren gab es noch ganz viele Assembler-Sprachen,
die hatten auch noch einen,
wir hatten klassischerweise in dem Sprachschatz ein Go-To,
also in Assembler-Sprachen ist das ganz normal, dass man mit Sprunganweisungen arbeitet.
Entsprechend haben auch höhere Programmiersprachen fangst ein Go-To angeboten.
Auch C, zum Beispiel aus den 60er Jahren,
bietet noch ein Go-To. Und der gute Herr Deikstra,
der jetzt hier auch so ein bisschen zum ersten Mal auftaucht,
der hat in einem ziemlich berühmten Leserbrief,
also 68, an die Communications of the ACM.
Das ist so die Flaggschiff Postille der Vereinigung der ACM,
also der Association of Computing Machineary, die Standesgenossenschaft der Informatiker,
kann man mehr oder weniger sagen, weltweit.
Da hat er einen Leserbrief geschrieben, hat einfach gesagt,
das Go-To in Programmiersprachen sollte eigentlich rausgeschmissen werden
Go-To ist gefährlich, Go-To macht Programme unlesbar.
Es ist einfach zu primitiv und es lädt dazu ein,
Programme zu einem Durcheinander zu machen, zum Spaghettik-Knäuel.
Das hat witzigerweise eine relativ intensive Debatte entzündet. Das sind,
glaube ich, zehn Jahre lang, gab es Leserbriefe hin und her.
Also es gab Leute, die haben gesagt, oh,
wir brauchen unbedingt das Go-To, ohne Route geht es nicht.
Tatsächlich ist es inzwischen so, dass viele Programmiersprachen kein Go-To
mehr haben. Da war zum Beispiel auch kein Go-To.
In Java ist das Schlüsselwort Go-To reserviert. Witzigerweise,
die haben sich das sozusagen offen gehalten, die Tür.
Das heißt, ihr könnt kein Schlüsselwort,
ihr könnt keine lokale Variable mit dem Namen Go-To benutzen.
Aber dieses Schlüsselwort ist nur belegt, aber nicht irgendwie mit einer Semantik versehen.
Man kann nicht wirklich Go-Tos programmieren in Java.
Und man kann in Java einfach ziemlich viel programmieren.
Es ist also nachweislich so, dass man es nicht braucht,
aber wie gesagt, es gab ja eine ganz heftige Debatte dazu.
Der gute Herr Deichstra hat das eben halt auch nochmal sehr deutlich dann pointiert gesagt,
er became convince that the go to statement should be abolished
from all higher level programming languages.
Und das war, wie gesagt,
umstritten und heutzutage wird man das aber auch garantiert
so akzeptieren wollen
Der gute Herr Dikestra, ist ein sehr engagierter Mensch
in der Informatik gewesen, einer der ganz großen Namen,
also vergleichbar mit so einem Heisenberg oder Marie Curie in der Physik und Chemie.
Also wirklich ein ziemlich großer, hat ganz viele wichtige Dinge getan,
war aber auch ein sehr, wie soll man sagen,
ein sehr ungeduldiger Mensch.
Und er war sehr gerne formal gearbeitet. Er hat zum Beispiel gesagt,
dass es völliger Quatsch ist, Programme zu testen,
also das systematisch zu tun, weil man kann damit ja nur Fehler nachweisen,
aber nie ihre Abwesenheit
B weisen. Er wollte immer das Programm bewiesen werden.
Er hat die Mathematik sehr mathematisch,
die Informatik
sehr mathematisch gesehen
Der ist inzwischen gestorben. Also die meisten tollen Informatiker leben
ja noch. Das ist das Tolle an unserer Disziplin.
Aber Dixtar ist schon seit 2002 verstorben.
Gut. Letztendlich ist für uns wichtig zu wissen,
wenn wir vernünftig strukturiert programmieren, dann reichen uns Sequenz,
Auswahl und Wiederholung. So, Sequenz haben wir kennengelernt.
Auswahl sehen wir uns heute genauer ein und Wiederholungsanweisungen.
Sprachen mit solchen Kontrollstrukturen heißen auch strukturierte Sprachen. Und das
ist hier nochmal so ein bisschen angedeutet, diese Helix hier.
Also da sind es ja auch nur wenige Aminosäuren,
die da irgendwie zusammen das bilden, da braucht man nicht viele von.
Und dann kann man aber ziemlich mächtige Dinge bauen.
Und das ist eben halt genauso. Das ist sozusagen die Genetik,
die Genstruktur von strukturierter Programmierung, man braucht nur Sequenzauswahlwiederholung.
Okay, also insbesondere sollte man mal strukturiert Prämie sich auf diese Dinge beschränken.
Wir haben bisher auch schon gesehen, dazu kommt dann Prozeduren und abstrakte Datentypen,
den werden wir uns auch nochmal etwas ausführlicher widmen. Gut,
ein Begriff, noch bevor ich jetzt auf die wirklichen bedingten Anweisungen komme,
ist, auch noch ein Begriff,
es gibt sowas wie zusammengesetzte Anweisungen in der Programmierung,
zu Sprachen wie Allgäu oder Pascal war das zum Beispiel so,
wenn man irgendwie das zwischen Beginn und Endstehen hatte,
dann waren die Anweisungen dazwischen,
wurden dann als eine Anweisung aufgefasst.
Also mehrere Anweisungen zusammengebündelt, einfach mit so einem Knoll drumherum,
mit einem Faden drum gebunden. Dann hat man gesagt,
das ist jetzt, betrachte ich einfach mal als eine einzige Anweisung.
Das ist sehr nützlich. Wir kennen das aus Java eher mit
diesen geschweiften Klammern. Die kann man tatsächlich auch einfach verwenden,
um Dinge zu klammern und dann zu einer einzigen Einheit zu machen.
In Java sind diese Dinger üblicherweise Blöcke. Das heißt,
das sind zusammengesetzte Anweisungen, wo mehrere Anweisungen zusammengefasst sind,
in denen aber auch lokale Variablen deklariert werden können.
Kale Variablen kennt ihr schon aus Prozeduren
Blöcke bilden in eigenen Sichtbarkeitsbereich. Da komme ich heute später
nochmal zu. Und auch ein Blog ist syntaktisch geklammert,
in Java mit den geschweiften Klammern.
Klar, also hier habe ich es ja schon gesagt.
Allgäu 60 war die erste Sprache mit Blöcken, also schon lange her.
Und es gab dann eine ganze Reihe von Programmiersprachen,
die waren Blog strukturiert. Zum Beispiel Pascal,
da könnte man tatsächlich auch innerhalb von Prozeduren, Prozeduren schachteln.
Das könnt ihr in Java nicht. Ihr könnt in Java
keine Methoden in Methoden schachteln. Geht einfach nicht.
Das haben die tatsächlich explizit für Java nicht gewollt.
Macht die Sprache auch deutlich einfacher
Okay, hier ist nochmal die Syntax dazu, wie das tatsächlich aussieht.
Man sieht hier wieder diese Gemeinheit mit Literale,
also hier terminale Symbole sind hier die blauen Symbole,
also die geschweiften Klammern,
als Elemente in der Sprache und dann als Metasymbole hier diese geschweiften Klammern,
die sagen, naja,
es können halt beliebig viele Blockstatements in einem Block stehen und ein Blockstatement kann entweder sein,
local variable declaration statement, also ich kann eine lokale Variable deklarieren,
oder es kann eben eine Anweisung sein.
Und dann wisst ihr ja, was es so für Anweisungen gibt. Gut,
wir wollen jetzt jetzt mal die Pfandunterscheidung etwas genauer ansehen,
ich will das gar nicht zu sehr vertiefen,
es ist so, dass ihr die ja schon benutzt habt.
In den Übungen musstet ihr ja schon
das IF benutzen
Habe auch immer mal wieder so in den letzten Jahren Beschwerden,
dass wir das IF benutzen lassen,
obwohl wir es hier in der Vorlesung noch gar nicht vorgeschlagen haben.
Ich stelle es jetzt erst vor, ihr musstet das schon benutzen.
Meistens stellen wir fest, dass das gar nicht so schwierig ist.
Also das ist nicht so eine Überforderung. Klar müssen wir dann so
ein bisschen helfen. Wir sind ja zum Glück dabei.
Aber es ist ja eigentlich relativ einfach. Ich schreibe
ein IF hin, dann muss ich in Runden klammern.
Die müssen da immer stehen, eine Bedingung angeben.
Diese Bedingung wird ausgewertet. Und wenn die Bedingung zutrifft,
dann wird eine Anweisung ausgeführt. Eventuell kann man noch einen Elster haben,
dann wird eine andere Anweisung ausgeführt, wenn die Bedingung nicht zutrifft.
Ganz wichtig ist, dass diese Ausdruck hier einen Bullshit-Ausdruck sein muss.
Es muss tatsächlich ein Wahrheitswert ergeben. So,
und Wenn wir uns das jetzt hier angucken,
dann sehen wir hier so ein Beispiel und das ist eigentlich ein relativ blödes Beispiel.
Ich werde jetzt versuchen zu erläutern, warum ich das Blöde finde.
Ich weiß nicht, ob es euch schon aufgefallen ist,
dass hier ja, wir haben ja so eigentlich immer gern darauf hingewiesen,
schreibt bitte die geschweiften Klammern hin.
Man muss es nicht machen. Man kann das tatsächlich weglassen.
In Java ist das hier auch eine gültige, bedingte Anweisung.
If a, kleiner B, dann ist Minimum gleich A
, Elster Minimum ist gleich B. Kann man so hinschreiben.
Das ist aber nicht so doll,
und das will ich mal so ein bisschen zeigen an einem konkreten Beispiel,
ich mache mal BlueJ auf, Papier eine klasse Textanalyse.
Die ist relativ einfach. Die hat nur eine einzige Methode
. Und diese Methode heißt, ist Frage. Ermittelt,
ob sich beim übergebenen Text um eine Frage handelt.
Eine Frage erkennt man am abschließenden Fragezeichen. Also eine ähnliche
Klasse kriegt ihr, glaube ich, auch in den Übungen.
Bin mir nicht ganz sicher. So,
und dann kommt hier als Parameter, der zu analysierende Text.
Und da steht extra der Hinweis, das sollte mindestens ein Zeichen haben.
Also keine leere Zeichenkette übergeben. So, und diese Methode liefert True,
wenn es sich um eine Frage handelt, falls sonst.
Also, wenn da am Ende ein Fragezeichen steht.
Das ist relativ einfach implementiert. Man kann das hier sehen
Es wird ein Text als Parameter übergeben,
dann wird zuerst hier so eine lokale Variable Bullien deklariert,
ist Frage und wird auch Falls initialisiert.
Dann wird die Länge dieses Textes ermittelt, das ist etwas,
was ihr erst in der nächsten Woche lernt, wie man mit Strings umgeht,
könnt ihr euch schon mal hier so ein bisschen angucken.
Also ich kann mir die Länge der Zeichenkette geben lassen,
dann kann ich sagen, die letzte Position in der Zeichenkette,
das ist die Länge minus eins,
also wenn die Zeichenkette ein Zeichen lang ist,
dann ist die Länge eins und dann ist die Position null,
weil die Zeichen von null Beginn indiziert werden.
Das ist so, gucken wir nächste Woche nochmal genauer drauf.
Und dann ist hier einfach gesagt, naja,
das letzte Zeichen, das muss ein Cha sein,
das ist Text Char-Ed,
also eine Operation auf so einer Zeichenkette,
gib mir doch mal das Zeichen an der letzten Position
Steht hier, If letztes Zeichen gleich gleich. Fragezeichen,
dann ist Frage gleich True. Und wir haben ja gesagt,
wir nehmen erst mal an, es ist kein Fragezeichen.
Und wenn da eines ist, dann ist es True.
Also das sieht ganz einfach aus, ist auch ganz einfach.
Ich kann hier mal so ein Exemplar mehr erzeugen von dieser Textanalyse
und stellen hier mal die Frage, sag irgendwie sowas wie,
hallo, hallo, hallo, hallo.
Das ist sicherlich keine Frage mit einem Ausrufezeichen. Da sollte
ich jetzt hoffentlich False rauskommen, kommt auch False raus.
Und wenn ich jetzt hier irgendwie sage,
hallo mit einem Fragezeichen, dann kommt da True raus.
Keine Hexenkunst. Gut
Jetzt stelle ich irgendwie fest, ich würde das gerne erweitern.
Ich habe jetzt, wie gesagt, diese Textanalyse ist ja
super klasse. Total hilfreich. Finde ich klasse.
Ich zähle jetzt mal, wie viele Fragen gestellt wurden.
Also sozusagen als Teil einer Software ist das eine Textanalyse-Objekt.
Und ich habe also irgendwie in einem Kontext,
wo Text verarbeitet wird, wird das Ding immer wieder benutzt.
Und der soll irgendwie aber auch registrieren,
wie oft jetzt tatsächlich eine Frage dabei war.
Also mache ich hier sowas wie Private in Fragezähler.
Den führe ich jetzt mal hier so ein. Dieser Fragezähler,
vernünftigerweise müssten wir jetzt einen Einen Konstruktor bauen,
der das Ding initialisiert, das lasse ich jetzt weg,
um das ein bisschen einfacher zu machen.
So, jetzt möchte ich eigentlich an dieser Stelle,
wenn tatsächlich hier das letzte Zeichen, ein Fragezeichen ist,
dann möchte ich, dass dieser Fragezähler um eins erhöht wird.
Also schreibe ich ihn einfach dazu. Frage unterstrich natürlich,
Fragezähler plus plus. Machen wir lieber plus plus Fragezähler.
Ihr wisst ja, das ist eigentlich schöner.
So, okay. Das kann ich ja erstmal
so hinschreiben
Und das macht hoffentlich auch immer was, ja,
geht, lässt sich übersetzen. Prima, ja,
ich kann das hier mal ausprobieren, mache also wieder meine
Textanalyse und kann ja hier mal mir das anzeigen lassen.
Ich sehe also hier, da ist tatsächlich jetzt dieser Fragezähler.
Und jetzt sage ich hier, ist Frage.
Und zuerst nehme ich mal so einen hier Frage,
ja, es ist eine Frage, True.
Und tatsächlich, der Fragezähler wurde erhöht. Prima, prima.
Ich teste das nochmal eben, auch mit einem anderen Beispiel,
wenn ihr mal was, was keine Frage ist.
Und da kommt Falls zurück. Wunderbar. Ups,
aber er hat diesen Fragezähler erhöht. Ich wollte eigentlich
nur den Fragezähler erhöhen, wenn das eine Frage ist
Gut, ich weiß nicht, ob ihr es jetzt
so schnell gesehen habt. Ich habe natürlich einen Fehler gemacht
und das Schöne ist am Blue Jack ist ja,
es zeigt mir das ja schon, wo der Fehler ist.
Ich habe nämlich jetzt hier einfach das dazu geschrieben und mit der Einrückung irgendwie angedeutet,
naja, das sollen auch geschehen, wenn das IF zutrifft.
Tatsächlich ist es aber so, es wird dann nach,
wenn die Bedingungen zutrifft, mit einer Anweisung ausgeführt.
Das heißt, die eine Anweisung ist diese und durch die
Bloghervorhebung im Blue Jack sieht man das hier auch,
dass das hier der Blog ist, der dazugehört.
Und das gehört schon gar nicht mehr zum,
das wird also auf jeden Fall, wird der Fragezähler erhöht.
Das ist nicht das, was wir wollten,
sondern was wir eigentlich wollten, ist,
das hier,
das ist die vernünftige Umsetzung
Dass ich tatsächlich hier jetzt daraus eine zusammengesetzte Anweisung mache,
einen Blog. Und dann wird das auch wirklich beides
nur ausgeführt, wenn es eine Frage ist.
So wird es also auch gehen. Wir brauchen das jetzt
nicht auszuprobieren. Ich wollte das einfach nur mal demonstrieren,
dass man relativ schnell Fehler macht, wenn man diese Klammern weglässt.
Hier ist ein weiteres Beispiel. Hier haben wir ein Code-Fragment,
if Summ gleich null, dann if Count gleich null,
dann Result gleich 1, Else Result gleich null.
So, nehmen wir mal an,
am Anfang ist Summen gleich null, Count ist 1,
Result ist 2. Was kommt da raus
Wer sagt mal, wer schmeißt mir mal
irgendeinen Wert an den Kopf, was da wohl rauskommt?
Okay, da. Da sagt jemand null, sagt dir mal was anderes?
Da sagt jemand zwei, okay, ihr seht,
es ist nicht so ganz eindeutig hier an der Stelle.
Nicht so ganz offensichtlich. Eine Antwort war richtig. Es
ist tatsächlich die Null. Und zwar ist das Problem,
wenn ihr euch das mal anguckt,
hier ist die Einrückung so,
suggeriert, als wenn sich dieses Ales auf dieses If bezieht
Es ist aber tatsächlich so, dass es sich tatsächlich auf dieses If bezieht.
Das heißt also, wenn Summ gleich Null ist,
dann wird geprüft, ob Count gleich Null ist, ist es nicht.
Also ein Elsfall mit Resard of Null. Das null ist
die richtige Antwort. Das liegt nur daran, dass das
hier einmal komisch eingerückt ist. Zum anderen aber auch,
weil es dieses Konzept, dieses Dengling Els gibt,
das heißt, dass da oben ist nicht gut eingerückt.
Es ist einfach so, es wird immer,
und das ist in Java so definiert, bei geschachtelten Ifs muss man aufpassen,
ein Elszweig bezieht sich immer auf die letzte If-Anweisung ohne Elszweig.
Also auch die letzte mögliche, offene IF-Anweise.
Und das ist ein bisschen komplizierter. Und auch da wieder,
wenn ihr explizit immer die Klammern setzt, ja,
wenn ihr sowas schreibt, hier if summen gleich null,
dann immer diese Klammern setzt.
Und auch wenn da nur eine Anweisung steht,
immer die Klammern setzt, dann ist es einfach komplett eindeutig.
Also mindestens zwei gute Argumente, warum es schlau ist,
diese Klammern immer hinzusetzen, auch wenn sie technisch nicht notwendig sind,
ist es schlau aus softwaretechnischer Sicht zu sagen, wir schreiben sie immer hin.
Deswegen haben wir sie in den Quertext-Konventionen auch so aufgenommen.
Das ist also hier Punkt 4,7 der Quertext-Konvention.
Das ist das, was wir da sagen,
schreibt es
Schreibt immer Blog-Klammern bei IF. Das ist,
wie gesagt, auch robuster Veränderung,
wenn man dann weitere Anweisungen ausführen will im zutreffenden Falle,
dann geht das eben halt sehr leistend.
Es müsste die Klammern immer wieder wegnehmen und so weiter.
Soweit zum IF, zur bedingten Anweisung. Dann kommen wir zum Switch.
Das ist eine Mehrwegverzweigung. Ich sag mal, ein erstes Beispiel.
Ich möchte abhängig auf der Tastatur gedrückten Taste in einem Spiel
eine von mehreren Prozeduren aufrufen oder einen von mehreren Methoden.
Also ich kann das dann in Java relativ gut so machen.
Ich habe also irgendwie gedrückte Taste. Das ist vermutlich eine
Variable vom Typ Char, also eine Taste, die gerückt wird,
wird irgendwie abgebildet auf einen Char. So, switchgedrückte Taste,
da wird also ein Switch geschrieben, abhängig von dem,
wie diese Variable hier belegt ist oder welchen Wert dieser Ausdruck hat.
Partie geguckt, KSA, wenn es ein A ist,
dann Bewegespieler nach links, Break, Case D,
Bewegespieler nach rechts, Break und so weiter.
Also man sieht hier, abhängig von diesem Wert,
wird dann tatsächlich irgendwo hier an einem dieser Case-Label gesprungen,
dann wird da das ausgeführt,
was da steht und dann besucht das Break,
das hier abgebrochen wird
Sozusagen dieses Switch hier verlassen wird. Also so Spiele könnt ihr
euch ja vorstellen, das ist so A, D,
W, S, also irgendwie so sind so Tassen,
die man üblicherweise bei Spielen mit Tastatursteuerung irgendwie ganz gerne benutzt.
Natürlich ganz wichtig, immer mit der Lehrtaste immer schön und ein Feuern.
Ja, ganz spannend. Als Case-Label verwenden wir ausschließlich Konstanten,
häufig vom Typ Int oder Char. Also hier sieht man jetzt,
dass es vom Typ Char, es gibt auch solche mit Int,
es gibt auch noch mehr Möglichkeiten, gucken wir uns noch an.
Aber das sind Konstanten, das müssen nicht Literale sein.
Also hier zum Beispiel T steht jetzt ein Literal,
A, D und W,
also als Charlotteral
Wir könnten auch Char-Ausdrücke stehen, aber es müssen konstante Ausdrücke sein.
Okay, das ist also hier so ein Case-Label.
Gut, was passiert jetzt, wenn die Break-Anweisung hier fehlt?
Weißt du jemand, was dann passiert? Also wenn es
immer mal an diese Break-Anweisung würde da nicht stehen.
Wo der A aus, danach zu gehen, weitergehen. Okay,
er sagt, wenn jetzt tatsächlich dann A zutreffen würde,
dann würde hierhin verzweigt werden,
dann würde der Spieler nach links bewegt werden,
das Break steht nicht da, dann würde der Kontrollfluss tatsächlich einfach weiterlaufen.
Dass wir das also hier zu Bewegespieler nach rechts,
das heißt, wir hatten den Spieler nach links und gleich
wieder nach rechts bewegt,
das wäre nicht
sehr schlau
Und dann würde er erst das Break Ash passieren und
dann würde sozusagen hier diese Bedingungen abgebrochen werden.
Das ist etwas, was, was man wissen muss,
was sehr zentral ist bei diesem Break in Java,
dass man mit dem Break dieses Konstrukt hier verlassen kann.
Weiteres Beispiel? Hier, Leas Buchstabe von Tastatur.
Ich lese ein Zeichen von Tastatur. Also ich möchte für eine
auf der Tastatur gedreht sein, es soll ausgegeben werden,
ob sie einen Vokal liefert oder nicht.
Also ich kann hier auf der Tastatur irgendwas eintippen und das
wird irgendwie eingelesen und dann wird hier ein Switch gemacht,
Switch über diesen Buchstaben, der eingetippt wurde,
wenn es ein A-E und so weiter ist,
dann ist Vokal
gleich true
Sieht man hier, hier ist überhaupt kein einziges Break drin.
Das heißt, die ganzen Case-Labels sind alle für den Fall hier aufgeführt.
Das sind alles Vokale, also wird dann hier ein Vokal auf True gesetzt.
Und dann sieht man hier so ein bisschen lustig,
das System Outprint-Buchstabe ist. Und dann if not is vokal,
dann kein Vokal oder ein Vokal, ja.
Sehr schön. Was passiert jetzt, wenn zwei Case-Label denselben Wert haben?
Also hier sieht man ja, das sind alles verschiedene Case-Label.
Was ist, wenn da zwei den gleichen Wert haben?
Was passiert da? Lässt sich das gar nicht übersetzen oder
springt ja beide an oder was ist da so die Vermutung?
Hat da jemand
eine Idee
Ja, ich lasse jetzt mal mal vorziehen, was das für wird.
Er sagt, er springt das an, was er zuerst findet.
Okay, gibt es andere Vorschläge? Du könntest ja mal probieren
, ich habe es zufällig dabei. Da ist es.
Bulien ist vokal, ja. Nehmen wir mal an,
ich würde jetzt hier aus dem UNA machen.
Dann hätte ich ja diesen Case-Label einmal da oben und einmal da unten,
habe ich aus Versehen nicht vertippt hier unten, ja.
Das Witzige ist, er übersetzt das gar nicht. Duplicit-Case-Label,
das Schöne ist ja, wir haben festgestellt, diese Label müssen konstanten sein.
Der Compiler kann deswegen zur Übersetzungszeit, also während er das Problem besetzt,
sehen, da sind zwei Label gleich und das ist sinnlos.
Das ist dann nicht eindeutig. Er weiß nicht,
wo er hinspringen soll, es ist Quatsch,
da irgendwie festzulegen, er springt zum ersten oder zum zweiten,
das ist einfach Unfug und der Compiler kann das ja melden und das passiert auch genau hier.
Das heißt also, wenn ich das jetzt hier wieder rückgängig
mache, dann geht es auch wieder. Okay,
dann noch ein Beispiel für die Switch-Anweisung,
für einen Monat im Jahr hat er den Benutzer durch eine ganze Zahl benennen soll,
den der Benutzer durch eine ganze Zeit benennen soll,
soll ausgegeben werden, wie viele Tage er hat.
Das sieht irgendwie ganz schön aus, es ist tatsächlich auch so ein Beispiel,
wo man sieht, dass es nützlich ist,
so mehrere Case-Label zusammenzufassen und dann aber auch einen Break mit drin hat.
Also hier ließ Monatszahl vom Benutzer und dann irgendwie hier Tage,
dann wird hier der Switch gemacht über diesen Monat,
der irgendwie von 1 bis 12 wahrscheinlich benennbar ist. So,
und dann 1, 3, 5, 7,
das sind genau die Monate,
die 31 Tage haben und dann wird hier ein Break gemacht und hier entsprechend für 4,
6, 9, das sind die und 11,
das sind die mit 30 Tagen, also zum Beispiel hier elf,
ja, das ist ja November,
hat 30 Tage und 5. Mai hat 31 Tage,
das passt.
Da gibt es auch so manche, die haben 28 Tage.
Klar, Schaltjahr ist hier jetzt nicht mit drin,
das ist einfach nur erstmal zur Veranschaulichung dieser Switch-Anweisung.
Das ist jetzt nicht unbedingt das Richtige,
die richtige Berechnungsstruktur hier für für alle Monate aller Jahre.
Links angedeutet, ein Beispiel für den Kontrollschluss.
Also wenn wir als Benutzer tatsächlich jetzt eine 7 eingegeben haben,
dann ist das so, dass hier der Kontrollfluss durchgeht,
dann wird dieses Switch, dieser Ausdruck hier ausgewertet,
abhängig von diesem Wert, wird tatsächlich dieser Label angesprungen.
Dann geht es da runter bis zu dieser Anweisung,
dann kommt da ein Break und dann geht der Kontrollfluss hier runter und dann geht es da weiter.
Also der Monat sowieso hat dann irgendwas. Okay,
was passiert denn jetzt, wenn keiner der Fälle zutrifft und es fehlt dir Defaultanweisung?
Was machen wir denn dann? Gibt es einen Fehler
oder ist das kein Problem?
Was meint ihr
Also ich habe jetzt hier, hier ist ja so default,
da wird jetzt irgendwie gesagt, wenn keiner diese Zahlen angegeben würde,
wenn der mindestens irgendeine falsche Zahl angibt,
dann gibt man halt irgendwas Negatives aus.
Ich meine, dieses Default würde da nicht stehen.
Was wäre denn dann, wenn dann eine andere Zahl angegeben wird?
Ja, er sagt, dann überspringt er das Switch und das ist auch genau richtig.
Das ist so ähnlich wie bei einem IF, wo die
Bedingungen nicht zutrifft. Hat halt nichts gemacht. Diese Switch-Fälle,
die da aufgeführt sind, werden ausgeführt, wenn sie zutreffen.
Ansonsten eben nichts. Also eigentlich gar kein Problem. Und
hier haben wir noch ein Beispiel für die Switch-Anweisung,
die nochmal ganz schön ist, um zu zeigen,
wie das ist,
wenn man da so durchläuft
Hier wird also eine Zehnerpotenz von Benutzer eingelesen, eine Zahl.
Und dann wird hier ein Exponent auf Null gesetzt.
Und abhängig von der Zahl, die eingelesen wird, wird hier verzweigt.
Wenn es also eine von diesen Zahlen ist hier,
dann wird hier irgendwas mit dem Exponent gemacht.
Im Defaultfall ist hier einfach gesagt, das System Outprint-Zahl ist
keine Zehnerpotenz. Also der Benutzer kann irgendwelche Zahlen eingeben.
Und wenn es eine Zehnerpotenz ist, wird gesagt,
das ist dann zehn hoch und dann tatsächlich der Exponent.
Also zum Beispiel zehn ist ja zehn noch eins,
eins ist zehn noch null, 100 ist zehn noch zwei und so weiter.
Man sieht hier ganz schön, dass es einfach so ist,
dass tatsächlich, wenn er jetzt hier oben reinspringt,
sondern wir hier bei der, bei der 100.000,
dann wird hier der Exponent 1, 2, 3,
4, 5 mal erhöht.
Und dann wird hier ausgegeben, 100.000 ist gleich 10
hoch 5. Also das ist tatsächlich etwas, wo man sieht,
dass diese Möglichkeit des Durchfallens, bei dem Switch durchaus nützlich ist.
Okay, ganz allgemein jetzt nochmal so das allgemeine Schema,
Switch, eine Expression, das muss ein Typ sein,
der da zugelassen ist.
Es dürfen Char und Inter stehen,
es dürfen auch über die Elemente eines Aufzählungstyps geswitcht werden,
die kennt ihr noch nicht,
die werdet ihr
vielleicht noch kennenlernen
Also man kann sowas haben wie ein Aufzählungstyp, Farbe mit den Elementen rot-grün-blau.
Und dann kann ich tatsächlich sagen, Switch, Farbvariable,
Case rot, Case blau, Case grün.
Das geht. Und Satjava 1,7, das ist ja die neueste Version,
die wir jetzt hier auch auf den Laborrechnern installiert haben,
kann man tatsächlich auch über Strings switchen.
Das ist also relativ neu. Werden wir uns aber wahrscheinlich
hier nicht so mehr ansehen. Gut, Auswahlanweisung ist ein
Mehrwegverzweigung. Aufgrund eines Ausdrucks können mehrere Fälle unterschieden werden.
Und wenn wir uns das jetzt mal vergleichen mit dem IF,
ist es jetzt so, Es können tatsächlich mehrere Ausdruckstypen, die Auswahl kontrollieren.
Also hier kann Char stehen, ein String,
ein Aufzählungstyp, ein Int, während bei dem IF,
kann da ja nur eine Boogleshow-Ausdruck stehen.
Bei einem IF gibt es ja nur zwei Fälle, war oder falsch.
Und das können eben halt tatsächlich mehrere Fälle dastehen.
Das ist also tatsächlich auch anders als beim,
also es können tatsächlich auch eine oder mehrere Fälle ausgewählt werden.
Ihr könnt beim IF, wenn ihr ein IF,
ein Elz habt, dann könnt ihr nicht dafür sorgen,
dass beides ausgeführt wird.
Das geht beim IF, das IF ist nicht so flexibel.
Also wenn ihr tatsächlich so diesen Fall haben wollt,
dass beides gehen könnte, dann solltet ihr einen Switch nehmen.
Das heißt, beides tatsächlich auch mal ausgeführt wird
Statt eines eindeutigen Elsfalles gibt es einen Standardfall für alle nicht explizit benannten Fälle,
auch das ist wie ganz, ganz praktisch.
Also eine ziemlich mächtige Geschichte und etwas, was man sich durchaus mal ansehen kann.
Hier ist nochmal die Jabba Level 1 Syntax, ergänzt um das Switch. Hier ganz einfach ein Statement,
kann seinen Blog oder ein If oder ein Switch,
also dann auch hier Switch, Runde,
Klammer Expression und dann Switch Statement Blog Group,
davon beliebig viele und dann hier Switch Label und das sind eben halt Switch Label,
kann so ein Case Constant Expression sein oder Default.
Ja, das ist Das, was ihr erstmal so sehen solltet.
Nochmal zusammengefasst, es werden alle nach einem passenden Label folgenden Anweisungen durchlaufen.
Auch wenn der nächste Label oder der Default Label erreicht wird.
Also es wird alles wirklich bis zum nächsten Break durchlaufen.
Man kann also mit dem Break dieses Verlassen veranlassen.
Alternativ könnt ihr natürlich auch mit einem Return einen Switch verlassen.
Klar, dann verlasst ihr die ganze Methode. Oder mit einem Throw
, das habt ihr ja auch schon so informell kennengelernt.
Damit kann man eine Acception werfen. Das ist momentan
für uns die Möglichkeit, ein Programm abzubrechen.
Und in einer Switch-Anweisung darf jeder Case Label einmal vorkommen
Und wenn kein Case-Label zutrifft und kein Default-Label-Fund ist,
wird das gesamte Switch übersprungen.
Hier ist nochmal so ein Negativbeispiel, Switch E.
Und dann im Case 1 ist zum Outprint and 1,
Case 2, 2 und Default viele.
Da hat vermutlich jemand geglaubt, dass da implizit ein Break stattfindet,
weil wenn nämlich jetzt tatsächlich hier das E mit 1 belegt ist,
dann kommt da irgendwie raus 1, 2 viele.
Eigentlich sollte vielleicht nur eins rauskommen. Vielleicht wollte der Mensch das
auch so, aber das ist vermutlich ein Negativbeispiel an dieser Stelle.
Gut, das ist das, was wir da zum IF
und zum Switch haben. Ich bin etwas schnell gewesen heute,
deswegen könnten wir jetzt mal so ein bisschen Storesi mal wieder machen.
Juhu. Ich schalte das mal weg hier.
Welchen Wert hält die Variable X nahe Ausführung des folgenden Java-Quelltextes?
Hier ist der Quelltext angegeben und ich starte hier schon mal
die Abstimmung und dann könnt ihr euch das nochmal in Ruhe angucken.
Also könnt ihr das lesen,
kann man das erkennen.
Ich vermute schon
Das sind so klassische Aufgaben, die wir auch gerne in
der Klausur stellen. Ja. Gut, jetzt,
ja, die letzten entscheiden sich,
so bei 150 mache ich mal Schluss, mit 150 nachher erreichen.
Ja, das schaffen wir noch. Gut,
schauen wir mal, was so die Meinung ist an
dieser Stelle
Erstmal die Verteilung. Ziemlich viele sagen, es ist sechs.
Einige sagen, es ist zwei und ein paar sagen auch,
es ist vier oder sieben. Okay. Versuchen wir das
mal aufzuklären. Ah, das ist schön. Ist natürlich jetzt auch so,
ich habe ja jetzt die Frage direkt nach danach gestellt,
nachdem ich es gerade erzählt habe.
Wer weiß, ob das dann auch noch gilt,
wenn ihr solche Fragen dann in ein paar Monaten wiedergestellt bekommt.
Aber das ist sehr, sehr erfreulich. Also an dieser Stelle war das ja relativ eindeutig,
dass tatsächlich hier tatsächlich das Xen mit null belegt wird,
dann wird das I hier abhängig, dann wird verzweigt,
also wird x gleich x plus 2 ausgeführt,
aber es fehlt das Break,
also wird x auch nochmal x plus 4 berechnet,
also haben wir sechs hin als richtige Antwort.
Gut, sind noch Fragen jetzt zum IF und zum Switch,
da ist eine Frage. Warum benutzt man bei dem Switch
keinen Blog? Du meinst bei dem Case, bei den Case-Labeln,
das kann man machen, man muss es aber nicht.
Das ist, von der Syntax her ist das ziemlich hässlich,
dieses Case-Konstrukt Switch Case
Man könnte das vielleicht, könnte man das, es macht tatsächlich
keinen Unterschied, weil tatsächlich ja das einfach sequenziell durchlaufen wird.
Das ist ja nicht so im Sinne wie bei dem IF,
dass man da irgendwie dann jetzt aufpassen muss,
wie viel gehört dazu zu dem Case, sondern das wird ja einfach durchlaufen.
Ja. Und wer jetzt Case ist,
das gleiche Case, was man jetzt in File hört.
Ob man das einrückt, ich würde sagen, ja,
auf den meisten Folien ist es hier, glaube ich,
auch weit eingerückt.
Hier ist es eher nicht eingerückt, okay,
hier ist es auch nicht eingerückt.
Ich würde es eher einrücken. Ich würde es eher einrücken.
Sonst noch Fragen zur,
ja,
da oben
Haben und heute Beispiele zu haben. Paulus ist dann stark
zu bauen. Gibt gleich das zweite,
die vielleicht eins genommen wird, weil du denkst, ah,
was ich gesagt habe, jedes Gleichnis ist weiter mitgenommen worden.
Ah, okay, ganz gemeine Frage. Er sagt,
was wäre gewesen, wenn jetzt hier I am Anfang eins
gewesen wäre und man würde jetzt hier hinspringen und dann würde
an dieser Stelle jetzt I verändert werden.
Ob das sich noch auswirken würde? Nein,
es ist tatsächlich so, das wird hier oben einmal ausgewettet,
der Ausdruck und abhängig davon wird hier einmal reingesprungen.
Und was man danach mit der Variablen macht,
ist vollkommen wurscht.
Hat keinen Einfluss mehr
Sonst noch Fragen zum Switch. Das ist nicht der Fall.
Fein. Dann machen wir doch jetzt mal eben fünf Minuten Pause.
Ja, zweite Hälfte heute. Ich habe vorhin auch eingangs gesagt,
ich werde mich mit Schleifen hier beschäftigen,
aber wir werden auch noch über Laufzeit und Übersetzungszeit reden heute.
Das habe ich ganz vergessen. Das sind also auch noch
so ein paar Folien, die dazu noch kommen.
Jetzt geht es erstmal um Schleifen. Also, erstmal vielleicht
ein paar einführende Beispiele. Wir wollen wiederholt ein Passwort einlesen,
solange die Eingabe noch nicht korrekt ist.
Also man stellt sich vor, es ist irgendwie so
ein String-Passwort-Deklariert
Eine Schleife, das ist eine Du-Wile-Schleife, aha.
Also er wird zuerst hier ausgegeben Passwort, dann wird
ein Passwort eingelesen, ja, irgendwie Teile vom Benutzer.
Und dann, solange, das soll er so lange machen,
bis, er soll es so lange machen,
solange dieses Passwort nicht gleich ist zu dem gespeicherten Passwort.
Also irgendwo gibt es anscheinend da so eine Exemplarvaria,
wie das Passwort hält. Das können wir uns mal
live angucken. Da habe ich hier ein Projekt dazu,
Schleifendreher, kann ich mir hier so ein Schleifendreher mal erzeugen.
Hier ist also tatsächlich dann dieser Code für lange Passwort Also System Outprint-Passwort,
liest Zeile von Benutzer und dann so lange Passwort, ungleich dem einzugebenden Passwort.
Und dann irgendwann, da steht hier, du darfst eintreten. Ja,
wenn ich das jetzt aufrufe, also dann kann ich tatsächlich hier,
na, wo ist das für lange Passwort,
dann sage ich irgendwie, hallo, das ist es nicht,
Test, nee, ist es auch nicht, Zimt,
Stern, Zimt, Stern, ich darf eintreten.
Gut, also sehr weihnachtliches Beispiel. Das ist
ein Beispiel für Eine Schleife. Man sieht hier,
es wird zuerst etwas gemacht und dann wird geprüft,
ob das vielleicht noch mal gemacht werden muss.
Oder wir möchten alle druckbaren Zeichen des Aski-Zeichensatzes jeweils mit
ihrer Originalzahl auf der Konsole ausgeben lassen.
Also, wir gehen einfach, wir haben eine Variable,
Chart C, die wird initialisiert mit 32.
Das ist sozusagen die Originalzahl des ersten druckbaren Zeichens, das ist Leerzeichen.
Und dann bis 126, das sind so die druckbaren Zeichen.
Und dann wird hier tatsächlich irgendwie dieses C erhöht und wie
wird das genau funktioniert, gucken wir uns gleich genauer an.
Das ist eine sogenannte Vorschleife hier. Dann wird hier irgendwie
bekommt diesen Wert von dem Charakter zugewiesen und dann können wir
dir ausgegeben, I ist das IT-Aski-Zeichen ist dieses.
Auch das haben wir hier im Quelltext vorliegen.
Das heißt, ich habe hier irgendwo drücke alle Asparen,
drückbare Aski-Zeichen, hier tatsächlich genauso wie auf der Folie.
Das kann ich auch mal eben ausführen, also nehme ich mal hier diesen Schleifendreher,
sage, drücke und dann kommt da sowas raus.
Das sieht jetzt hier so ein bisschen durchaus,
das geht nur bis zu 80, das ist wieder so ein Problem.
Ich muss also hier sagen,
unbegrenzter Textspeicher und ich würde auch gerne sagen, hier,
Konsole löschen beim Methodenaufruf, so, also mir das jetzt nochmal mache,
Dann sollte hier jetzt auch alles zu finden sein,
dann sieht man hier tatsächlich jetzt.
Es geht bei 32 los,
hier ist das Leerzeichen und dann kommen die ganzen Zeichen,
das Aski-Zeichensatzes, sozusagen mit ihrer Originalzahl.
Das ist erstmal so keine Hexenkunst, das sind aber zwei sehr konkrete Beispiele,
um mal so verschiedene Formen von Schleifen in Java zu zeigen.
Warum Schleifen angucken? Klar, es ist eben halt etwas,
was Computer eigentlich erst so richtig interessant macht,
Dinge wiederholt ausführen zu lassen.
Also das ist, da sind Computer ziemlich gut drin,
die sind verdammt schnell,
ziemlich blöd,
aber auch verdammt schnell dabei
Und ja, das finde ich auch ein sehr schönes Zitat.
Der normale Mensch hat heute mehr Rechenpower zu Hause
als ganz Houston, als es ein Apollo-Problem hatte.
Das ist, heute würde man wahrscheinlich sogar sagen,
das hat er 2008 gesagt, der gute Gunther Dück.
Heute hat der Mensch mehr Rechenpower in der Tasche, also mit seinem Smartphone.
Die sind damals zum Mond geflogen mit diesem Rechnern. Okay,
also Wiederholungsanweisungen ermöglichen das Anweisungen keinmal, einmal oder mehrfach ausgeführt werden.
Das ist erstmal ganz einfach. Allerdings muss man sich
dann in limperativen Sprachen schon sehr genau angucken,
wie denn die Mechanismen in der Sprache funktionieren, um das auszuführen.
Also wie ist die Wiederholungsanweisung aufgebaut
Wie wird die Wiederholung überhaupt kontrolliert? Und wo steht dieser Kontrollmechanismus innerhalb der Schleife?
Das ist jetzt auch wieder für Programmieranfänger ganz wichtig,
weil das haben wir einfach auch die letzten Jahre mal festgestellt.
Es ist nicht so intuitiv, dass man das so hinschreibt,
wie man das so hinschreibt. Es ist natürlich viel einfacher,
wenn ich sagen würde, ich möchte etwas viermal ausführen,
dann schreibe ich die Anweisung einfach viermal hin.
So kann man natürlich auch etwas wiederholt ausführen lassen.
Ist nur nicht sehr flexibel, wenn man tatsächlich unterschiedlich häufig
diese Anweisung ausführen lassen will
Das heißt, was wir dafür haben, ist eine Kontrollstruktur.
Das heißt, wir haben einen eigentlichen Anweisungsblock. Hier die
Anweisung A, und dann haben wir drumherum irgendwie eine Kontrollstruktur.
Etwas, was steuert, wie oft dieser Block hier ausgeführt wird.
Und wir versuchen das ein bisschen systematischer zu beschreiben,
mit dem wir sagen, naja,
bei einer Schleife unterscheiden wir den Schleifen Rumpf von der Schleifensteuerung.
Also der Schleifen Rumpf ist das Eigentliche, was ausgeführt werden soll.
Das deuten wir hier so ein bisschen so an,
meistens in diesem Vorliegen hier so mit so blauen Kästchen.
Und die schleifende Steuerung steuert die Anzahl der Wiederholung
Also ob es eine feste Anzahl von Wiedererholungen ist oder von
der Variablen abhängig oder von einer Bedingung hier in dem Fall von der Schleifenbedingung.
Nicht in diesem Fall, sondern das gucken wir uns gleich an.
Was ganz wichtig ist in diesem Schleifenrumpf, können durchaus Anweisungen stehen,
die Einfluss darauf haben, wie die Schleife gesteuert wird.
Wir gucken uns das mal so ein bisschen abstrakt an.
Also so Schleifenarten ist sowas hier, führe genau viermal aus.
Also ich kann sagen, eine Anweisung 1 soll genau viermal ausgeführt werden.
Oder ich möchte das abhängig von einer Variablen N machen und dann sage ich,
führe genau N mal aus, zwei Anweisungen.
Das sind sogenannte Zählschleifen, das heißt,
man hat irgendwie vorher schon festgestellt, wie oft das durchgefährt werden soll,
dann wird das genauso häufig gemacht.
Andere Art der Schleife ist diese hier, solange B zutrifft,
führe die Anweisung aus. Das alles sind abweisende Schleifen,
also im Sinne hier von diesen Strukturgrammendarstellungen sieht man hier,
das Grüne, wenn der Kontrollfluss wieder von oben reinfließt,
das Grüne steht dazwischen, dem Schleifenrumpf und dem Kontrollfluss,
kann also sein, dass dieser grüne Teil dafür sorgt, dass der Schleifenrumpf gar nicht ausgeführt wird.
Das nennen wir dann eine abweisende Schleife. Es gibt auch schleifende Assess anders,
die haben wir auch eingangs gesehen mit dem Passwort,
da wurde auf jeden Fall einmal der Schleifenrumpf ausgeführt und dann wird geprüft,
ob eine bestimmte Bedingung zutrifft und dann wird eventuell wiederholt
Das ist eine nicht abweisende Schleife. Und diese Schleifenart,
wo irgendwelche Bedingungen geprüft werden, das sind dann auch bedingte Schleifen.
Das sind jetzt so Begriffe, ja, das ist irgendwie,
einfach müssen wir mal ganz kurz so sich merken,
wie wir das hier nennen,
damit wir einfach dann auch drüber reden können in den Übungen.
Also eine Schleife heißt abweisend, wenn es sein kann,
dass der Schleifenhof gar nicht ausgeführt wird,
können wir auch manchmal als kopfgesteuerte Schleife bezeichnen.
Wird hingegen der Schleifenrumpf auf jeden Fall einmal ausgeführt,
dann ist es eine Nicht-Abweisungsleife oder Fuß- oder Endgesteuert.
So, Begriffe.
Dann eine bedingte Schleife
Da ist es eine logische Verknüpfung, die geprüft wird.
Und diese Bedingung wird entweder vor, bei einer abweisenden Schlaf oder nach,
Endgescheitschleife, jede Ausführung des Schleifen Rumpfes, erneut überprüft.
Das ist auch ganz wichtig, dass man sich klar macht,
anders als eben bei dem Switch,
wo die Frage ja kam, wird das denn mehrfach ausgewettet?
Nein, es wird genau einmal ausgewertet, der Ausdruck.
Das ist bei einer Schleife tatsächlich so, dass nach jedem
Schleifendurchlauf diese Bedingung erneut geprüft wird und erneut ausgewertet wird.
Und das werden wir uns auch vielleicht ein Beispiel mal ansehen.
Unabhängig von der Frage, ob es eine abweisende oder nicht ist,
gibt es zwei verschiedene Sichtweisen auf die Steuerung mit einer Bedingung von einer Schleife.
Man kann es positiv, positiv bedingt machen. Man kann sagen,
wenn die Bedingung zutrifft, dann soll der Schleifenrumpf nochmal ausgeführt werden.
Oder soll der Schleifenruf überhaupt ausgeführt werden? Man kann es
auch negativ formulieren, wenn die Bedingung nicht zutrifft,
dann soll die Schleife nicht weiter ausgeführt werden.
Also sozusagen bis eine Bedingung zutrifft, soll etwas gemacht werden.
Das ist also dieses Ausführen bis etwas,
also nicht mehr ausführen, wenn die Bedingung zutrifft.
So lange schleifen, wenn wir positiv bedingte schleifen,
die anderen nennen wir zielorientiert,
bedingte Schleifen
Wir werden uns gleich Beispiele dazu nochmal ansehen. Wir gucken uns
das mal hier an, an einem ganz einfachen Beispiel.
Ich möchte ein einzelnes Zeichen so lange einlesen,
bis es entweder ein J oder ein N ist,
also nebenan, da soll irgendwie,
der Benutzer soll irgendwie mit J oder mit Ja oder mit Nein antworten.
Das ist eine etwas andere Folie als im Skript,
also nicht wundern. Das können wir natürlich sofort hinschreiben.
Wir können im Pseudo-Code hinschreiben, wiederhole, Schleifenrumpf einlesen eines Zeichens.
Char, bis Char gleich J oder Char gleich N.
Das ist kein Problem. Das Problem in Java ist,
es gibt nur positiv bedingte Schleifen. Das heißt,
ich kann bei allen Schleifen immer nur sagen,
die Schleife soll ausgeführt werden,
wenn die Bedingung zutrifft
Wir wollen aber ja hier das nur machen, solange das nicht zutrifft. Das heißt,
wir kommen jetzt, wenn wir das in Java notieren wollen,
was wir jetzt hier sozusagen im Pseudo-Code geschrieben haben,
dann müssen wir das ein bisschen ändern,
dass wir einfach die Bedingungen negieren.
Also aus diesem Wiederhole bis das hier zutrifft,
also das ist Charles, entweder ein J oder ein N,
wird dann, solange so lange wiederholen,
solange es ungleich J ist und ungleich Nein, gleich N.
Das ist wieder so ein Beispiel, Man hätte tatsächlich auch
das anders machen können. Ich hätte diese ganze Bedingung hier
, klammern können und ein Ausrufezeichen davor schreiben können.
Das wäre dann eine Negation gewesen. Was wir dann gemacht
haben, ist mit den Demorgan-Regeln hier dieses sozusagen auszumultiplizieren.
Und das heißt also, diese Anweisung hier ist die logische Negation von der.
Da ist wieder so ein Beispiel, wo man sieht,
diese Demorgan-Regeln sollte man kennen, das ist diese Regel hier,
ja, wenn ich etwas P oder Kuh, wenn ich das negiere,
dann ist das eine Negierung aller Einzelausdrücke und dazwischen ein End.
Das braucht man tatsächlich, um solche Ausdrücke dann
ein bisschen zu vereinfachen
Also das ist ganz wichtig. Bei Java ist,
es gibt nur positiv bedingte Schleifen. Gut,
dann gibt es so etwas wie Zählschleifen. Bei einer Zählschleife
ist die Anzahl der Wiederholung zu Beginn der Schleife festgelegt,
entweder durch eine Konstante oder die Billigung einer Variablen.
Meistens sind die dann auch abweisend. Gibt also üblicherweise einen Schleifenzähler,
so einen Loop-Counter. Hier ist mal so ein Beispiel in Pascal,
eine Variable I vom Typ Injitscher, wird deklariert.
So, und dann wird hier gesagt,
VE gleich 1 210 Doo, Beginn End,
also es sieht sehr ähnlich aus wie ein Java,
Beginn und End sind hier die geschweiften Klammern.
Writeln, hallo, also wird da Hallo ausgegeben und dann
steht da Durchlauf und dann wird hier das I ausgegeben.
Das heißt, Dieser Schleifenzähler, der hier verwendet wird,
um die Schleife zu steuern, kann auch im Schleifenrumpf ausgelesen werden.
Er kann auch teilweise in Sprache natürlich im Schleifenrumpf auch manipuliert werden.
Das werden wir uns auch gleich noch ansehen. Okay. So,
jetzt mal, wie ist es konkret in Java gebaut?
Wenn wir jetzt diese Begriffe alle anwenden, dann können wir
einfach sagen, die Wahlschleife, die ist positiv bedingt.
Also die Schleife wird so lange ausgeführt, solange die Bedingung zutrifft,
positiv bedingt. Und sie ist abweisend. Das heißt,
wenn die Bedingung gleich zu Anfang nicht zutrifft, wird die Schleifenrumpf gar nicht ausgeführt.
Die Du-Wal-Schleife, die wir bei der Passwortangabe verwendet haben,
positiv bedingt. Also solange diese Bedingungen zutrifft, wird einfach
der Rumpf wiederholt. Ist aber entgesteuert. Das heißt,
es ist tatsächlich, dass das einmal durchgeführt wird.
Und die Vorschleife, die ist etwas komplizierter in Java,
die sieht hier auch von der Syntax etwas komplizierter aus.
Sie sehen uns mal etwas genauer an.
Ja, dann gucken wir uns das mal hier an.
Wir nehmen das mal mit rüber. Also die ist ziemlich flexibel.
Also die gesamte Schleifenschauen kann zwischen den runden Klammern stehen.
Das ist tatsächlich ganz toll. Man kann ziemlich viel da
in dieser Schleifensteuerung machen. Man kann zum Beispiel auch die Variable,
hier als Steuerung dienen soll, direkt in dem Fondsstatement deklarieren.
Dann ist sie auch nur innerhalb dieses, dieser Voranweisung sichtbar.
Werden wir uns gleich mal angucken. So,
jetzt ganz wichtig, es gibt diesen,
und das ist alles optional, ihr seht hier,
das ist tatsächlich, es kann da auch überall nichts stehen.
Es gibt einen Initialisierungsteil. Er wird, wird einmalig zu Beginn
der Schleife ausgeführt. Wirklich nur einmal und das ist eine Initialisierung.
Dann wird die Bedingung zwischen den beiden Semicola geprüft,
also diese Bedingung hier, wenn da eine steht,
Wenn die zutrifft, wird der Schleifenrumpf ausgeführt.
Und nach Ausführung des Schleifenrumfes wird der Teil nach dem zweiten Semikol dann ausgeführt.
Also diese Update Expression hier. Das ist hier,
ist so ein Beispiel, für NTI gleich null,
I-Kleiner 10 plus plus I.
Wir gucken uns das mal gleich genauer an.
Was hier passiert ist, werden einfach die Ziffern von 0 bis 9 ausgegeben.
Also hier null ist eine Ziffer, eins ist eine Ziffer und so weiter.
Das habe ich hier auch mal im Code.
Wir haben hier den Schleifendreher.
Drucke alle Ziffern
Das finde ich ein bisschen tatsächlich ein bisschen hakelig,
diese Sache mit der Vorstadt. Deswegen will ich das mal versuchen,
jetzt auch mit einem Debugger hier mal zu zeigen,
was da eigentlich genau passiert.
Das heißt, jetzt machen wir mal hier den Aufruf in
diesem Schleifendreher und sagen, drücke alle Ziffern.
Dann habe ich hier den Debugger und stehe jetzt an
dieser Stelle und wir sehen jetzt, was passiert.
Also diese Teile ist noch nicht ausgeführt.
Ihr seht zum Beispiel jetzt auch hier die lokale Variable,
auch jetzt das Passwort zu sehen, Zimtstern, sehr schön.
Die lokale Variable, I ist hier noch nicht sichtbar.
Die ist ja nur für innerhalb dieser Vorschleife zu sehen.
Also wenn diese Vorschleife jetzt ausgeführt, diese Zeile ausgefüllt wird,
dann werden aber nur diese beiden Teile ausgeführt.
Dieses Plus Plus I wird noch nicht ausgeführt. Also sollte I
dann erstmal null sein und wir sollten also dann jetzt,
weil die Bedingungen ja zutrifft, IS0 und null ist kleiner als zehn,
wird also dieser Rumpf auch ausgeführt.
Also meine Vorhersage ist das jetzt beim Schritt über,
der gelbe Balken in die nächste Zeile springt.
Und das ist auch so. Und jetzt sieht man,
I ist gleich null. Das heißt also,
dieses Plus Plus I, das ist tatsächlich noch nicht ausgeführt,
sondern dieses Plus Plus I wird jetzt logisch erst am Ende des Rumpfes ausgeführt.
Also jetzt mal, jetzt wird,
wenn ich jetzt einen Schritt übermache, passieren zwei Dinge.
Es wird zum einen Null ist eine Ziffer ausgegeben auf der Konsole.
Und es wird das I auch tatsächlich dann am Ende des Schleifenrumpfes erhöht.
Also ihr seht hier, null ist eine Ziffer. Okay,
es ist der Schleifenrum tatsächlich hier, das I nicht erhöht, auch interessant.
Okay, aber erstmal hat die Ausgabe hier funktioniert.
Ich muss mal eben den ein bisschen kleiner machen.
Die Konsole, das ist hier nicht so im Weg ist.
Okay. Und wenn ich jetzt den Schritt übermache, aha,
dann hat er jetzt tatsächlich das I erhöht am Ende des vorigen Schleifendurchlaufes,
hat jetzt festgestellt, ja,
es ist immer noch kleiner als zehn,
also können wir jetzt erstmal hier
ein bisschen durchlaufen
Gehen hier mal so ein bisschen weiter, dann passiert da relativ wenig.
Jetzt wird es ein bisschen interessanter, also das I ist jetzt acht,
dann wird es jetzt erhöht, dann wird es geprüft,
das ist klein, neun ist kleiner als zehn,
also wird dann hier auch die neuen ausgegeben.
Jetzt ist es neun und es wird jetzt erhöht am Ende des Schleifendurchlaufes,
dann wird es geprüft, es ist dann die zehn,
es ist dann nicht mehr kleiner als zehn,
also wird hier auch dran vorbeigesprungen.
Also das ist, finde ich, ein bisschen, ja,
nicht so intuitiv, das heißt, ich könnte das hier mal verdeutlichen,
dass man das auch wegnehmen könnte, ja, tatsächlich.
Ich könnte also tatsächlich hier ans Ende dieses Schleifen Rumpfes.
Einfach plus plus i schreiben. Das ist äquivalent.
So ist es aber viel klarer, was wo passiert.
Nur hatten wir den Vorteil, dass die ganze Schleifensteuerung hier drin passiert.
Hier ist jetzt sozusagen dieses Ding ein Teil der Schleifensteuerung im Rumpf drin.
Kann man sagen, das ist nicht so schön,
weil nicht die ganze Schleifensteuerung an einer Stelle steht.
Andererseits wird so sehr viel deutlicher, was da passiert.
Das ist Geschmackssache, aber ihr würdet jetzt,
wenn ihr das jetzt so übersetzen würdet, es genauso funktionieren.
Das heißt, das würde jetzt hier wieder,
wenn ich einen Schleifendreher mir erzeuge,
sollte der auch genau die Ziffern von 0 bis 9 ausgeben
Ja, da funktioniert also. Also nur,
dass ihr seht, dass das auch tatsächlich äquivalent ist.
Okay, dann gibt es noch die sogenannten Endlosschleifen.
Das ist etwas, was meistens nicht so gewollt ist.
Die einfachste, einfachste Form der Endlosschleife ist hier Wild True.
Solange die Bedingung zutrifft und True trifft immer zu,
dann wird das einfach endlos wiederholt.
Betriebssysteme sind im Grunde genommen so gebaut. Irgendwie immer eine
Schleife und Aktionen entgegennehmen und ausführen. Oder hier auch in
Java kann man auch so eine Endlosvorschleife programmieren. Ganz lustig,
Java, die haben in ihrem alten Karten-App-Logo hatten sie so
einen Kartenausschnitt mit dem Headquarter von Apple und die Adresse von denen ist tatsächlich,
es ist so ein Kreis und die Straße heißt Infinite Loop.
Die sind also sehr witzig gewesen, als sie das benannt haben.
Gut, das war jetzt erstmal was zu schleifen.
Gibt es noch Fragen zu schleifen? Zuweil, zuvor,
zu, das ist nicht der Fall. Dann würde ich jetzt nochmal
so ein paar Begriffe hier nochmal ein bisschen diskutieren wollen.
Was ich schon öfter, wenn ich hier mit euch gesprochen habe,
gesagt habe, ist, es gibt die Übersetzungszeit.
Das ist der Zeitpunkt, bei der der Compiler das Programm übersetzt.
Und das ist relativ wichtig, dass man das unterscheidet von
der Zeit, wenn das Programm wirklich läuft.
Und allgemein ist es so,
dass Programme einfach statische Eigenschaften haben und dynamische Eigenschaften,
dynamische Eigenschaften zur Laufzeit statische Eigenschaften zur Übersetzungszeit.
Und die wollen wir uns mal genauer angucken,
da kommen nämlich so Dinge hin ins Spiel,
so wann sind Variablen sichtbar und wie lange leben denn
Variablen und andere Objekte
Okay. Laufzeit und Übersetzungszeit. Das sind zwei ganz zentrale Begriffe.
Übersetzungszeit, Englisch Compilitant. Das ist nicht die Zeit,
die ein Compiler braucht, um euer Programm zu übersetzen.
Das wäre die Übersetzungsdauer. Wenn man das so benennen wollte.
Wir sagen einfach nur die Zeit, zu der der Compiler den Quelltext übersetzt.
Da guckt er auf die statische Struktur des Quelltextes.
Und da sind statische Eigenschaften von Programm relevant auf dieser Ebene.
Also welche Syntaxregeln gibt es? Welche wo dürfen Klammern
gesetzt werden und ähnliches? Welche Sichtbarkeitsregeln gibt es?
Kommen wir gleich noch drauf. Dann die Frage,
wie ist der Quelltext
denn strukturiert
Welche Klassenmethoden und so weiter gibt es denn in dem Quell?
Das kann man ja sehen. Und wie lesbar ist der Quelltext,
also Konventionen und ähnliches? Das sind alles Dinge,
die man zur Übersetzungszeit statisch feststellen kann. Deswegen auch hier
so ein bisschen die Statik angedeutet. Die Laufzeit,
das ist tatsächlich die Zeit, wenn das Programm ausgeführt wird.
Im Englischen wird das auch Runtime genannt. Und das ist
die Zeit, in der ein Computerprogramm ausgeführt wird.
Das gilt eigentlich für fast alle Programmiersprachen,
also insbesondere für die Programmiersprachen, die mit Compilern übersetzt werden.
Und da geht es dann darum, bei der Laufzeit,
ja, was macht denn das Programm eigentlich
Das ist das Entscheidende, was bewirkt das für Veränderungen im Speicher?
Letztendlich ist ja die Semantik, die ein Programm tatsächlich hat,
wie viele Objekte werden erzeugt, welche Lebensdauer haben die.
Das sind alles Fragen, die kann man meist erst beantworten,
wenn das Programm läuft.
Die kann man nicht aus dem Programmtext direkt ablesen.
Welche Methoden werden aufgerufen, welche Daten werden manipuliert? Insbesondere ist es so,
wenn ihr als Mensch mit dem Programm interagiert,
dann weiß man ja nicht, was der Mensch da so alles eingibt.
Also von daher kann man oft nicht wissen,
welche Methoden ausgeführt werden und welche Daten manipuliert werden.
Wir können uns das mal an einer logischen,
an einer lokalen Variablen veranschaulichen
Was Witzen wir zur Übersetzungszeit über eine lokale Variante?
Wir kennen ihren Namen und ihren Typ und ihre Sichtbarkeit.
Also wir wissen, lokale Variale hat einen Namen und einen Typ,
also was wie End-E oder so. Und die Sichtbarkeit,
also eine lokale Variante, da wissen wir,
die ist eigentlich nur innerhalb ihrer Methode sichtbar.
Und zur Laufzeit wissen wir, erst,
wir wissen erst zur Laufzeit mehr, nämlich darüber,
wie sie denn belegt wird.
Also mit welchen Werten sie belegt wird. Also was ihr
zugewiesen wird. Kann ja bei jeder Ausführung anders sein.
Ich kann ja das abhängig machen von irgendwelchen Parametern,
die übergeben werden,
von irgendwelchen Klienten
Die Lebensdauer. Also wie lange wird denn die lokale Variale
gebraucht? Wie lange braucht die Methode für die Ausführung?
Kann sehr unterschiedlich sein. Und was wir auch überhaupt nicht wissen,
ist, was man aber auch erst zur Laufzeit wissen kann,
ist, die Adresse einer Variante.
Wir wissen ja immer, Variablen sind eigentlich nur Abstraktionen vom Speicher.
Das heißt also, irgendwo wird auch jede Variable im Speicher
ihren Platz haben. Und das weiß man immer erst zur
Laufzeit, wenn man es überhaupt wissen will. Okay,
ein anderes Beispiel hier für den Unterschied,
um das nochmal zu verdeutlichen, ist,
es gibt die Aussage,
die Return-Anweisung ist immer die letzte Anweisung einer Methode
Das gilt für Java. Was ist dann mit dieser Methode
hier? Wir haben eine Methode Max, bekommen zwei Parameter
und liefert als Ergebnis das Maximum der beiden Zahlen.
Wenn A größer B ist, ein Return A, Elds Return B.
Hier haben wir jetzt den Unterschied zwischen statisch und dynamisch.
Wenn das Ding ausgeführt wird, ist es klar,
es wird eine dieser beiden Fälle nur zutreffen.
Das heißt, die letzte Anweisung, die ausgeführt wird zur Laufzeit,
wird irgendwie ein Return sein. Statisch ist es aber so,
dass das hier nicht die letzte Anweisung ist.
Also hier ist Return A ist offensichtlich nicht die letzte Anweisung,
die im Quelltext steht
Um das, ja, also gemeint ist hier zur Laufzeit
und zur besseren Lesbarkeit kann man das tatsächlich so machen,
dass man hier entsprechend eine lokale Variale deklariert und dann dafür sorgt,
dass dann hier diese lokale Variable zugewiesen wird.
Und dann wird hier tatsächlich, kann man sagen,
die Return-Anweisung ist die letzte Anweisung einer Methode. Deswegen sagen wir meistens,
es ist ganz angenehm, sich so eine Ergebnisvariable,
wenn man so eine sondierende Methode hat,
sich eine Ergebnisvariable zu deklarieren, die genauso heißt,
wie die Methode, das kann man tatsächlich machen in Java.
Und dann entsprechend am Ende einfach diesen Wert zurückgibt,
der dann im Laufe der Methode,
Methodenausführung berechnet wird
Das kann man so machen, das muss man nicht so machen.
Bei kleinen Methoden kann es durchaus okay sein,
dass man auch zwei Ausgänge mit Return hat.
Wir haben eine Zeit lang hier sehr stark vertreten,
dass eine Methode immer nur einen Eingang haben sollte.
Das ist klar durch den Aufruf und die Parameter,
aber auch nur einen Ausgang, wenn man es einfach besser lesbar zu halten.
Bei kleinen Methoden kann man auch dafür argumentieren,
dass es okay ist, dass man zwei Return oder drei Return-Statements hat,
solange man das so auf einen Blick sehen kann.
Okay, der Sichtbarkeitsbereich, das ist ein relativ zentraler Begriff
in der imperativen Programmierung. Das heißt,
jedem Bezeichnen ein Programm wird ein Bereich zugeordnet,
in dem er angesprochen oder benutzt
werden kann
Und auf den Wert einer sichtbaren Variablen kann dann über den Namen zugegriffen werden.
Man sieht hier so, man sieht hier so ganz dunkel da,
so diese Kühe, die da kaum sichtbar sind.
Sichtbarkeit von Variablen ist tatsächlich im Programmtext statisch erkennbar.
Das heißt, ich kann tatsächlich sehen, wo etwas sichtbar ist.
Das können wir auch tatsächlich in allen Java-Beispielen hier sehen,
wenn ich jetzt hier zum Beispiel An dieser Stelle eine variable End-I-Deklariere und sage,
sie soll den Wert 42 haben, dann ist das kein Problem,
weil diese Variable I hier, die war lokal,
nur sichtbar innerhalb dieser Vorschleife.
Ich kann also tatsächlich direkt danach eine andere Variable I haben.
Das heißt, die Sichtbarkeit dieses Is war beschränkt auf diesem Block hier.
Das ist ja auch so schön hervorgehoben hier.
Man kann das vielleicht nochmal Einstellungen hier ein bisschen stärker hervorheben
Dann sieht man das noch ein bisschen deutlicher. Also dieser
rote Block hier ist der Block, in dem dieses I sichtbar ist.
Und die Sichtbarkeit ist dann, geht nicht bis hierher,
deswegen kann ich hier einfach ein neues I deklarieren.
Okay, und jetzt, wenn wir auf Objektnotierte Systeme gucken,
insbesondere bei Java, ist es so,
eine Methode bildet gegenüber ihrer Umgebung einen eigenen Sichtbarkeitsbereich.
Das heißt, lokale Variable ist tatsächlich nur innerhalb der Methode sichtbar.
Die Umgebung einer Methode ist in einer Objektnotität und sprach natürlich ihre Klasse.
Das heißt, Alle Exemplarvariablen sind auch in allen Methoden sichtbar.
Das heißt, die Sichtbarkeitsbereiche von Klassen und Methoden sind ineinander geschachtelt.
Und das ist ja genau das, was man hier auch sieht.
Also hier lauter gelbe Sichtbarkeitsbereiche für die verschiedenen Methoden innerhalb dieser Klasse.
Die sind also da rein geschachtelt. Und auch hier sieht man wieder
die Sichtbarkeit dieser Vorschleife ist wiederum in dieser Methode geschachtelt.
Die sind also tatsächlich ineinander schachtelbar, Sichtbarkeitsbereiche.
Und tatsächlich kann ich ja auch solche Blöcke,
ich kann tatsächlich auch einfach Blöcke ineinander schachteln,
das kann ich auch nochmal zeigen,
Also auch jetzt hier einfach stattdessen schreiben, geschweifte Klammer.
Tap. So, und wieder geschweifte Klammer.
Ich kann also einfach hier einen neuen Blog aufmachen.
Lässt sich übersetzen. Das ist wenig spektakulär,
aber ich könnte jetzt hier zum Beispiel eine lokale Variable deklarieren,
die dann nur in diesem Blog sichtbar wäre.
Okay. Soweit so gut. Wir haben ja mal
ein Beispiel, dass das nochmal so ein bisschen aufgreift.
Wir haben eine Klasse, Test.
Wir haben eine Exemplarvariable
Vom Typ Int und die ist private. Was fällt als erstes auf,
wenn man diesen Quelltext hier sieht, bei dieser Exemplarvariante,
was ist da ganz schrecklich,
sofort möchte ich hier einen Sturm der Entrüstung losbrechen sehen.
Was ist das Problem mit dieser Exemplarvariable? Kein Unterstrich, genau.
Ihr werdet gleich sehen, warum das nämlich ganz hilfreich ist.
Diese Variable ist aber bewusst hier jetzt so benannt,
ohne unter Strich, um zu verdeutlichen,
dass das nützlich ist, es zu tun normalerweise.
Jetzt haben wir hier eine Methode Start,
die ruft zwei private Methoden auf, M1 und M2
Und dann hatten wir hier private Methode M1 und private Methode M2. So,
und jetzt haben wir hier innerhalb der Methode M1 zwei lokale Variablen,
X und Y, die sind vom Typ Double.
Und deswegen kann ich an dieser Stelle auch einfach schreiben,
X ist gleich 1.5. Ich habe dieses Projekt nochmal hier,
können wir also uns nochmal eben hier anzeigen lassen,
das ist der gleiche Code, der gleiche Quelltext.
Achtung, Exemplarvariable, nicht nach Konvention benannt, explizit bemerkt.
Wenn ich jetzt an dieser Stelle hier X gleich 1.5 zuweise,
1.5,
hat welchen Typ
Als Literal. Jeder Ausdruck hat einen Wert, hat einen
Typ in Java. Auch dieser Ausdruck hat einen Typ Long
. Quatsch, Double. Korrigiert mich doch. Schlaft ihr
schon? Das ist ein Double, ein Double-Literal.
Kann man ja auch hier sehen. Wenn ich jetzt hier
1.5 eintippe, dann ist das ein Double.
So, deswegen kann ich diese Zuweisung schreiben. Wenn ich
an dieser Stelle jetzt mal die Deklaration von X wegnehme,
dann ist plötzlich dieses X hier das X da oben.
Also ich habe hier ein In-X und weil ich mit dem X hier nicht mehr,
was ich hier lokal deklariert habe, das überdecke,
ist jetzt dieses X-Gemeine. Wenn ich das jetzt übersetze,
dann sagt der Kampagne natürlich, possible loss of precision,
weil ich versuche, eine Int-Variablin, einen Double-Wert zuzuweisen.
Wir wissen, das geht nicht,
weil da sozusagen der größere Behälter in einen kleineren gestopft wird,
der Inhalt eines größeren Behälters. Das heißt also,
wenn ich jetzt hier wieder dieses X einführe, als lokale Variante,
dann überdeckt dieses X die Sichtbarkeit von diesem X. Okay,
das ist also schon mal dann dieser Begriff der Sichtbarkeit,
Das ist tatsächlich hier X und Y sind hier sichtbar.
Hier ist nochmal das X, dass auf das wird sich tatsächlich bezogen.
Also hier die X gleich 5 Zuweisung. Das heißt,
es ist relativ unglücklich,
wenn hier X gleich 1,5 stehen und die X gleich 5 und man als Entwickler,
als Programmierer draufschaut und sich wundert, warum bei dem einen,
bei dem anderen was anderes passiert,
ist es also relativ unglücklich, Variablen gleich zu benennen.
Als Exemplar war Jabel und als lokale Variable.
Das ist also ein gutes Argument dafür,
diese Exemplarvariable mit Unterstrichen
zu benennen
Selbst wenn man das tut, selbst wenn man seine Exemplarvariante
mit einem Unterstrich benennt, kann man trotzdem noch Fehler machen.
Hier so eine klasse Uhrenanzeige, erinnert euch vielleicht noch dran,
war, glaube ich, in der letzten Übung dran.
Hier gibt es jetzt zwei Exemplarvariablen, Nummernanzeige vom Typ Nummernanzeigestunden und Minuten.
Und im Konstruktor sollen diese Exemplarvariablen initialisiert werden.
Und der Mensch, der das hier programmiert hat,
hat aber dummerweise im Konstruktor vor dieser Initialisierung,
die er schreiben wollte, nochmal den Typ davor geschrieben.
Also Nummernanzeige, Stundennummernanzeige Minuten. Das führt dazu,
dass hier tatsächlich nur zwei lokale Variablen deklariert werden.
Die werden irgendwie initialisiert und am Ende des Konstruktors
werden sie
wieder weggeschmissen
Das heißt, die Exemplarvarianten werden hier überhaupt nicht angefasst.
Das ist also auch ein typisches Problem eines Überdeckungsproblems.
Diese lokalen Varianten überdecken diese und damit werden die nicht mehr verändert.
Richtig ist es also tatsächlich, das so zu schreiben.
Einfach nur zu sagen, hier,
Stunden möchte ich jetzt zuweisen und Minuten möchte ich zuweisen.
Okay, dann haben wir noch die Sichtbarkeit der Elemente
einer Klasse, das haben wir ja schon kennengelernt.
Für Methoden wissen wir, wenn eine Methode Public ist,
dann ist sie für Klienten sichtbar und zugreifbar und auch aufrufbar,
wenn eine Methode Private ist,
dann ist sie tatsächlich nur innerhalb der Klasse sichtbar
Die Exemplarvariablen machen wir eigentlich üblicherweise private. Dazu kommen noch Protected und Default
, die sehen wir uns aber erst in SE2 an.
Das ist erstmal nicht wichtig. Was wir brauchen,
ist hier die Unterscheidung von Public and Private.
Da gibt es noch ein Konzept, das ist die Lebensdauer
einer Variablen. Das ist jetzt eine dynamische Eigenschaft.
Also wie lange lebt denn eine Variable oder ein Objekt?
Muss man unterscheiden. Also Objekte und Variablen muss man ja
sehr genau aufpassen. Das ist einfach die Zeit,
für die praktisch Speicher für ein variablen Objekt reserviert ist
Das kann durchaus unabhängig voneinander sein. Wir haben das gerade gesehen,
ein Exemplar war ja, der X ist statisch deklariert,
ein entsprechendes Feld eines Objektes hält zur Laufzeit einen Wert.
In einer Methode ist eine gleichnamige lokale Wahl,
aber Exeklent haben wir gerade gesehen, die die Exemplarvariable verdeckt,
obwohl sie weiter im Speicher existiert,
ist sie wechseln plavarial während der Ausführung der Methode nicht über den Namen X sichtbar.
Das heißt, Sichtbarkeit und Lebensdauer können auseinanderlaufen.
Bei Objekten ist das sogar noch ganz anders.
Ein Objekt in Java lebt so lange,
so lange es noch Referenzen auf das Objekt gibt.
Oder anders gesagt, es gibt keine Referenzen,
die länger leben als ihre Objekte
Wenn das Objekt weg ist,
dann kann es auch keine Referenz mehr darauf geben.
Das ist in Java einfach garantiert durch die Sprache.
Okay, das war das Thema Lebensdauer und Sichtbarkeit.
Was wir heute gesehen haben, wir machen gleich noch so
ein paar Euro, wir haben noch Zeit, herrlich.
Wir können auch so ein paar Fragen stellen gleich.
Strukturierte Programmierung beschränkt sich auf Kontrollstrukturen und zwar Sequenz, Verzweigung, Wiederholung.
Man braucht kein Go-To, um systematisch strukturiert zu programmieren.
Schleifenkonstrukte sind die einfachste Form, syntaktisch nicht so ganz einfach,
aber die einfachste Form von Wiederholung. Nächste Woche sehen wir
unsere Rekursion an und bei Elementen von Programmiermann haben wir gesehen,
es gibt Sichtbarkeit und Lebensdauer als wichtige Konzepte.
Sichtbarkeit ist eine statische Eigenschaft, kann ich im Programmtext sehen.
Laufzeit zur Erlaubszeit kann ich nur was sagen über die Lebensdauer.
Das ist also eine dynamische Eigenschaft. Hängt teilweise eng zusammen
. Gut, dann gucken wir noch mal,
was Storesi so für uns zu bieten hat.
Wir haben doch hier irgendwo noch bestimmt eine feine Aufgabe.
Das war das, sehr schön. Okay. Welchen Wert
hält die Variable X nach Ausführung des folgenden Java-Quelltextes?
Das hier ist der Java-Quelltext
Und welchen Wert hat X da? Ich starte die Abstimmung
, ihr könnt euch das in Ruhe überlegen.
Schaut es euch genau an. Also die Antwortmöglichkeiten hier,
Interja Max Value oder hat keine Belegung, es gibt eine Endlosschleife.
Das ist also tatsächlich eine Möglichkeit. Oder es kann auch sein,
dass es einfach zäh, dass es den Wert null hat.
Oder X hat auch keine Belegung, weil das Programm einfach
beim Überlauf abbricht
Naja. Ich weiß ja noch so bis zu 150.
Komm, komm, komm. Die letzten Stimmen.
Ja, sehr schön. Schau mal auf die Verteilung.
Oho, also 70 Prozent sagen, es ist null.
Und das ist tatsächlich auch die richtige Antwort
Gott, es funktioniert mal wieder nicht mit dem Anzeigen hier.
Ah, schön. Das ist auf jeden Fall die richtige Antwort.
Denn hier wird X der Wert null zugewiesen. Und solange
X größer 0 ist und X ist nicht größer neu.
Von Anfang an ist es schon nicht null.
Das heißt, es ist eine abweisende Schleife.
Es wird einfach gar nichts geändert. Also hat X
den Wert null eigentlich ganz einfach. Eigentlich ganz einfach.
Gut, dann haben wir hier nochmal ein weiteres Beispiel.
Welches Ergebnis liefert diese Methode, nämlich diese hier?
Diese Methode, wenn bei ihrem Aufruf als aktueller Parameter,
der wird 5 übergeben wird. Hier eine Methode M mit
einem Interparameter P und dann wird hier eine Vorschleife ausgeführt.
Ich starte mal die Abstimmung. Man könnte ja schon
eure Stimmen abgeben
Sechs Stimmen, oha. Ja, es ist nicht so einfach.
Man muss das erst mal sich in Ruhe angucken.
Kann ich schon verstehen. Das ist nicht so ganz ohne
. Das ist ja das, was ihr lernen müsst.
Ihr müsst eigentlich durch Lesen des Programmtextes euch vorstellen können,
wie das Programm sich zur Ausführungszeit verhält.
Zur Laufzeit. 30 Stunden, yeah, traut euch,
gebt eure Stimme ab
Offensichtlich nicht so ganz einfach. 50 Stimmen. 60 Stürmen,
70 Stürmen, ja. Gut, also ich glaube jetzt,
so langsam können wir einfach mal so, ja komm,
100 Stürmern kriegen wir doch zusammen, oder?
Na komm. Ja, toll. So, wir halten das mal
an. Ich hoffe mal, dass es jetzt klappt,
dass wir zumindest schon mal die Verteilung der Antworten sehen.
Okay, da ist also auch wieder eine deutliche Mehrheit bei 20.
Das heißt also auch, ich vermute mal,
dass die Leute, die sich sehr sicher waren,
dann auch ihre Stimme abgegeben haben.
Und die Verteilung ist tatsächlich richtig
Es kommt tatsächlich hier 20 raus. Denn wenn diese Schleife
hier fünfmal ausgeführt wird, also hier i gleich i kleiner,
also es wird viermal ausgeführt. Nein, i wird null,
dann sozusagen ein i kleiner P ist,
wenn es also fünf über das fünfmal ausgeführt.
Das heißt also, es wird hier i immer verdoppelt,
also es sind jetzt die Zahlen von 1 bis 4 auf addiert.
Das ist also zehnmal 20 und 20. Nicht so ganz einfach,
gebe ich zu. Und damit sind wir auch für heute
fertig. Vielen Dank. Tschüss