Ricerca…


Tipi di variabili implicite

Quando Fortran era originariamente sviluppato, la memoria era un premio. Le variabili e i nomi delle procedure potevano avere un massimo di 6 caratteri e le variabili venivano spesso digitate implicitamente . Ciò significa che la prima lettera del nome della variabile determina il suo tipo.

  • le variabili che iniziano con i, j, ..., n sono integer
  • tutto il resto (a, b, ..., h, e o, p, ..., z) sono real

Programmi come il seguente sono accettabili Fortran:

program badbadnotgood
  j = 4
  key = 5 ! only the first letter determines the type
  x = 3.142
  print*, "j = ", j, "key = ", key, "x = ", x
end program badbadnotgood

Potresti anche definire le tue regole implicite con la dichiarazione implicit :

! all variables are real by default 
implicit real (a-z)

o

! variables starting with x, y, z are complex
! variables starting with c, s are character with length of 4 bytes
! and all other letters have their default implicit type
implicit complex (x,y,z), character*4 (c,s) 

La tipizzazione implicita non è più considerata la migliore pratica. È molto facile commettere un errore utilizzando la digitazione implicita, poiché gli errori di battitura possono passare inosservati, ad es

program oops
  real :: somelongandcomplicatedname

  ...

  call expensive_subroutine(somelongandcomplEcatedname)
end program oops

Questo programma funzionerà felicemente e farà la cosa sbagliata.


Per disattivare la digitazione implicita, è possibile utilizzare l'istruzione implicit none .

program much_better
  implicit none
  integer :: j = 4
  real :: x = 3.142
  print*, "j = ", j, "x = ", x
end program much_better

Se avessimo usato implicit none nel programma oops sopra, il compilatore si sarebbe accorto immediatamente e avrebbe prodotto un errore.

Aritmetica se dichiarazione

L'istruzione aritmetica if consente di utilizzare tre rami in base al risultato di un'espressione aritmetica

if (arith_expr) label1, label2, label3

Questa istruzione if trasferisce il flusso di controllo a una delle etichette in un codice. Se il risultato di arith_expr è negativo, l' label1 è coinvolta, se il risultato è zero label2 viene utilizzato e se il risultato è positivo, viene applicata l'ultima label3 . Aritmetica if richiede tutte e tre le etichette ma consente il riutilizzo di etichette, quindi questa affermazione può essere semplificata in due rami if .

Esempi:

if (N * N - N / 2) 130, 140, 130

if (X) 100, 110, 120

Ora, questa funzione è obsoleta con la stessa funzionalità offerti dal if dichiarazione e if-else costrutto. Ad esempio, il frammento

    if (X) 100, 110, 120
100 print*, "Negative"
    goto 200
110 print*, "Zero"
    goto 200
120 print*, "Positive"
200 continue

può essere scritto come il costrutto if-else

if (X<0) then
  print*, "Negative"
else if (X==0) then
  print*, "Zero"
else
  print*, "Positive"
end if

Una sostituzione di dichiarazione if per

    if (X) 100, 100, 200
100 print *, "Negative or zero"
200 continue

può essere

if (X<=0) print*, "Negative or zero"

Costrutti DO non bloccanti

La non-blocco do costruire assomiglia

    integer i
    do 100, i=1, 5
100 print *, i

Cioè, dove la dichiarazione di terminazione etichettata non è una dichiarazione continue . Ci sono varie restrizioni sulla dichiarazione che può essere usata come dichiarazione di terminazione e l'intera faccenda è generalmente molto confusa.

Tale costrutto non blocco può essere riscritto in forma di blocco come

    integer i
    do 100 i=1,5
      print *, i
100 continue

o meglio, usando una dichiarazione di end do ,

integer i
do i=1,5
  print *, i
end do

Ritorno alternativo

Il ritorno alternativo è una funzione per controllare il flusso di esecuzione al ritorno da una subroutine. È spesso usato come una forma di gestione degli errori:

real x

call sub(x, 1, *100, *200)
print*, "Success:", x
stop

100 print*, "Negative input value"
stop

200 print*, "Input value too large"
stop

end

subroutine sub(x, i, *, *)
  real, intent(out) :: x
  integer, intent(in) :: i
  if (i<0) return 1
  if (i>10) return 2
  x = i
