2.6 Fortran 90

ISO/IEC 1539:1991

Nesta revisão da linguagem foram acrescidas novas funcionalidades, e algumas funcionalidades antigas foram melhoradas, porém o padrão Fortran 90 manteve a compatibilidade com o padrão Fortran 77.

Novas funcionalidades

O código fonte pode ser escrito nos formatos:

  • Fortran 77, onde as instruções são escritas entre as colunas 7 e 72, a coluna 6 é usada para indicar uma linha de continuação e a coluna 1 é usada para indicar uma linha de comentário;
  • Livre, onde não há colunas reservadas, podem ser adicionados comentários no final da linha e os espaços em branco têm significado sob certas circunstâncias: não é mais possível escrever “E N D” em vez de “END”, como se podia fazer antes. Para isso a extensão do arquivo deve ser .f90 e não .f, ou deve ser usada a opção de compilação -ffree-form no gfortran.

Os identificadores podem ter até 31 caracteres, e não mais até 6 caracteres, e podem conter o caractere sublinhado (_).

O comentário é precedido por uma caractere de exclamação (!).

Podem ser usados os caracteres “<” e “>” nas expressões relacionais:

Operador Equivalente Significando
.LT. < Menor que
.LE. <= Menor que ou igual
.EQ. == Igual a
.NE. /= Não igual a
.GT. > Maior que
.GE. >= Maior que ou igual

Os procedimentos podem ser recursivos se a palavra-chave RECURSIVE for especificada na linha de instrução FUNCTION ou SUBROUTINE.

Podem ser definidos tipos de dados compostos, como uma struct do C ou uma record do Pascal, que podem ser acessados como um todo ou somente um de seus componentes.

Podem ser definidos ponteiros como atributo para outros tipos de dados, e a memória pode ser alocada dinamicamente.

Os módulos permitem programar no estilo orientado a objeto, semelhante ao C++, e podem esconder variáveis globais não sendo mais necessário o uso da declaração COMMON.

A declaração NAMELIST foi adicionada ao padrão.

O tipo de dado CHARACTER pode representar uma cadeia de caracteres vazia, e pode haver superposição na atribuição. Uma cadeia de caracteres pode ser delimitada tanto por ' (aspas simples) quanto por " (aspas duplas).

Podem ser definidas três construções DO diferentes:

    DO
        bloco de declarações
    END DO
    
    DO i = inicio, fim, incremento
        bloco de declarações
    END DO
    
    DO WHILE (expressão lógica)
        bloco de declarações
    END DO

onde a declaração:

  • EXIT termina a execução do laço;
  • CYCLE termina a execução da iteração.

Pode ser definida a construção SELECT:

    SELECT CASE (expressão)
    CASE (seletor do caso)
        bloco de declarações
    CASE (seletor do caso)
        bloco de declarações
    ...
    CASE DEFAULT
        bloco de declarações padrão
    END SELECT

Exemplo:

    MODULE CACHORROS
        ! RAÇAS DE CACHORROS
        IMPLICIT NONE
        CHARACTER*16, PRIVATE :: CACHORRO(20)
        DATA CACHORRO / 'Beagle', 'Boxer', 'Bulldog', 'Bullmastiff',   &
                        'Chihuahua', 'Collie', 'Dálmata', 'Dobermann', &
                        'Labrador', 'Maltês', 'Mastiff', 'Pequinês',   &
                        'Perdigueiro', 'Pinscher', 'Poodle',           &
                        'Rottweiler', 'São Bernardo', 'Shar Pei',      &
                        'Teckel', 'Vira Lata' /
        CONTAINS
        FUNCTION E_CACHORRO(RACA) RESULT(ENCONTRADO)
            ! RETORNA VERDADEIRO SE A RAÇA DO CACHORRO FOR ENCONTRADA
            IMPLICIT NONE
            CHARACTER (LEN=*), INTENT(IN) :: RACA
            LOGICAL :: ENCONTRADO
            INTEGER :: I
            ENCONTRADO = .FALSE.
            BUSCA: DO I = 1, SIZE(CACHORRO)
                IF (RACA == CACHORRO(I)) THEN
                   ENCONTRADO = .TRUE.
                   EXIT BUSCA
                END IF
            END DO BUSCA
            RETURN
        END FUNCTION E_CACHORRO
    END MODULE CACHORROS
    MODULE GATOS
        ! RAÇAS DE GATOS
        IMPLICIT NONE
        CHARACTER*16, PRIVATE :: GATO(18)
        DATA GATO / 'Abissínio', 'Angorá', 'Azul Russo', 'Bengal',     &
                    'Burmese', 'Chartreux', 'Cornish Rex',             &
                    'Devon Rex', 'Egyptian Mau', 'Himalaio',           &
                    'Maine Coon', 'Munchkin', 'Oriental', 'Persa',     &
                    'Ragdoll', 'Savannah', 'Siamês', 'Sphynx' /
        CONTAINS
        FUNCTION E_GATO(RACA) RESULT(ENCONTRADO)
            ! RETORNA VERDADEIRO SE A RAÇA DO GATO FOR ENCONTRADA
            ! USA A FUNÇÃO DE ARRAY "ANY()"
            IMPLICIT NONE
            CHARACTER (LEN=*), INTENT(IN) :: RACA
            LOGICAL :: ENCONTRADO
            ENCONTRADO = ANY(GATO(1 : SIZE(GATO)) == RACA)
            RETURN
        END FUNCTION E_GATO
    END MODULE GATOS
    PROGRAM ANIMAIS
        ! INDICA SE É CACHORRO OU GATO CONFORME A RAÇA INFORMADA
        USE CACHORROS
        USE GATOS
        CHARACTER*16 :: RACA
        PRINT *, 'INFORME A RAÇA DO ANIMAL: (entre '''' se tiver espaço)'
        READ *, RACA
        IF (E_CACHORRO(RACA)) THEN
           PRINT *, 'É UM CACHORRO!'
        ELSE IF (E_GATO(RACA)) THEN
           PRINT *, 'É UM GATO!'
        ELSE
            PRINT *, 'RAÇA NÃO ENCONTRADA!'
        END IF
        STOP
    END PROGRAM ANIMAIS

Makefile:

animais: animais.f90
	gfortran animais.f90 -o animais
clean:
	rm animais

Execução:

pi@raspberrypi:~/F/animais $ ./animais 
 INFORME A RAÇA DO ANIMAL: (entre '' se tiver espaço)
Pequinês
 É UM CACHORRO!
pi@raspberrypi:~/F/animais $ ./animais 
 INFORME A RAÇA DO ANIMAL: (entre '' se tiver espaço)
Angorá
 É UM GATO!
pi@raspberrypi:~/F/animais $ ./animais 
 INFORME A RAÇA DO ANIMAL: (entre '' se tiver espaço)
'São Bernardo'
 É UM CACHORRO!
pi@raspberrypi:~/F/animais $ ./animais 
 INFORME A RAÇA DO ANIMAL: (entre '' se tiver espaço)
'Bicho do Mato'
 RAÇA NÃO ENCONTRADA!

Referências: