====== Schleifen ====== Schleifen (Iterationen) werden dazu verwendet Quellcode mehrfach hintereinander auszuführen. Abhängig von einer Bedingung kann Code also wiederholt werden. ===== Klassisches Fortran ===== In klassichem Fortran wird gibt es eine Zählschleife: DO k = , [, ] c Anweisungscode CONTINUE ! oder andere Anweisung Das ist eine gewöhnliche Zählschleife, die mit k von bis iteriert, und zwar mit der Schrittgröße . Für frühes Fortran galt, dass kstep immer größer als Null sein muss, in Fortran 77 war dann möglich auch negative Zahlen als Schrittgröße zu verwenden. ist eine Sprungmarkierung. Dorthin wird gesprungen, wenn die Bedingung nicht mehr erfüllt ist. Wichtig ist auch, dass die Anweisung bei der Sprungmarke ebenfalls im Schleifenkörper ausgeführt wird! Ein ''CONTINUE'' also als erste Anweisung zu schreiben hat zur Folge, dass an dieser Stelle keine Aktion ausgeführt wird. In Fortran 77 war es eine Zeit lang möglich auch reelle Zahlen als Zählvariablen (und Schrittgröße) zu wählen. Allerdings entstanden dadurch Probleme, da die Anzahl der Durchläufe nicht immer korrekt bestimmt werden konnte, weil mit reellen Zahlen Rundungsfehler passieren (siehe 0.1 in Binärdarstellung). Heutzutage sollte der Compiler dieses Feature nicht mehr erlauben. ===== Fortran 77 ===== :?: Fortran 77? Ebenfalls möglich ist die Verwendung einer Syntax, die ähnlich der eine ''for''-Schleife anderer Programmiersprachen erscheint: do k=, [,] c Anweisungen enddo Hierbei werden die Anweisungen im do-while-Block ausgeführt, und ''k'' pro Schleifendurchlaus jeweils um '''' hochgezählt. ''k'' startet bei ''''; die Schleife wird solange ausgeführt bis ''k'' größer ist als ''''. Anstelle von ''k'' kann jede beliebige Integer-Variable verwendet werden. Im Fortran 77 Standard war vorgesehen, dass nicht nur Integer-Variablen als Laufvariablen verwendet werden können, sondern auch Real. Führt auch dazu, dass '''' Real-Variablen sein konnten. Das bringt allerdings durch Rundungsfehler viele Fehler mit sich, bspw. wurde es für den Programmierer schwer vorauszusagen, wie viele Schleifendurchläufe die Schleife genau macht, da es kaum abschätzbar ist, wie stark eine Real-Variable durch Rundungsfehler beeinflusst wird. Daher ist dieses Feature in den meisten heutigen Compilern ein deleted Feature (gelöschtes Feature). ===== Do-While (Fortran 90) ===== In Fortran 90 gibt es die Do-While-Schleife, die ähnlich wie While-Schleifen anderer Programmiersprachen aussieht. Dieses Feature wurde oftmals bereits in Fortran 77-Compiler eingebaut. DO WHILE () c Anweisungscode END DO Im Anweisungscode steht idealerweise Code, der Auswirkung auf den logischen Ausdruck hat. Es ist aber auch möglich aus der Schleife mittels ''goto'' herauszuspringen. ===== Unendliche Schleifen ===== Passend dazu gibt es noch die unendliche Schleife, die gänzlich ohne Abbruchbedingung auskommt. Idealerweise gibt es im Anweisungsblock allerdings die Möglichkeit aus der Schleife auszubrechen - eine tatsächlich unendliche Schleife ist selten in Programmen nützlich. DO c code IF () EXIT c noch mehr code END DO Die Schleife beginnt mit ''DO'', dann folgt der Anweisungsblock (auf der nächsten Zeile). Im Anweisungsblock sollte mit einer Bedingung der Ausbruch aus der Schleife (''EXIT'') möglich sein. ===== Schleifen mittels GOTO ===== Es ist auch möglich Schleifen wie im Assemblercode mittels ''GOTO'' aufzubauen. Bitte beachten Sie, dass ''GOTO'' heutzutage kaum Verwendung finden sollte, weil der Code durch ''GOTO'' erheblich schwerer zu lesen wird (siehe Spaghetticode). ==== Abweisende Schleifen ==== Bei abweisenden Schleifen (also Schleifen, die zuerst eine Bedingung prüfen und dann das erste mal den Schleifenkörper ausführen) muss mit ''if'' die Bedingung geprüft werden, und sollte diese nicht erfüllt sein, hinter den Schleifenkörper gesprungen werden. Am Ende des Schleifenkörpers muss dann wieder nach oben zur Bedinungsprüfung gesprungen werden. program main integer :: k = 10; 1 if (k .LT. 5) then goto 20 endif k=k-1 goto 1 20 CONTINUE write (*,*) k end program ==== Nicht-abweisende Schleife ==== Bei der nicht-abweisenden Schleife wird zuerst der Schleifenkörper ausgeführt, danach die Bedingung geprüft. Ist sie noch erfüllt, wird wieder nach oben gesprungen, ansonsten wird nicht gesprungen, und damit die Schleife nicht erneut ausgeführt. program main integer :: k = 10; 1 k=k-1 if (k>5) then goto 1 endif write (*,*) k end program ===== Steueranweisungen ===== In Fortran kann mittels spezieller Steueranweisungen bspw. aus einer Schleife ausgebrochen werden (vgl. break / continue aus C): * ''CYCLE'' -> überspringt den Rest der inneren Schleife und führt die innere Schleife erneut aus (vgl. ''continue'') * ''EXIT'' -> bricht aus der aktuellen Schleife aus (vgl. ''break'') Bsp: outer: do i=1,n ! Zählschleife von 1 bis n, Schrittweite 1 c Anweisungen inner: do j=i,n ! Zählschleife von i bis n c ... if (...) EXIT outer ! verlasse die gesamte Schleife if (...) EXIT ! verlasse nur die innere Schleife if (...) CYCLE ! überspringe den Rest der inneren Schleife c ... END DO inner END DO outer Hier stehen zwei verschachtelte Zählschleifen von 1 bis n, bzw. von i bis n. Im Inneren sehen Sie verschiedene Steueranweisungen. Mit ''EXIT outer'' wird das gesamte Konstrukt verlassen (also die äußere Schleife wird verlassen), mit ''EXIT'' wird nur die aktuelle Stufe verlassen (inner) und mit ''CYCLE'' wird, ähnlich wie ''continue'' in C, der Rest der Schleife übersprungen und sofort mit den nächsten Schleifenelement fortgefahren. ===== Matrizen ausgeben ===== :!: Vorgriff auf Kapitel [[array|Felder]] Die Anweisung ''write'' gibt immer eine Zeile aus, dh. egal, was Sie damit ausgeben, am Ende steht immer implizit ein '\n', also ein Zeilenendzeichen. Wollen Sie aber eine Matrix ausgeben, kann es notwendig sein mehrere Werte nebeneinander auszugeben, aber vielleicht wissen Sie nicht wie viele Zahlen das sind. Dafür gibt es folgendes Konstrukt: REAL A(1000,1000) ! Array mit 1000x1000 Real-Einträgen WRITE (*,*) (A(1,j), j=1,m) Diese Anweisung die die erste Zeile der Matrix aus, dh. der Index //j// wird von 1 bis //m// iteriert und die Werte der Matrix an die Stelle des Konstrukts getragen, sodass ''write'' alle Werte der Zeile ausgibt. Das Ganze geht auch geschachtelt (dann stehen __alle__ Werte auf einer Zeile): REAL A(1000,1000) ! Array mit 1000x1000 Real-Einträgen WRITE (*,*) ((A(i,j), j=1,m), i=1,n)