end subroutine

Il ritorno alternativo è contrassegnato dagli argomenti * nell'elenco degli argomenti fittizi subroutine.

Nell'istruzione di call sopra *100 e *200 riferiscono rispettivamente alle dichiarazioni 100 e 200 .

Nella subroutine stessa le dichiarazioni di return corrispondenti al ritorno alternativo hanno un numero. Questo numero non è un valore di ritorno, ma indica l'etichetta fornita a cui viene trasmessa l'esecuzione al reso. In questo caso, return 1 passa l'esecuzione all'istruzione 100 e return 2 passaggi all'esecuzione etichettata 200 . Una dichiarazione di return senza ornamenti, o il completamento dell'esecuzione di subroutine senza una dichiarazione di return , l'esecuzione della passata immediatamente dopo l'istruzione di chiamata.

La sintassi di ritorno alternativa è molto diversa dalle altre forme di associazione degli argomenti e la struttura introduce il controllo del flusso contrario ai gusti moderni. Un controllo di flusso più gradevole può essere gestito con la restituzione di un codice di "stato" intero.

real x
integer status

call sub(x, 1, status)
select case (status)
case (0)
  print*, "Success:", x
case (1)
  print*, "Negative input value"
case (2)
  print*, "Input value too large"
end select

end

subroutine sub(x, i, status)
  real, intent(out) :: x
  integer, intent(in) :: i
  integer, intent(out) :: status

  status = 0

  if (i<0) then
    status = 1
  else if (i>10)
    status = 2
  else
    x = i
  end if

end subroutine

Modulo Fisso

Originariamente Fortran è stato progettato per un formato di formato fisso basato su una scheda perforata a 80 colonne:

inserisci la descrizione dell'immagine qui

Sì: questa è una riga del codice dell'autore

Questi sono stati creati su una macchina punch card, molto simile a questo:

inserisci la descrizione dell'immagine qui

Le immagini sono fotografie originali dell'autore

Il formato, come mostrato nella scheda campione illustrata, aveva le prime cinque colonne riservate per le etichette di istruzioni. La prima colonna è stata utilizzata per denotare i commenti con una lettera C. La sesta colonna è stata utilizzata per indicare una continuazione dell'istruzione (inserendo un carattere diverso da zero '0'). Le ultime 8 colonne sono state utilizzate per l'identificazione e il sequenziamento delle carte, il che è stato di grande valore se hai lasciato cadere il mazzo di carte sul pavimento! La codifica dei caratteri per le schede perforate aveva solo un numero limitato di caratteri ed era solo in maiuscolo. Di conseguenza, i programmi Fortran assomigliavano a questo:

       DIMENSION A(10)                                                    00000001
C THIS IS A COMMENT STATEMENT TO EXPLAIN THIS EXAMPLE PROGRAM             00000002
       WRITE (6,100)                                                      00000003
 100   FORMAT(169HTHIS IS A RATHER LONG STRING BEING OUTPUT WHICH GOES OVE00000004
      1R MORE THAN ONE LINE, AND USES THE STATEMENT CONTINUATION MARKER IN00000005
      2COLUMN 6, AND ALSO USES HOLLERITH STRING FORMAT)                   00000006
       STOP                                                               00000007
       END                                                                00000008

Anche il carattere dello spazio è stato ignorato ovunque, tranne all'interno di una costante di carattere di Hollerith (come mostrato sopra). Ciò significava che gli spazi potevano verificarsi all'interno di parole e costanti riservate, o completamente persi. Ciò ha avuto l'effetto collaterale di alcune affermazioni piuttosto fuorvianti come:

       DO 1 I = 1.0

è un compito assegnato alla variabile DO1I mentre:

       DO1I = 1,0 

è in realtà un ciclo DO sulla variabile I


Il moderno Fortran non richiede ora questa forma di input fissa e consente la forma libera utilizzando qualsiasi colonna. I commenti ora sono indicati da un ! che può anche essere aggiunto a una riga di istruzioni. Gli spazi ora non sono consentiti da nessuna parte e devono essere usati come separatori, proprio come nella maggior parte delle altre lingue. Il suddetto programma potrebbe essere scritto in Fortran moderno come:

