3 Programme zum Herunterladen und Spielen
Wir benutzen hier eine teilweise implizite Deklaration, d.h. alle nicht spezifizierten Variablen/Funktionen
mit Anfangsbuchstaben I-N sind vom
(4-Byte) Integer-typ, alle restlichen vom
(4-Byte) Real-typ.
Implizite Deklaration ist schnell, aber aeusserst fehleranfaellig!
Laesst sich nur durch die
IMPLICIT NONE
Anweisung verbieten! Dies sollte immer die erste Anweisung nach den USE-Anweisungen sein.
Falls nicht anders spezifiziert, haben INTEGER-Variablen
eine 4 Byte (= 32 bit) Darstellung, d.h. insgesamt koennen 2^32-1 verschiedene Integers (neg, 0, pos) erzeugt werden.
Bereich: [-2^31+1...0,..2^31-1], 2^31-1=2147483647 approx 2.14e9
Fuer die REAL-Variablen wird eine 4 Byte Gleitkommadarstellung angenommen, wobei die ersten 6 Stellen genau dargestellt
werden (meistens die ersten 7)
Bereich: [-0.3402823e39...-0.117549e-37,0.,0.117549e-37,0.3402823e39]
Falls man einen groesseren Bereich abdecken will, braucht man auf jeden Fall eine explizite Deklaration des Typparameters
(KIND)
Es existieren folgende Arten von Feldern (Pointer = Zeiger spaeter)
statische Felder
automatische Felder (immer mit expliziter Gestalt, nur in Unterprogrammen)
dynamische Felder (allocatable)
!
!========================================================================
!
program feldexp
! Beispielprogramm fuer Felder mit expliziter Gestalt
integer, parameter :: m=3
integer, parameter :: n=2
integer,dimension(m,n) :: ifeldexp=(/1,2,3, 4,5,6/) !expl. Gestalt
! Gesamtzahl der Feldelemente des naechsten Feldes = 6*4=24
real,dimension(-3:2,7:10) :: rfeldexp=(/(float(i),i=1,24)/)
real,dimension(6,4) :: rfeldexp_1=(/((float(i),i=j,24,4),j=1,4)/)
!implizite DO-Schleife, entspricht
! 1,5, 9,13,17,21, (j=1)
! 2,6,10,14,18,22, (j=2)
! 3,7,11,15,19,23, (j=3)
! 4,8,12,16,20,24, (j=4)
do i=1,m !fuer alle Zeilen
print*,'Zeile',i,':',ifeldexp(i,:) !fuer alle Spalten
enddo
print* !Leerzeile
do i=-3,2
print*,'Zeile',i,':',rfeldexp(i,:)
enddo
print*
! Jetzt rueckwarts
do i=2,-3,-1
print*,'Zeile',i,':',(rfeldexp(i,j),j=10,7,-1) !implizite DO-Schleife
enddo
print*
do i=1,6
print*,'Zeile',i,':',rfeldexp_1(i,:)
enddo
call sub(ifeldexp,rfeldexp,rfeldexp,rfeldexp_1,m,n,6,4)
end program feldexp
!--------------------------------------------------------------------------
subroutine sub(iarr,r1,r2,r_1,m,n,dim1,dim2)
integer,intent(in) :: dim1,dim2 ! Muss explizit erklaert werden, da sonst
!als REAL angenommen
integer,dimension(m,n) :: iarr !Dimension haengt von Formalparametern m,n ab
!Indizes starten jeweils bei 1, 2. Dimension kuerzer als im Orginal
real ,dimension(dim1,dim2-1) :: r1
! 1. Dimension kuerzer als im Orginal
real ,dimension(dim1-1,dim2) :: r2
!r_1 explizit mit gleicher Dimension (aber versch. Grenzen)
!wie im Hauptprogramm dimensioniert
real ,dimension(-3:2,7:10) :: r_1, newarr !lokales Feld newarr
integer,dimension(m,n) :: auto !Automatisches Feld, da Dimensionierung
!nicht konstant
!Man beachte den Unterschied vom lokalen zum automatischen Feld.
! Addition von 5 zum gesamten Feld!
print*
print*,'in sub'
print*
auto=iarr
newarr=r_1+5.
do i=1,m
print*,'Zeile',i,':',auto(i,:)
enddo
print* !Leerzeile
do i=1,dim1
print*,'Zeile',i,':',r1(i,:)
enddo
print*
do i=1,dim1-1
print*,'Zeile',i,':',r2(i,:)
enddo
print*
print*,'Merke also:!!'
print*,'Felder werden immer in der Reihenfolge der im Hauptprogramm'
print*,'definierten Speicherplaetze (1. Index laeuft zuerst),'
print*,'bis zur im Unterprogram def. Gesamtlaenge (dim1*dim2*..) uebergeben!'
print*
do i=-3,2
print*,'Zeile',i,':',r_1(i,:)
enddo
print*
do i=-3,2
print*,'Zeile',i,':',newarr(i,:)
enddo
return
end subroutine sub
!========================================================================
!
! Beachte: Interfaces unbedingt notwendig, entweder in einem Modul, das
! mit Use angesprochen wird, oder im rufenden Programm
!
!
! Beachte des weiteren: Uebernommene Gestalt sollte Standardprogrammiertechnik
! sein, uebernommene Groesse sehr komplex, wenn moeglich zu vermeiden!
!
module my_inter
interface
subroutine sub1(iarr1,iarr2,iarr3)
integer,dimension(:,:) :: iarr1
integer,dimension(3,0:*) :: iarr2
integer,dimension(-13:*) :: iarr3
end subroutine sub1
end interface
end module my_inter
program feldass
!
! Beispielprogramm fuer Felder mit uebernommener Gestalt / Groesse
!
use my_inter
interface
subroutine sub(iarr)
integer,dimension(:,:) :: iarr
end subroutine sub
end interface
integer, parameter :: m=3,n=2
integer,dimension(m,n) :: ifeld=(/1,2,3, 4,5,6/) !expl. Gestalt
integer,dimension(0:1,3:5) :: ifeld_1=(/1,2, 3,4, 5,6/) !expl. Gestalt
integer,dimension(2,4) :: ifeld_2=(/1,1,2,2,3,3,4,4/) !expl. Gestalt
call sub(ifeld)
call sub1(ifeld_1,ifeld_2,ifeld_2)
end program feldass
!--------------------------------------------------------------------------
subroutine sub(iarr)
integer,dimension(:,:) :: iarr !Uebernommene Gestalt:
!Zahl + Groesse der Dim. bleiben gleich
print*
print*,'in sub'
print*
do i=1,3
print*,'Zeile',i,':',iarr(i,:)
enddo
return
end subroutine sub
!--------------------------------------------------------------------------
subroutine sub1(iarr1,iarr2,iarr3)
integer,dimension(:,:) :: iarr1 !Uebernommene Gestalt
integer,dimension(3,0:*) :: iarr2 !Uebernommene Groesse:
!Gesamtgroesse des aktuell uebergebenenen Feldesbleibt erhalten)
integer,dimension(-13:*) :: iarr3 !Uebernommene Groesse
! Beachte:
!Nur letzte Dimension darf variabel sein, Untergrenze muss spezifiziert werden,
!Obergrenze mit *
m=size(iarr1,1)
n=size(iarr1,2)
print*
print*,'in sub1, m = ',m,' n = ',n
print*
do i=1,m
print*,'Zeile',i,':',iarr1(i,:)
enddo
print*
m=size(iarr2,1) ! Beachte: 2. Index kann nicht berechnet werden
do i=1,m
print*,'Zeile',i,':',iarr2(i,0:3) ! 2. Index muss explizit angeben werden
enddo
print*
do i=-13,-6
print*,'Zeile',i,':',iarr3(i)
enddo
return
end subroutine sub1
!========================================================================
!
! Dieses Programm zeigt, wie man voellig dimensionsunabhaengig programmiert!
!
! Im Hauptprogramm sind alle Felder allokierbar, waehrend die Unterprogramme
! dann assumed shape arrays verwenden!
program felddyn
!
! Beispielprogramm fuer dynamische Felder: Allokieren und Statusabfrage
!
interface
subroutine sub(ife)
integer, dimension(:,:) :: ife ! Beachte: Nur ife (assumed shape array)
! muss im interface angegeben werden
end subroutine sub
end interface
integer, dimension(:,:), allocatable :: ifeld
Bigloop: do
print*,'Give in first and 2nd dimension of ifeld(m,n); (m=0 ==> Exit)'
read*,m,n
print*,'Input was ',m,n
if(m == 0) exit
if (.not. allocated(ifeld) ) then
allocate(ifeld(m,n),stat =ifehler)
else
deallocate(ifeld)
allocate(ifeld(m,n),stat =ifehler)
endif
if (allocated(ifeld) ) then
print*,' ifeld successfully allocated'
else
stop' Error in allocation'
endif
! Alternativ dazu (nach erfolgreichem Allokieren stat => 0, sonst pos)
if (ifehler == 0 ) then
print*,' ifeld successfully allocated'
else
stop' Error in allocation'
endif
iz=0
do i=1,m
do j=1,n
iz=iz+1
ifeld(i,j)=iz
enddo
enddo
print*,'Size(ifeld) = ',size(ifeld,1),size(ifeld,2)
do i=1,m
print*,'Zeile ',i,':',ifeld(i,:)
enddo
call sub(ifeld)
enddo Bigloop
end program felddyn
subroutine sub(ife)
integer, dimension(:,:) :: ife
integer, dimension(:,:), allocatable:: i1
m=size(ife,1)
n=size(ife,2)
allocate(i1(m,n))
i1=ife
print*
print*,'in sub'
print*
do i=1,m
print*,'Zeile ',i,':',i1(i,:)
enddo
deallocate(i1)
return
end subroutine sub