Fortran: FORTRAN 77: Unterprogramme

Aus Wikibooks
<<< zur Fortran-Startseite
<< FORTRAN 77 Fortran 90/95 >>
< Standardfunktionen Ein- und Ausgabe >

Natürlich können in FORTRAN 77 auch eigene Unterprogramme erstellt werden.

Funktionsanweisung[Bearbeiten]

Eine Funktionsanweisung (auch Anweisungsfunktion genannt) stellt die einfachste Möglichkeit dar, ein Unterprogramm in FORTRAN 77 zu realisieren. Eine Funktionsanweisung kann nur einen Ausdruck umfassen und gilt nur in der Programmeinheit in der sie definiert wurde.

Definieren einer Funktionsanweisung:

funktionsname([formale parameter]) = ausdruck

Aufruf der Funktion:

[variable =] funktionsname([aktuelle parameter])

Beispiel:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
   
      FUNK() = 5 
   
      WRITE (*,*) FUNK ()
C  Ausgabe: 5.000000   
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  


Beispiel:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
    
      REAL A, B, C
      FUNK(A, B) = COS(A) * LOG(B) 
   
      C = FUNK(3.1415, 2.)
   
      WRITE (*,*) C
C  Ausgabe: -0.6931472   
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

FUNCTION[Bearbeiten]

Soll eine Funktion mehrere Anweisungen umfassen, so genügt das Konzept der Funktionsanweisung nicht mehr. FORTRAN 77 kennt zu diesem Zweck das Schlüsselwort FUNCTION.

[datentyp] FUNCTION funktionsname([formale parameter])

  anweisungen

END

Aufgerufen wird eine derartige Funktion gleich wie eine Funktionsanweisung.

Beispiel:

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
 
C  Funktionsaufruf
      WRITE(*,*) FUNK() 
C  Ausgabe: 27.50000     
     
      END   
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  


Datei funk.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      REAL FUNCTION FUNK()
 
      REAL TMP 
 
      DO 10 I = 1,10  
        TMP = TMP + I*0.5
 10   CONTINUE    
    
      FUNK = TMP
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  


Übersetzung mit gfortran:

gfortran bsp.f funk.f

Eine Funktion muss einen Wert zurückgeben. Welcher Wert das ist, wird durch eine Zuweisung an den Funktionsnamen erreicht. Wird am Anfang des Funktionskopfes kein Datentyp explizit vorgegeben, so gelten die Regeln für die implizite Datentypvergabe.

Mit Hilfe des Schlüsselwortes RETURN kann eine Funktion auch vor dem Funktionsende verlassen werden.

Beispiel:

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
 
C  Funktionsaufruf
      WRITE(*,*) FUNK(3) 
C  Ausgabe: 1.500000     
     
      END  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  


Datei funk.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      FUNCTION FUNK(I1)
 
      IF(I1 .LE. 5) THEN
        FUNK = 1.5
        RETURN
      END IF  
   
      FUNK = SIN(I1*0.5)
      
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

SUBROUTINE[Bearbeiten]

Eine Subroutine besitzt im Gegensatz zu einer Funktion keinen Datentyp und gibt keinen Wert zurück.

SUBROUTINE subroutinenname([formale parameter])

  anweisungen

END


Aufruf der Subroutine:

CALL subroutinenname([aktuelle parameter])

Beispiel:

Datei test.f

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
      CALL SUB   
      END 
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  


Datei sub.f

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB
      WRITE (*,*) 'Hallo Welt!'
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  


Übersetzung mittels gfortran:

gfortran -c sub.f
gfortran -c test.f
gfortran  test.o sub.o

Anzeige auf der Standardausgabe:

Hallo Welt!

Auch eine Subroutine kann mittels RETURN vorzeitig verlassen werden.


Die aktuellen und formalen Parameter müssen hinsichtlich Datentyp, Anzahl, Reihenfolge übereinstimmen. Alle Namen und Variablen in einer Programmeinheit (Subroutine, Funktion oder Hauptprogramm) sind grundsätzlich nur lokal in der jeweiligen Programmeinheit bekannt. Über die Unterprogrammparameter können aber sehr wohl Werte in der aufrufenden Programmeinheit geändert werden.

Beispiel:

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
 
      REAL A = 2.0
 
      CALL SUB(A)
 		
      WRITE(*,*) A
C  Ausgabe: 10						
 			
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Datei sub.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB(X)
 		
      REAL X
      REAL A
 
C  Unterprogrammparameter 
      X = 10
 
C lokale Variable
      A = 500
 		
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Felder als Parameter[Bearbeiten]

Beispiel: Übergabe eines ganzen Feldes

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
 
      INTEGER FELD(3,3)
      INTEGER CNT
 		
      CNT = 1
 
      DO 10 I = 1, 3
        DO 20 J = 1, 3
          FELD(J,I) = CNT
          CNT = 1 + CNT
 20     CONTINUE
 10   CONTINUE
  
C  Unterprogrammaufruf
      CALL SUB(FELD)
C  Ausgabe: 1   2   3   4   5   6   7   8   9
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Datei sub.f

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB(ARR)
 
      INTEGER ARR(3, 3)
 	
      WRITE(*,*) ARR
 				 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Beispiel: Übergabe einer Feld-Teilkette

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
 
      INTEGER FELD(3,3)
      INTEGER CNT
 		
      CNT = 1
 
      DO 10 I = 1, 3
        DO 20 J = 1, 3
          FELD(J,I) = CNT
          CNT = 1 + CNT
 20     CONTINUE
 10   CONTINUE
  