! This is a comment statement to explain this example program
Print *,"THIS IS A RATHER LONG STRING BEING OUTPUT WHICH no longer GOES OVER MORE THAN ONE LINE, AND does not need to USE THE STATEMENT CONTINUATION MARKER IN COLUMN 6, or the HOLLERITH STRING FORMAT"

Sebbene la continuazione vecchio stile non sia più utilizzata, l'esempio sopra illustra che si verificano ancora dichiarazioni molto lunghe. Il Fortran moderno usa un simbolo & alla fine e all'inizio della continuazione. Ad esempio, potremmo scrivere quanto sopra in una forma più leggibile:

! This is a comment statement to explain this example program
Print *,"THIS IS A RATHER LONG STRING BEING OUTPUT WHICH still &
         &GOES OVER MORE THAN ONE LINE, AND does need to USE THE STATEMENT &
         &CONTINUATION notation"

Blocchi comuni

Nelle prime versioni di Fortran, l'unico meccanismo per la creazione di archivi di variabili globali visibili da subroutine e funzioni consiste nell'utilizzare il meccanismo di blocco COMMON . Questo consentiva che le sequenze di variabili fossero nomi e condivisi in comune.

Oltre ai blocchi comuni denominati potrebbe esserci anche un blocco comune vuoto (senza nome).

Un blocco comune vuoto potrebbe essere dichiarato come

common i, j

mentre le variables blocco nominate potrebbero essere dichiarate come

common /variables/ i, j

Come esempio completo, possiamo immaginare un archivio di heap che viene utilizzato da routine che possono aggiungere e rimuovere valori:

       PROGRAM STACKING
       COMMON /HEAP/ ICOUNT, ISTACK(1023)
       ICOUNT = 0
       READ *, IVAL
       CALL PUSH(IVAL)
       CALL POP(IVAL)
       END

       SUBROUTINE PUSH(IVAL)
       COMMON /HEAP/ ICOUNT, ISTACK(1023)
       ICOUNT = ICOUNT + 1
       ISTACK(ICOUNT) = IVAL
       RETURN
       END

       SUBROUTINE POP(IVAL)
       COMMON /HEAP/ ICOUNT, ISTACK(1023)
       IVAL = ISTACK(ICOUNT)
       ICOUNT = ICOUNT - 1
       RETURN
       END

È possibile utilizzare dichiarazioni comuni per dichiarare implicitamente il tipo di una variabile e specificare l'attributo della dimension . Questo comportamento da solo è spesso una fonte sufficiente di confusione. Inoltre, l'associazione di memorizzazione implicita ei requisiti per le definizioni ripetute su unità di programma rendono l'uso di blocchi comuni inclini all'errore.

Infine, i blocchi comuni sono molto limitati negli oggetti che contengono. Ad esempio, una matrice in un blocco comune deve essere di dimensioni esplicite; gli oggetti allocabili potrebbero non verificarsi; i tipi derivati ​​non devono avere l'inizializzazione predefinita.

Nel moderno Fortran questa condivisione di variabili può essere gestita mediante l'uso di moduli . L'esempio sopra può essere scritto come:

module heap
  implicit none
  ! In Fortran 2008 all module variables are implicitly saved
  integer, save :: count = 0
  integer, save :: stack(1023)
end module heap

program stacking
  implicit none
  integer val
  read *, val
  call push(val)
  call pop(val)

contains
  subroutine push(val)
    use heap, only : count, stack
    integer val
    count = count + 1
    stack(count) = val
  end subroutine push

  subroutine pop(val)
    use heap, only : count, stack
    integer val
    val = stack(count)
    count = count - 1
  end subroutine pop
end program stacking

I blocchi comuni nominati e vuoti presentano comportamenti leggermente diversi. Di nota:

  • gli oggetti in blocchi comuni denominati possono essere inizialmente definiti; gli oggetti in bianco comune non devono essere
  • gli oggetti nei blocchi comuni vuoti si comportano come se il blocco comune avesse l'attributo di save ; gli oggetti nei blocchi comuni denominati senza l'attributo di save potrebbero non essere definiti quando il blocco non si trova nell'ambito di un'unità di programma attiva

Quest'ultimo punto può essere contrapposto al comportamento delle variabili del modulo nel codice moderno. Tutte le variabili del modulo in Fortran 2008 vengono salvate in modo implicito e non diventano indefinite quando il modulo esce dal campo di applicazione. Prima che le variabili del modulo di Fortran 2008, come le variabili nei blocchi comuni denominati, diventassero indefinite anche quando il modulo usciva dall'ambito.

GOTO assegnato

GOTO assegnato utilizza la variabile intera a cui è assegnata un'etichetta di istruzione utilizzando l'istruzione ASSIGN.

100 CONTINUE

...

ASSIGN 100 TO ILABEL

...


GOTO ILABEL

GOTO assegnato è obsoleto in Fortran 90 e eliminato in Fortran 95 e versioni successive. Può essere evitato nel codice moderno utilizzando procedure, procedure interne, indicatori di procedura e altre funzionalità.

GOTO calcolato

GOTO calcolato consente la diramazione del programma in base al valore di un'espressione intera.

GOTO (label_1, label_2,... label_n) scalar-integer-expression

Se l' scalar-integer-expression è uguale a 1, il programma continua con l'etichetta label_1 , se è uguale a 2 va a label_2 e così via. Se è inferiore a 1 o maggiore di n programma continua sulla riga successiva.

Esempio:

ivar = 2

...

GOTO (10, 20, 30, 40) ivar

salterà all'etichetta dell'istruzione 20.

Questa forma di goto è obsoleta in Fortran 95 e successivi, essendo sostituita dal costrutto di select case .

Specificatori di formato assegnati

Prima di Fortran 95 era possibile utilizzare i formati assegnati per l'input o l'output. Tenere conto

integer i, fmt
read *, i

assign 100 to fmt
if (i<100000) assign 200 to fmt

print fmt, i

100 format ("This is a big number", I10)
200 format ("This is a small number", I6)

end

L'istruzione assign assegna un'etichetta di istruzione a una variabile intera. Questa variabile intera viene in seguito utilizzata come identificatore di formato nell'istruzione print .

Tale attribuzione di identificatori di formato è stata eliminata in Fortran 95. Invece, un codice più moderno può utilizzare un'altra forma di controllo del flusso di esecuzione

integer i
read *, i

if (i<100000) then
  print 100, i
else
  print 200, i
end if

100 format ("This is a big number", I10)
200 format ("This is a small number", I6)

end

o una variabile di carattere può essere usata come specificatore di formato

character(29), target :: big_fmt='("This is a big number", I10)'
character(30), target :: small_fmt='("This is a small number", I6)'
character(:), pointer :: fmt

integer i
read *, i

fmt=>big_fmt
if (i<100000) fmt=>small_fmt

print fmt, i

end

Funzioni di dichiarazione

Considera il programma

implicit none
integer f, i
f(i)=i

print *, f(1)
end

Qui f è una funzione di dichiarazione. Ha un tipo di risultato intero, prendendo un argomento fittizio intero. 1

Tale funzione di dichiarazione esiste all'interno dell'ambito in cui è definita. In particolare, ha accesso a variabili e costanti con nome accessibili in tale ambito.

Tuttavia, le funzioni di dichiarazione sono soggette a molte restrizioni e sono potenzialmente confuse (guardando un'occhiata casuale come una dichiarazione di assegnazione di elementi dell'array). Restrizioni importanti sono:

  • il risultato della funzione e gli argomenti fittizi devono essere scalari
  • gli argomenti fittizi sono nella stessa portata della funzione
  • le funzioni di istruzione non hanno variabili locali
  • le funzioni di istruzioni non possono essere passate come argomenti reali

I principali vantaggi delle funzioni di statement sono ripetuti dalle funzioni interne

implicit none

print *, f(1)

contains

  integer function f(i)
    integer i
    f = i
  end function

end

Le funzioni interne non sono soggette alle restrizioni sopra menzionate, anche se è forse interessante notare che un sottoprogramma interno non può contenere ulteriori sottoprogrammi interni (ma può contenere una funzione di istruzione).

Le funzioni interne hanno il loro ambito ma hanno anche un'associazione host disponibile.


1 Negli esempi di codice vecchio e reale, non sarebbe inusuale vedere gli argomenti fittizi di una funzione di istruzione digitati implicitamente, anche se il risultato ha un tipo esplicito.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow