|
In f90 gli array possono essere dichiarati con
l'attributo ALLOCATABLE. Tale attributo indica che lo spazio
per quell'array non viene riservato all'inizio dell'esecuzione del
programma ma solo dopo l'esecuzione dell'istruzione ALLOCATE(),
in cui si determina anche la dimensione dell'array (denominato quindi
"deferred shape array" o "array allocato dinamicamente"). Il rango
(cioè il numero delle dimensioni) dell'array deve essere comunque reso
noto al momento della compilazione specificandolo nella dichiarazione
dell'array stesso.
Una variabile ALLOCATABLE può essere allocata solo nell'unità di programma in cui è dichiarata o, se è dichiarata in un modulo, in una qualsiasi unità di programma che fa USE di quel modulo; in altre parole non è possibile, in una subroutine, allocare un array ricevuto come parametro (sarà possibile farlo in F2003). Al termine dell'utilizzo o prima di un'eventuale riallocazione dell'array con una dimensione diversa, è opportuno liberare lo spazio con l'istruzione DEALLOCATE(). Esiste poi la funzione intrinseca ALLOCATED() che restituisce un valore logico .TRUE. se il corrispondente argomento è correntemente allocato e viceversa. |
PROGRAM rete_oss USE stazioni IMPLICIT NONE CHARACTER (LEN=20), rnome REAL :: rlon, rlat, rt INTEGER :: n READ*,n CALL alloc_staz(n) DO WHILE(.TRUE.) READ*, rnome, rlon, rlat, rt IF (rlon < -361.) EXIT CALL aggiungi_staz(rnome, rlon, rlat, rt) ENDDO PRINT'(A,I3,A)','Ho letto ',get_nstaz(),' stazioni' CALL elabora_temp() CALL dealloc_staz() END PROGRAM rete_oss |
MODULE stazioni IMPLICIT NONE INTEGER, PARAMETER :: nstazmax=100 INTEGER :: nstaz = 0 REAL, ALLOCATABLE :: lon(:), lat(:), t(:) CHARACTER (LEN=20), ALLOCATABLE :: nome(:) PRIVATE nstaz CONTAINS SUBROUTINE alloc_staz(n) INTEGER, INTENT(IN) :: n ALLOCATE(lon(n), lat(n), t(n), nome(n)) END SUBROUTINE alloc_staz SUBROUTINE dealloc_staz() IF ALLOCATED(lon) THEN DEALLOCATE(lon, lat, t, nome) ENDIF END SUBROUTINE dealloc_staz SUBROUTINE aggiungi_staz(nnome, nlon, nlat, nt) CHARACTER (LEN=*), INTENT(IN) :: nnome REAL, INTENT(IN) :: nlon, nlat, nt IF (nstaz < size(lon)) THEN nstaz = nstaz + 1 nome(nstaz) = nnome lon(nstaz) = nlon lat(nstaz) = nlat t(nstaz) = nt ELSE PRINT*,'Raggiunto il massimo delle stazioni' ENDIF END SUBROUTINE aggiungi_staz SUBROUTINE stampa_anag() INTEGER :: i DO i = 1, nstaz PRINT'(A,2F7.2)',TRIM(nome(i)),lon(i),lat(i) ENDDO END SUBROUTINE stampa_anag SUBROUTINE elabora_temp() IF (nstaz > 0) THEN PRINT'(A,F9.2)','Temperatura media:', SUM(t(1:nstaz))/nstaz ENDIF END SUBROUTINE elabora_temp INTEGER FUNCTION get_nstaz() get_nstaz = nstaz END FUNCTION get_nstaz END MODULE stazioni |