C  Unterprogrammaufruf
      CALL SUB(FELD(1:2,2:3))
C  Ausgabe: 4           5           7           8
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Datei sub.f

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB(ARR)
 
      INTEGER ARR(0:1, 0:1)
 	
      WRITE(*,*) ARR
 				 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Beispiel: Übergabe eines Feld-Einzelelements

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP

      INTEGER FELD(3,3)
      INTEGER CNT
 		
      CNT = 1
 
      DO 10 I = 1, 3
        DO 20 J = 1, 3
          FELD(J,I) = CNT
          CNT = 1 + CNT
 20     CONTINUE
 10   CONTINUE
  
C  Unterprogrammaufruf
      CALL SUB(FELD(1,2))
C  Ausgabe: 4
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Datei sub.f

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB(ARR)
 
      INTEGER ARR
 
      WRITE(*,*) ARR
 				 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Prozeduren als Parameter[Bearbeiten]

Auch Prozeduren können als Parameter übergeben werden.

Standardfunktionen werden dazu folgendermaßen im Vereinbarungsteil gekennzeichnet:

Aufruf der Subroutine:

INTRINSIC namensliste

Eigene Funktionen oder Subroutinen mit:

EXTERNAL namensliste

Beispiel:

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
 
      REAL PI
      PARAMETER(PI=3.1415927)
 
C  intrinsic functions
      INTRINSIC SIN, COS
 
C  Unterprogrammaufrufe
      CALL SUB(SIN, PI)
C  Ausgabe: 0.000000
      CALL SUB(COS, PI)
C  Ausgabe: -1.000000
 				
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Datei sub.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB(FUNK, X)
 		
      REAL FUNK, X
 	
      WRITE(*,*) NINT(FUNK(X)*1000)/1000.0
 				 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

COMMON[Bearbeiten]

Mit COMMON läßt sich ein gemeinsamer Datenbereich für mehrere Programmeinheiten realisieren.

Unbenannter COMMON:

COMMON variablenliste
COMMON /name/ variablenliste

Beispiel:

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
     PROGRAM BSP
 
      REAL A, B, C, D
      COMMON  A, B, C
      COMMON /C1/ D
   
      A = 4.0
      B = 5.0
      C = 6.0
   
      CALL SUB
   
      WRITE (*,*) A, B, C, D
C  Ausgabe: 3.330000   4.440000   6.000000   5.550000   
     
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Datei sub.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB
    
      REAL X, Y, Z
      COMMON X, Y
      COMMON /C1/ Z
 
      X = 3.33
      Y = 4.44  
      Z = 5.55 
   
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

ENTRY[Bearbeiten]

Mittels ENTRY kann gezielt in ein Unterprogamm gesprungen werden. Dieses Konstrukt widerspricht aber einer strukturierten Programmierung und sollte nicht verwendet werden.

ENTRY entryname[([formale parameter])]

Der Aufruf entspricht dem einer Subroutine:

CALL entryname[([aktuelle parameter])]

Beispiel:

Datei bsp.f

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
 
      CALL SUB  
C  Ausgabe: Hallo   
C           Welt!
 
      CALL E1
C  Ausgabe: Welt!
     
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Datei sub.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB
   
      WRITE(*,*) 'Hallo'
   
      ENTRY E1
      WRITE (*,*) 'Welt!'
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

SAVE[Bearbeiten]

Durch ein SAVE-Statement in Unterprogrammen behalten die lokalen Variablen ihren jeweiligen Wert auch nach Verlassen des Unterprogrammes. Dieses Konstrukt ist meist nicht notwendig, da die meisten FORTRAN-Compiler dieses Verhalten ohnehin automatisch aufweisen (siehe auch Kapitel DATA zwecks Initialisierung von Variablen).

SAVE [variablenliste]

Beispiel:

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
 
      CALL SUB  
C  Ausgabe: 1.000000
 
      CALL SUB  
C  Ausgabe: 2.000000
 
      CALL SUB  
C  Ausgabe: 3.000000
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Datei sub.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB
   
      REAL A
      SAVE
   
      A = A + 1
  
      WRITE(*,*) A
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

DATA[Bearbeiten]

DATA dient zur Wertinitialisierung von Variablen vor der Programmeinheitausführung. Diese Anweisung ist also nicht gleichzusetzen mit einer Wertzuweisung.

Beispiel:

DATA [variablenliste] /variablenwerte/

Beispiel:

Datei bsp.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      PROGRAM BSP
 
      CALL SUB  
C  Ausgabe: 1.000000
 
      CALL SUB  
C  Ausgabe: 2.000000
 
      CALL SUB  
C  Ausgabe: 3.000000
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Datei sub.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
      SUBROUTINE SUB
   
      REAL A
      DATA A /0.0/
   
      A = A + 1
 
      WRITE(*,*) A
 
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Unterschied zwischen Wertinitialisierung und Wertzuweisung:

Wertinitialisierung Wertzuweisung
Code
PROGRAM BSP
CALL SUB  
CALL SUB  
CALL SUB  
END

SUBROUTINE SUB
REAL A
DATA A /3.0/
A = A + 1
WRITE(*,*) A
END
PROGRAM BSP
CALL SUB  
CALL SUB  
CALL SUB  
END

SUBROUTINE SUB
REAL A
A = 3.0
A = A + 1
WRITE(*,*) A
END
Ausgabe
4.000000
5.000000
6.000000
4.000000
4.000000
4.000000

<<< zur Fortran-Startseite
<< FORTRAN 77 Fortran 90/95 >>
< Standardfunktionen Ein- und Ausgabe >