tabelas unidimensionais - fenix.tecnico.ulisboa.pt · 3 joão miguel da costa sousa 181 tabelas as...
TRANSCRIPT
1
João Miguel da Costa Sousa 177
Tabelas unidimensionais
� Tipos de dados simples:� real,
� inteiro,
� complexo, etc.
� Necessidade de processamento de vários valores simultaneamente pode tornar-se muito moroso. Exemplos:� Lista de resultados
� Conjunto de medidas
� matrizes, etc.
� Tipos de dados estruturados
� Tabelas
� Fichas
João Miguel da Costa Sousa 178
Exemplo: Detecção de avarias
� Este programa recebe os tempos de avaria de vários componentes e pretende-se saber como medida de fiabilidade o tempo médio de falha de cada um dos componentes. O programa deverá seguir os seguintes passos:� Calcular o tempo médio de avaria.� Imprimir a lista de avarias maior do que a média.� Ordenar os tempos de avaria de forma ascendente.
� A lista de avarias é assim processada várias vezes. São propostas três soluções:1. Utilizar uma variável para cada tempo de avaria2. Reler os dados sem atribuir um a cada variável3. Utilizar uma tabela unidimensional
2
João Miguel da Costa Sousa 179
Programa: Tempos_de_avaria1 (1)
� Esboço do programa:PROGRAM Tempos_de_avaria1
!-----------------------------------------------------------
! Descricao do programa e das variaveis utilizadas.
!-----------------------------------------------------------
IMPLICIT NONE
INTEGER :: EstadoAbertura, EstadoEntrada
REAL :: TempoAvaria_1, TempoAvaria_2, TempoAvaria_3, &
TempoAvaria_4, TempoAvaria_5, TempoAvaria_6, &
! etc.
TempoAvaria_48, TempoAvaria_49, TempoAvaria_50, &
Tempo_Medio_Avaria
! Le os tempos de avaria
OPEN (UNIT = 10, FILE = “TEMP_IN.DAT”, STATUS = “OLD”, IOSTAT = EstadoAbertura)
IF (EstadoAbertura > 0)
WRITE (*, *) “Ficheiro nao disponivel!”
ELSE
READ (10, *, IOSTAT = EstadoEntrada) &
TempoAvaria_1, TempoAvaria_2, TempoAvaria_3, TempoAvaria_4, TempoAvaria_5, &
! etc.
TempoAvaria_48, TempoAvaria_49, TempoAvaria_50, &
IF (EstadoEntrada > 0)
WRITE(*, *) “Erro na entrada de dados”
ELSE IF (EstadoEntrada < 0)
WRITE(*, *) “Dados insufucientes”
ELSE
João Miguel da Costa Sousa 180
Programa: Tempos_de_avaria1 (2)
Tempo_Medio_Avaria = &
(TempoAvaria_1 + TempoAvaria_2 + TempoAvaria_3 + &
TempoAvaria_4 + TempoAvaria_5, TempoAvaria_6, &
! etc.
TempoAvaria_46 + TempoAvaria_47 + TempoAvaria_48 + &
TempoAvaria_49 + TempoAvaria_50) / 50.0
WRITE (*, *) “Tempo medio de avaria =”, &
Tempo_Medio_Avaria
! Mostra tempos acima da média
IF (TempoAvaria_1 > Tempo_Medio_Avaria) &
WRITE (*, *) TempoAvaria_1
IF (TempoAvaria_2 > Tempo_Medio_Avaria) &
WRITE (*, *) TempoAvaria_2
!
! etc., etc., etc.
!
IF (TempoAvaria_50 > Tempo_Medio_Avaria) &
WRITE (*, *) TempoAvaria_50
! Apos 200 linhas de codigo, ordenar os valores?!!
! Deve existir uma forma melhor de programar!!
END PROGRAM Tempos_de_avaria1
� Outra solução:� Reler os dados várias vezes para cada um dos cálculos necessários.
3
João Miguel da Costa Sousa 181
Tabelas
� As soluções propostas são ineficientes; é necessária uma estrutura de dados para:� armazenar� organizar os dados de forma simples.
� Estrutura de dados deve poder ser acedida de forma não sequencial, ou ter um acesso directo.
� Estrutura pretendida: tabela (array).� Exemplo:
REAL, DIMENSION(50) :: TempoAvaria
� O compilador cria uma tabela com o nome TempoAvaria, consistindo em 50 espaços em memória do tipo REAL.
� Exemplo: TempoAvaria(34)
� o índice correspondendo ao elemento é 34.
João Miguel da Costa Sousa 182
Tabelas (cont.)
� Localização da tabela em memória:Memória
…
TempoAvaria(1) ←→
TempoAvaria(2) ←→
TempoAvaria(3) ←→
… …
TempoAvaria(50) ←→
…
� Índice deve ser uma variável ou expressão do tipo inteiro.� Leitura de tabelas:
READ (10, *) TempoAvaria
� é equivalente a:READ (10, *) TempoAvaria(1), (...), TempoAvaria(50)
4
João Miguel da Costa Sousa 183
Programa: Tempos_de_avaria2 (1)
PROGRAM Tempos_de_avaria2
!------------------------------------------------------------
! Programa que le uma lista de tempos de avaria, calcula o
! tempo medio de avaria, mostra uma lista de tempos de avaria
! maiores que a media. Identificadores:
! EstadoAbertura : estado da variavel para OPEN
! EstadoEntrada : estado da variavel para READ
! TempoAvaria : tabela unidimensional de tempos avaria
! NumeroVezes : dimensao da tabela (constante)
! I : indice
! Soma : somados tempos de avaria
! Tempo_Medio : media dos tempos de avaria
!
! Entradas: Lista com NumeroVezes de tempos de avaria
! Saidas: Informacao sobre o estado do ficheiro de dados,
! Tempo_Medio, e uma lista com tempos de avaria
! maiores que Tempo_Medio
!------------------------------------------------------------
IMPLICIT NONE
INTEGER, PARAMETER :: NumeroVezes = 50REAL, DIMENSION(NumeroVezes) :: TempoAvariaINTEGER :: EstadoAbertura, EstadoEntrada, I
REAL :: Soma, TempoMedio
WRITE (*, *) “Programa le”, NumeroVezes, “tempos de avarias &
&no ficheiro entrada.dat.”
OPEN (UNIT = 10, FILE = “entrada.dat”, STATUS = “OLD”, &
IOSTAT = EstadoAbertura)
IF (EstadoAbertura > 0)
WRITE (*, *) “*** Ficheiro nao disponivel! ***”
João Miguel da Costa Sousa 184
Programa: Tempos_de_avaria2 (2)
ELSE
! Le os tempos de avaria e armazena-os em TempoAvariaREAD (10, *, IOSTAT = EstadoEntrada) TempoAvariaIF (EstadoEntrada > 0)
WRITE(*, *) “*** Erro na entrada de dados ***”
ELSE IF (EstadoEntrada < 0)
WRITE(*, *) “*** Dados insufucientes ***”
ELSE
! Calcula o tempo medio de avaria
Soma = 0.0
DO I = 1, NumeroVezesSoma = Soma + TempoAvaria(I)
END DOTempoMedio = Soma / REAL(NumeroVezes)
WRITE (*, ‘(1X, “Tempo medio de falha =”, F6.1)’,&
TempoMedio
! Mostra lista de tempos maiores que a media
WRITE(*, *)
WRITE(*, *) “Lista de tempos maiores que a media:”
DO I = 1, NumeroVezesIF (TempoAvaria(I) > TempoMedio) THEN
WRITE (*, ‘(1X, F9.1)’, TempoAvaria(I)END IF
END DOEND IF
END IF
END PROGRAM Tempos_de_avaria2
5
João Miguel da Costa Sousa 185
Ficheiro de dados
�Listagem do ficheiro entrada.dat:
99.5, 133.8, 84.2, 217.5, 188.8, 103.1, 93.9, 165.0, 68.3
111.4, 88.8, 88.2, 90.1, 70.2, 150.5, 122.9, 138.8, 99.9
111.6, 155.7, 133.4, 122.2, 93.4, 101.5, 109.9, 103.3, 177.7
188.1, 99.8, 144.4, 87.5, 79.3, 190.2, 190.3, 170.1, 160.9
121.1, 95.6, 140.5, 177.2, 150.1, 140.3, 139.2, 113.8, 155.9
144.4, 88.3, 83.5, 101.1, 112.8
João Miguel da Costa Sousa 186
Exemplo de execução
> Programa le 50 tempos de avarias no ficheiro entrada.dat.
> Tempo medio de falha = 126.0
>
> Lista de tempos maiores que a media:
> 133.8
> 217.5
> 188.8
> 165.0
> 150.5
> 138.8
> 155.7
> 133.4
> 177.7
> 188.1
> 144.4
> 190.2
> 190.3
> 170.1
> 160.9
> 140.5
> 177.2
> 150.1
> 140.3
> 139.2
> 155.9
> 144.4
6
João Miguel da Costa Sousa 187
Leitura e escrita de tabelas
�Leitura e escrita de tabelas
� Exemplo leitura:READ (10, ‘(5F6.1)’) TempoAvaria
12345678901234567890123456789012345678901234567890
99.5 133.8 84.2 217.5 188.8
103.1 93.9 165.0 68.3 111.4
etc.
� Exemplo escrita:WRITE (20, ‘(1X 5F10.1)’) TempoAvaria
João Miguel da Costa Sousa 188
Ciclos DO implícitos
� Definição:
(lista, var_controlo = inicial, limite, passo)
� Onde lista corresponde à lista de variáveis, e var_controlo, inicial, limite e passo são as mesmas variáveis de um ciclo DO.
� Exemplo leitura:READ (10,*) (TempoAvaria(I), I=1, NumeroVezes)
� é equivalente a:READ (10,*) TempoAvaria(1), TempoAvaria(2),&
..., TempoAvaria(NumeroVezes)
� Exemplo escrita:WRITE (*,*) (TempoAvaria(I), I=1, NumeroVezes)
� é equivalente a:WRITE (*,*) TempoAvaria(1), TempoAvaria(2),&
...,TempoAvaria(NumeroVezes)
7
João Miguel da Costa Sousa 189
Definição de tabelas
Definição de tabelas compiladas_____________________________________________________________________
Forma:
tipo, DIMENSION(l:u) :: lista_nome_tabelas
outipo :: lista_especificadores_tabelas
� Onde:� a lista_nome_tabelas é uma lista de nomes de tabelas;� a lista_especificadores_tabelas é uma lista de especificadores
da forma:nome_tabela(l:u)
� Cada um dos identificadores da lista é uma tabela, cuja memória é atribuída (alocada) aquando da compilação do programa.
� Os índices vão de l a u são quaisquer inteiros. Se l é igual a 1, este valor pode ser omitido.
João Miguel da Costa Sousa 190
Exemplos de tabelas
� Exemplo anterior (TempoAvaria):REAL, DIMENSION(50) :: TempoAvaria
REAL, DIMENSION(1:50) :: TempoAvaria
REAL :: TempoAvaria(1:50)
REAL :: TempoAvaria(50)
� Exemplo 2:
INTEGER, PARAMETER :: LimInf_1 = -1, LimSup_1 = 3, &
LimInf_2 = 0, LimSup_2 = 5
INTEGER, DIMENSION(LimInf_1:LimSup_1) :: Gama
REAL, DIMENSION(LimInf_2:LimSup_2) :: Delta
� Gama tem 5 elementos e Delta 6 elementos.
8
João Miguel da Costa Sousa 191
Tabelas alocáveis
�Na versão anterior, é associado um bloco de memória para toda a tabela, o qual não pode ser alterado.
�Problemas:� Se tamanho indicado é maior do que o necessário, existe
memória desperdiçada
� Se tamanho indicado é menor do que o necessário, há erro de overflow da tabela.
�Fortran não permite alocar memória após a declaração da tabela
�Solução: alocar memória durante execução
João Miguel da Costa Sousa 192
Tabelas alocáveis
Definição de tabelas alocáveis____________________________________________________________________
Forma:
tipo, DIMENSION(:), ALLOCATABLE :: lista
outipo, DIMENSION(:) :: lista
ALLOCATABLE :: lista
� Onde a variável lista é uma lista de tabelas.
� Declara que o tamanho de cada uma das tabelas em lista será especificado durante a execução.
� Exemplo:
REAL, DIMENSION(:), ALLOCATABLE :: A, B
9
João Miguel da Costa Sousa 193
Instrução ALLOCATE
Instrução ALLOCATE____________________________________________________________________
Forma:
ALLOCATE(lista)
ouALLOCATE(lista, STAT = estado_variavel)
� Onde a variável lista é uma lista de especificações de tabelas da forma:nome_tabela(l:u)
� Atribui espaço em memória para cada uma das tabelas da lista.
� Na segunda forma, à variável estado_variavel é atribuído o valor zero se a alocação for bem sucedida. Se não existir mais memória ou a tabela já tiver sido previamente alocada, é atribuído um valor de erro.
� Existe uma pilha de memória disponível quando o programa começa a ser executado. Cada ALLOCATE vai utilizar espaço dessa memória (alocá-lo).
João Miguel da Costa Sousa 194
Instrução DEALLOCATE
� Como a memória é limitada, dever-se-á libertar espaço em memória sempre que este não é necessário.
Instrução DEALLOCATE____________________________________________________________________
Forma:
DEALLOCATE(lista)
ouDEALLOCATE(lista, STAT = estado_variavel)
� Onde a variável lista é uma lista de tabelas previamente alocadas.
� Liberta a memória previamente utilizada. À variável estado_variavel é atribuído o valor zero se a desalocação for bem sucedida. A memória libertada passa a estar disponível.
10
João Miguel da Costa Sousa 195
Programa: Tempos_de_avaria3 (1)
PROGRAM Tempos_de_avaria3
!----------------------------------------------------------------------------------
! Programa que le uma lista de tempos de avaria, calcula o tempo medio de avaria e
! mostra uma lista de tempos de avaria maiores que a media. E utilizada uma tabela
! alocada para guardar os tempos de avaria. Identificadores:
! NomeFicheiro : nome do ficheiro de dados
! EstadoAbertura : estado da variavel para OPEN
! EstadoEntrada : estado da variavel para READ
! EstadoAlocacao : estado da variavel para ALLOCATE
! TempoAvaria : tabela unidimensional de tempos avaria
! NumeroVezes : dimensao da tabela (variavel)! I : indice
! Soma : somados tempos de avaria
! Tempo_Medio : media dos tempos de avaria
!
! Entrada(teclado) : NomeFicheiro
! Entrada(ficheiro): NumeroVezes e lista com NumeroVezes de tempos de avaria
! Saidas: Tempo_Medio e uma lista com tempos de avaria maiores que Tempo_Medio
! Nota: Primeiro valor do ficheiro deve conter NumeroVezes
!-----------------------------------------------------------------------------------
IMPLICIT NONE
CHARACTER(20) :: NomeFicheiro
REAL, DIMENSION(:), ALLOCATABLE :: TempoAvaria
INTEGER :: EstadoAbertura, EstadoEntrada, EstadoAlocacao, NumeroVezes, I
REAL :: Soma, TempoMedio
! Le o nome do ficheiro de dados e abre-o para entrada
WRITE (*, ‘(1X, A)’, ADVANCE = “NO”) “Escreva o nome do &
&ficheiro de dados: ”
READ (*, *) NomeFicheiro
João Miguel da Costa Sousa 196
Programa: Tempos_de_avaria3 (2)
OPEN (UNIT = 10, FILE = NomeFicheiro, STATUS = “OLD”, IOSTAT = EstadoAbertura)
IF (EstadoAbertura > 0)
WRITE (*, *) “*** Ficheiro nao disponivel! ***”
ELSE
! Le o numero dos tempos de avaria e aloca uma tabela! com o numero de elementos a guardar os tempos de avariaREAD (10, *, IOSTAT = EstadoEntrada) NumeroVezes IF (EstadoEntrada > 0) WRITE(*, *) “*** Erro na entrada de dados ***”
ELSE IF (EstadoEntrada < 0) WRITE(*, *) “*** Dados insufucientes ***”
ELSEALLOCATE(TempoAvaria(NumeroVezes), STAT = EstadoAlocacao)
END IFIF (EstadoAlocacao /= 0)WRITE(*, *) “*** Memoria Insuficiente ***”
ELSE
! Le os tempos de avaria e armazena-os em TempoAvaria
READ (10, *, IOSTAT = EstadoEntrada) TempoAvaria
IF (EstadoEntrada > 0)
WRITE(*, *) “*** Erro na entrada de dados ***”
ELSE IF (EstadoEntrada < 0)
WRITE(*, *) “*** Dados insufucientes ***”
ELSE
! Calcula o tempo medio de avaria
Soma = 0.0
DO I = 1, NumeroVezes
Soma = Soma + TempoAvaria(I)
END DO
11
João Miguel da Costa Sousa 197
Programa: Tempos_de_avaria3 (3)
TempoMedio = Soma / REAL(NumeroVezes)
WRITE (*, ‘(/ 1X, “Para ”, I4, “tempos de avaria, ” &
/ 1X, “o tempo medio de avaria =”, F6.1)’) Numero Vezes, TempoMedio
! Mostra lista de tempos maiores que a media
WRITE(*, *)
WRITE(*, *) “Lista de tempos maiores que a media:”
DO I = 1, NumeroVezes
IF (TempoAvaria(I) > TempoMedio) THEN
WRITE (*, ‘(1X, F9.1)’) TempoAvaria(I)
END IF
END DO
! Liberta espaco em memoria de TempoAvaria
DEALLOCATE(TempoAvaria)
END IF
END IF
END IF
END PROGRAM Tempos_de_avaria3
� Hipótese de verificação de alocação para libertar a memória correspondente a uma dada variável:IF (ALLOCATED(TempoAvaria)) THEN
DEALLOCATE(TempoAvaria)
END IF
João Miguel da Costa Sousa 198
Processamento de tabelas
� As tabelas constantes são uma lista de valores entre (/ e /).
(/ valor_1, valor_2, ..., valor_k /)
� Exemplo 1:
(/ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 /)
� Podem ser dadas por um DO-implícito:
(/ valor-lista, controlo-DO-implícito /)
� Exemplo 2:
(/ (2*I, I = 1, 10) /)
12
João Miguel da Costa Sousa 199
Expressões e atribuições
� Operadores e funções são aplicáveis a tabelas com o mesmo número de elementos.
� Exemplos:INTEGER, DIMENSION(4) :: A, B
INTEGER, DIMENSION(0:3) :: C
INTEGER, DIMENSION(6:9) :: D
LOGICAL, DIMENSION(4) :: P
A = (/ 1, 2, 3, 4 /)
B = (/ 5, 6, 7, 8 /)
A = A + B
C = (/ -1, -3, -5, 7 /)
D = 2 * ABS(C) + 1
P = (C > 0) .AND. (MOD(B, 3) == 0)
� Atribuiçõesvariavel_tipo_tabela = expressao
� Valores da expressão atribuída podem ser:1. Uma tabela do mesmo tamanho da variável.2. Um valor simples. Neste caso o valor é atribuído a todos os elementos da
tabela.
João Miguel da Costa Sousa 200
Sub-tabelas
� Definição:nome_tabela(inferior:superior:passo)
ounome_tabela(vector_indices)
� Exemplo 1:INTEGER, DIMENSION(8) :: A
INTEGER, DIMENSION(4) :: B
INTEGER :: J
� SeA = (/ 11, 22, 33, 44, 55, 66, 77, 88 /)
� então:B = A(2:8:2)
� é a parte de A com os elementos 22, 44, 66 e 88.
� Exemplo 2:I = (/ 6, 5, 3, 8 /)
B = A(I)
� atribui a B os elementos 66, 55, 33, 88.B = A((/ 5, 3, 4, 3/))
� atribui a B os elementos 55, 33, 44, 33.
13
João Miguel da Costa Sousa 201
A construção WHERE
Construção WHERE____________________________________________________________________
Forma:
WHERE (exp_log_tab) var_tab_1 = exp_tab_1
ouWHERE (expressao_logica_tabela)
var_tabela_1 = expressao_tabela_1
...
var_tabela_m = expressao_tabela_m
ELSEWHERE
var_tabela_m+1 = expressao_tabela_m+1
...
var_tabela_n = expressao_tabela_n
END WHERE
� A variável expressao_logica_tabela é uma tabela de expressões de valores lógicos;
� Cada var_tabela_i tem a mesma dimensão de expressao_logica_tabela;� Na segunda forma ELSEWHERE é opcional.
João Miguel da Costa Sousa 202
Tabelas como argumentos
� Exemplo com construção WHERE:
INTEGER, DIMENSION(5) :: A = (/ 0, 2, 5, 0, 10/)
REAL, DIMENSION(5) :: B
WHERE (A > 0)
B = 1.0 / REAL(A)
ELSEWHERE
B = -1.0
END WHERE
� Atribui a B a sequência -1.0, 0.5, 0.2, -1.0, 0.1.
� Tabelas como argumentos� Subprogramas com processamento de tabelas intrínseco. Exemplos:
ALLOCATED(A)
MAXVAL(A)
MAXLOC(A)
PRODUCT(A)
SIZE(A)
SUM(A)
14
João Miguel da Costa Sousa 203
Subprogramas com tabelas
�Subprogramas definidos pelo programador� O argumento tipo tabela deve ser definido na unidade que
chama o subprograma.
� O argumento formal do tipo tabela deve ser declarado dentro do subprograma.
João Miguel da Costa Sousa 204
Programa: Media_de_uma_lista_1
PROGRAM Media_de_uma_Lista_1
!------------------------------------------------------------
! Programa que le uma lista de numeros Item(1), Item(2), …,
! Item(NumItems) e calcula a sua media usando a funcao Media.
! Os identificadores sao:
! Item : tabela uni-dimensional de numeros
! NumItems : numero de items (constante)
! Media : funcao que calcula a media de um conjunto de
! numeros
!
! Entradas : NumItems e a lista de numeros reais
! Saida : A media dos numeros
!------------------------------------------------------------
IMPLICIT NONE
INTEGER, PARAMETER :: NumItems = 10REAL, DIMENSION(NumItems) :: Item
WRITE (*, *) “Insira”, NumItems, “numeros reais:”
READ (*, *) Item
WRITE (*, ‘(1X, “Media de ”, I3, “numeros e:”, F6.2)’) &NumItems, Media(Item)
15
João Miguel da Costa Sousa 205
Media_de_uma_lista_1 (concl.)
CONTAINS
!-Media---------------------------------------------------! Funcao que calcula a media de elementos de uma tabela X ! Identificadores locais:! NumElementos: numero de elementos em X (constante)!! Recebe : Tabela X! Retorna : A media dos valores guardados em X!---------------------------------------------------------FUNCTION Media(X)
INTEGER, PARAMETER :: NumElementos = 10REAL, DIMENSION(NumElementos), INTENT(IN) :: XREAL :: Media
Media = SUM(X) / REAL(NumElementos)END FUNCTION Media
END PROGRAM Media_de_uma_Lista_1
� Exemplo de execução:> Insira 10 numero reais:
> 55, 88.5, 90, 71.5, 100, 66.5, 70.3, 81.2, 93.7, 41
> Media de 10 numeros e 75.77
João Miguel da Costa Sousa 206
Programa: Media_de_uma_lista_2
PROGRAM Media_de_uma_Lista_2
!------------------------------------------------------------
! Programa que le uma lista de numeros Item(1), Item(2), …,
! Item(NumItems) e calcula a sua media usando a funcao Media.
! Os identificadores sao:
! Item : tabela uni-dimensional de numeros
! NumItems : numero de items (constante)
! Media : funcao que calcula a media de um conjunto de
! numeros
!
! Entradas : NumItems e a lista de numeros reais
! Saida : A media dos numeros
!------------------------------------------------------------
IMPLICIT NONE
INTEGER, PARAMETER :: NumItems = 10
REAL, DIMENSION(NumItems) :: Item
WRITE (*, *) “Insira”, NumItems, “numeros reais:”
READ (*, *) Item
WRITE (*, ‘(1X, “Media de ”, I3, “numeros e:”, F6.2)’) &
NumItems, Media(Item, NumItems)
16
João Miguel da Costa Sousa 207
Media_de_uma_lista_2 (concl.)
CONTAINS
!-Media---------------------------------------------------
! Funcao que calcula a media de NumElementos de uma tabela
! X. O tamanho da tabela X (NumElementos) é passado como
! argumento.
!
! Recebe : Tabela X e NumElementos
! Retorna : A media dos valores guardados em X
!---------------------------------------------------------
FUNCTION Media(X, NumElementos)
INTEGER, INTENT(IN) :: NumElementos
REAL, DIMENSION(NumElementos), INTENT(IN) :: X
REAL :: Media
Media = SUM(X) / REAL(NumElementos)
END FUNCTION Media
END PROGRAM Media_de_uma_Lista_2
João Miguel da Costa Sousa 208
Tabela Item alocada
�A tabela Item poderia ser alocada:! ...
INTEGER :: NumItems, EstadoAlocacao
REAL, DIMENSION(:), ALLOCATABLE :: Item
REAL :: Media
WRITE (*, ‘(1X, A)’, ADVANCE = “NO”) &
“Quantos elementos existem no conjunto de dados? ”
READ (*, *) NumItems
ALLOCATE(Item(NumItems), STAT = EstadoAlocacao)
IF (EstadoAlocacao /= 0) THEN
WRITE (*, *) “*** Memoria insuficiente ***”
ELSE
WRITE (*, *) “Insira”, NumItems, “numeros reais:”
READ (*, *) Item
WRITE (*, ‘(1X, “Media de ”, I3, “numeros e:”, F6.2)’) &
NumItems, Media(Item, NumItems)
END IF
!...
17
João Miguel da Costa Sousa 209
Tabelas de dimensão pré-definida
� A dimensão da tabela actual é a dimensão da tabela formal (no subprograma).
Declaração:
DIMENSION(:)
ouDIMENSION(limite_inferior:)
� Onde limite_inferior especifica o limite inferior dos índices da tabela formal.
� Exemplo: No programa Media_de_uma_lista_2, a função média seria dada por:
! (...)
FUNCTION Media(X)
REAL, DIMENSION(:), INTENT(IN) :: X
REAL :: Media
Media = SUM(X) / REAL(SIZE(X))
END FUNCTION Media
João Miguel da Costa Sousa 210
Tabelas automáticas
� Um subprograma com tabelas de dimensão pré-definida pode necessitar de variáveis locais do tipo tabela.
� Usam-se tabelas automáticas neste caso, onde o seu tamanho varia com a chamada.
� A função SIZE dimensiona estas tabelas.� Exemplo:
!-Troca----------------------------------------------------
! Esta subrotina troca duas tabelas de dimensão pre-
! assumida. Tabela local utilizada:
! Temp : Tabela automatica utilizada para trocar A e B
!
! Aceita: Tabelas A e B
! Retorna: A e B com elementos trocados
!----------------------------------------------------------
SUBROUTINE Troca(A, B)
REAL, DIMENSION(:), INTENT(INOUT) :: A, B
REAL, DIMENSION(SIZE(A)) :: Temp
Temp = A
A = B
B = Temp
END SUBROUTINE Troca
18
João Miguel da Costa Sousa 211
Funções que retornam tabelas
� Exemplo: Inversão de valores duma tabela
PROGRAM Inversao_de_uma_Lista
!------------------------------------------------------------
! Programa que testa a funcao Inverte. Le uma lista de
! numeros Item(1), Item(2), …, Item(NumItems), chama a funcao
! Inverte, constroi uma lista na ordem inversa e mostra-a.
! Os identificadores sao:
! Item : tabela unidimensional de numeros
! NumItems : numero de items (constante)
! Inverte : funcao que inverte a tabela
!
! Entradas : NumItems e a lista de numeros inteiros
! Saida : A lista invertida
!------------------------------------------------------------
IMPLICIT NONE
INTEGER, PARAMETER :: NumItems = 10
REAL, DIMENSION(NumItems) :: Item
WRITE (*, ‘(1X, A, I3, A)’, ADVANCE = “NO”) &
“Insira”, NumItems, “numeros inteiros: ”
READ (*, *) Item
WRITE (*, *) “A lista por ordem inversa e dada por:”
WRITE (*, *) Inverte(Item)
João Miguel da Costa Sousa 212
Inversao_de_uma_lista (concl.)
CONTAINS
!-Inverte-------------------------------------------------! Funcao que inverte uma tabela X. Variaveis locais:! NumElementos : numero de elementos em X! I : indice!! Recebe : Tabela X de dimensão predefinida! Retorna : A tabela X invertida!---------------------------------------------------------FUNCTION Inverte(X)
INTEGER, DIMENSION(:), INTENT(IN) :: XINTEGER, DIMENSION(SIZE(x)) :: InverteINTEGER :: NumElementos, I
NumElementos = SIZE(X)DO I = 1, NumElementos
Inverte(I) = X(NumElementos - I + 1)END DO
END FUNCTION Inverte
END PROGRAM Inversao_de_uma_Lista
� Exemplo de execução:> Insira 10 numero inteiros: 1 2 3 4 5 6 7 8 9 10
> A lista por ordem inversa e dada por:
> 10 9 8 7 6 5 4 3 2 1
19
João Miguel da Costa Sousa 213
Algoritmos de ordenação
� Arranjo dos elementos de uma tabela de forma ascendente ou descendente.� Selecção simples� Ordenação rápida
� Ordenação por selecção simples
� Verifica a lista várias vezes, e de cada vez selecciona um elemento da lista colocando-o na posição correcta.
� Exemplo: ordenar de forma ascendente67, 33, 21, 84, 49, 50, 75
1. Localizar o elemento mais pequeno:
67, 33, 21, 84, 49, 50, 752. Trocá-lo com o primeiro:
21, 33, 67, 84, 49, 50, 753. Localizar o 2º elemento mais pequeno e ordená-lo (já se encontra na posição correcta
neste caso):
21, 33, 67, 84, 49, 50, 75(...) Repetem-se os passos até se obter a lista ordenada:
21, 33, 49, 50, 67, 75, 84
João Miguel da Costa Sousa 214
Ordenação por selecção simples
Algoritmo
� Algoritmo para ordenar uma lista de items X(1), X(2), …, X(N) de forma ascendente. Para ordenar de forma descendente procura o maior item em vez do menor de cada vez que a tabela é percorrida.
� Entrada: Lista X(1), X(2), …, X(N).
� Saída: Lista X(1), X(2), …, X(N) modificada ; os elementos estão na lista de forma ascendente.
Para I variando de 1 a N - 1, faz o seguinte:
� Na Iésima passagem, procura o ItemMaisPequeno na sublista X(I), …, X(N), e a sua respectiva posição LocalizacaoMaisPequeno.
� Troca ItemMaisPequeno com o item no princípio da lista.
� Atribui X(LocalizacaoMaisPequeno) o valor de X(I).
� Atribui X(I) o valor de X(LocalizacaoMaisPequeno).
20
João Miguel da Costa Sousa 215
Subrotina: Ordenacao_por_seleccao
!-Ordenacao_por_Seleccao-------------------------------------------------------------
! Esta subrotina ordena a tabela Item em ordem ascendente usando o algoritmo de
! ordenacao por seleccao simples. Para ordenar em ordem descendente dever-se-a trocar
! MINVAL por MAXVAL e MINLOC por MAXLOC. Variaveis locais:
! NumItems : numero de elementos na tabela Item
! ItemMaisPequeno : item mais pequeno da sublista actual
! MINLOC_tabela : tabela de um elemento dada por MINLOC
! LocalMaisPequeno: localizacao de ItemMaisPequeno
! I : índice
!
! Aceita: Tabela de Items
! Retorna: Tabela com items ordenados de forma ascendente
!--------------------------------------------------------------------------------------
SUBROUTINE Ordenacao_por_Seleccao(Item)
INTEGER, DIMENSION(:), INTENT(INOUT) :: Item
INTEGER :: NumItems, ItemMaisPequeno, LocalMaisPequeno, I
INTEGER, DIMENSION(1) :: MINLOC_tabela
NumItems = SIZE(Item)
DO I = 1, NumItems - 1
! Encontra o item mais pequeno na sublista Item(I),...,Item(NumItems)
ItemMaisPequeno = MINVAL(Item(I:NumItems))
MINLOC_tabela = MINLOC(Item(I:NumItems))
LocalMaisPequeno = (I - 1) + MINLOC_tabela(1)
! Troca ItemMaisPequeno com Item(I) no inicio sublista
Item(LocalMaisPequeno) = Item(I)
Item(I) = ItemMaisPequeno
END DO
END SUBROUTINE Ordenacao_por_Seleccao
João Miguel da Costa Sousa 216
Ordenação rápida
� Escolhe-se um pivot, e trocam-se todos os elementos inferiores para um lado e todos os superiores para outro.
� Lista é dividida em duas mais pequenas e o procedimento é repetido.� Esta estratégia de dividir-para-reinar é implementada recursivamente de
forma natural.� Método mais eficiente; é um dos mais rápidos.� Exemplo: ordenar de forma ascendente
50, 30, 20, 80, 90, 70, 95, 85, 10, 15, 75, 251. O elemento pivot é o 50. Elementos maiores que 50 passam para a sua direita e
inferiores para a esquerda10, 30, 20, 25,15, 50, 95, 85, 70, 90, 75, 80
2. A lista é dividida em duas sublistas a ser ordenadas:10, 30, 20, 25,15 e95, 85, 70, 90, 75, 80
3. Os passos 1 e 2 podem ser aplicado a cada uma das duas sublistas mais pequenas de forma recursiva. O caso âncora (caso mais simples) ocorre quando a lista é vazia ou tem apenas um elemento.
21
João Miguel da Costa Sousa 217
Ordenação rápida (concl.)
� O caso indutivo ocorre quando uma lista contém mais do que um elemento, onde:1. A lista é separada em duas sublistas.2. A sublista esquerda é ordenada recursivamente.3. A sublista direita é ordenada recursivamente.
� Subrotina: Ordenacao_Rapida!--------------------------------------------------------------------------------
! Nota: Nas subrotinas seguintes Item e uma tabela de
! tamanho predefinido; o programa principal deve:
! 1. conter uma subrotina como um subprograma interno,
! 2. importar a subrotina de um módulo, ou
! 3. conter um bloco de interface para esta subrotina.
!---------------------------------------------------------------------------------
!-Ordenacao_Rapida----------------------------------------------------------------
! Subrotina que ordena tabela usando o metodo de ordenacao rapida. Chama-a com
! Primeiro = limite inferior dos indices da tabela e Ultimo = limite superior.
! Variaveis locais:
! Media: ponto de separacao da tabela
!
! Aceita: Tabela Item
! Retorna: Tabela Item ordenada de forma ascendente
!---------------------------------------------------------------------------------
João Miguel da Costa Sousa 218
Subrotina: Ordenacao_Rapida
RECURSIVE SUBROUTINE Ordenacao_Rapida(Item, Primeiro, Ultimo)
INTEGER, DIMENSION(:), INTENT(INOUT) :: Item
INTEGER, INTENT(IN) :: Primeiro, Ultimo
INTEGER :: Medio
IF (Primeiro < Ultimo) THEN !Se tamanho lista >= 2
CALL Divide(Item, Primeiro, Ultimo, Medio) !Divide-a
CALL Ordenacao_Rapida(Item,Primeiro,Medio-1) !Ordena esq
CALL Ordenacao_Rapida(Item,Medio+1,Ultimo) !Ordena dir
END IF
END SUBROUTINE Ordenacao_Rapida
!-Divide-----------------------------------------------------
! Subrotina que divide uma lista em duas sublistas, usando o
! primeiro elemento como pivot, e retorna a posicao do
! elemento onde a lista e dividida. Variaveis locais:
! Esquerdo: posicao do primeiro elemento
! Direito : posicao do ultimo elemento
! Pivot : elemento pivot
! Troca : usado para trocar dois elementos
!
! Aceita: Tabela Item e posicoes Baixo e Alto do primeiro e
! do ultimo elementos.
! Retorna: Tabela Item ordenada de forma ascendente
!------------------------------------------------------------
SUBROUTINE Divide(Item, Baixo, Alto, Medio)
INTEGER, DIMENSION(:), INTENT(INOUT) :: Item
INTEGER, INTENT(IN) :: Baixo, Alto
INTEGER, INTENT(OUT) :: Medio
INTEGER :: Esquerdo, Direito, Pivot, Troca
22
João Miguel da Costa Sousa 219
Subrotina: Divide
Esquerdo = Baixo
Direito = Alto
Pivot = Item(Baixo)
! Repete enquanto Esquerdo e Direito nao se encontrarem
DO
IF (Esquerdo >= Direito) EXIT
! Procura da direita para a esquerda elemento < pivot
DO
IF (Esquerdo>=Direito .OR. Item(Direito)<Pivot) EXIT
Direito = Direito - 1
END DO
! Procura da esquerda para a direita elemento > pivot
DO
IF (Item(Esquerdo) > Pivot) EXIT
Esquerdo = Esquerdo + 1
END DO
! Se Esquerdo e Direito nao se encontraram, troca items
IF (Esquerdo < Direito) THEN
Troca = Item(Esquerdo)
Item(Esquerdo) = Item(Direito)
Item(Direito) = Troca
END IF
END DO
! Troca elemento na posicao de separacao com pivot
Item(Baixo) = Item(Direito)
Item(Direito) = Pivot
Medio = Direito
END SUBROUTINE Divide
João Miguel da Costa Sousa 220
Algoritmos de procura
� Consideram-se dois tipos:� Procura linear� Procura binária
� Procura linear� Começa no primeiro item da lista, e procura sequencialmente até o
elemento ou o fim da lista serem encontrados.Algoritmo
� Algoritmo de procura linear que encontra ItemProcurado na lista X(1), X(2), …, X(N). À variável Encontrado é atribuído o valor de verdadeiro e a Localizacao é atribuí-da a posição de ItemProcurado quando a procura é bem sucedida; caso contrário Encontrado tem o valor falso.
� Recebe: Lista X(1), X(2), …, X(N) e ItemProcurado.
� Retorna:Se ItemProcurado é encontrado na lista:
Encontrado = verdadeiro, eLocalizacao = posição de ItemProcurado.
Se ItemProcurado não é encontrado na lista:Encontrado = falso (e Localizacao = N + 1)
23
João Miguel da Costa Sousa 221
Procura linear
� Inicializa Localizacao a 1 e Encontrado a falso.� Enquanto Localizacao <= N e Encontrado é falso:
Se ItemProcurado = X(Localizacao) entãoAtribui a Encontrado o valor verdadeiro.
Caso contrário:Incrementa Localizacao de uma unidade.
� Exemplo: Procura numa cadeia de caracteres. !-Procura_Linear------------------------------------------------------
! Subrotina que procura na lista Item o ItemProcurado usando
! o metodo de procura linear. Se ItemProcurado for encontrado
! na lista, sao retornados: Encontrado com o valor de
! verdadeiro e a Localizacao do item; caso contrario
! Encontrado tem o valor de falso.
!
! Aceita: Tabela Item e ItemProcurado
! Retorna: Se ItemProcurado é encontrado na lista:
! Encontrado = verdadeiro e
! Localizacao = posição de ItemProcurado
! Caso contrario:
! Encontrado = falso
! (Localizacao = ultima posicao examinada)
!-----------------------------------------------------------------------
João Miguel da Costa Sousa 222
Subrotina: Procura_Linear
SUBROUTINE Procura_Linear(Item, ItemProcurado, Encontrado, Localizacao)
CHARACTER(*), DIMENSION(:), INTENT(IN) :: Item
CHARACTER(*), INTENT(IN) :: ItemProcurado
LOGICAL, INTENT(OUT) :: Encontrado
INTEGER, INTENT(OUT) :: Localizacao
INTEGER :: NumeroItems
NumItems = SIZE(Item)
Localizacao = 1
Encontrado = .FALSE.
! Enquanto Localizacao <= NumeroItems e Encontrado falso:
DO
IF ((Localizacao > NumeroItems) .OR. Encontrado) EXIT
! Se fim da lista ou item encontrado, termina procura
! Caso contrario testa o proximo elemento da lista
IF (ItemProcurado == Item(Localizacao)) THEN
Encontrado = .TRUE.
ELSE
Localizacao = Localizacao + 1
END IF
END DO
END SUBROUTINE Procura_Linear
24
João Miguel da Costa Sousa 223
Procura binária
� Procura que divide lista em 2 sublistas, escolhendo a que tem o item procurado.
� A procura linear requer n comparações, enquanto a procura binária requer log2n.
� Exemplo: lista com 1024 (=210) elementos� Procura binária: máximo 10 comparações.� Procura linear: máximo 1024 comparações.
Algoritmo� Algoritmo de procura binária na lista X(1), X(2), …, X(N) ordenada de forma
ascendente. À variável Encontrado é atribuído o valor de verdadeiro e a Localizacaoé atribuí-da a posição de ItemProcurado quando a procura é bem sucedida; caso contrário Encontrado tem o valor falso.
� Recebe: Lista X(1), X(2), …, X(N) e ItemProcurado.� Retorna:
Se ItemProcurado é encontrado na lista:Encontrado = verdadeiro, eLocalizacao = posição de ItemProcurado.
Se ItemProcurado não é encontrado na lista:Encontrado = falso
João Miguel da Costa Sousa 224
Algoritmo de procura binária
� Inicializa Primeiro a 1 e Ultimo a n. Estes valores repre-sentam as posições do primeiro e do último items da sublista onde a procura está a ser efectuada.
� Inicializa Encontrado com o valor lógico falso. � Enquanto Primeiro <= Ultimo e Encontrado é falso:
� Encontra a posição do meio na sublista, atribuindo a Meio o valor inteiro de (Primeiro + Ultimo) / 2.
� Compara ItemProcurado com X(Meio). Existem três possibilidades:
� ItemProcurado < X(Meio): ItemProcurado está na primeira metade da sublista. Atribui a Ultimo o valor Meio - 1.
� ItemProcurado > X(Meio): ItemProcurado está na segunda metade da sublista. Atribui a Primeiro o valor Meio + 1.
� ItemProcurado = X(Meio): ItemProcurado foi encontrado. Atribui a Localizacao o valor Meio e a Encontrado o valor verdadeiro.
� Exemplo: Procura numa cadeia de caracteres.
25
João Miguel da Costa Sousa 225
Subrotina: Procura_Binaria
!-Procura_Binaria----------------------------------------------------------
! Subrotina que procura na lista Item o ItemProcurado usando
! o metodo de procura binaria. Se ItemProcurado e encontrado
! na lista sao retornados: Encontrado com o valor de
! verdadeiro e a Localizacao do item; caso contrario
! Encontrado e falso. Esta subrotina e aplicada a cadeias de
! caracteres. Variaveis locais usadas:
! Primeiro : primeiro item a (sub)lista sob procura
! Ultimo : ultimo item a (sub)lista sob procura
! Meio : item do meio na (sub)lista sob procura
!
! Aceita: Tabela Item e ItemProcurado
! Retorna: Se ItemProcurado é encontrado na lista:
! Encontrado = verdadeiro e
! Localizacao = posição de ItemProcurado
! Caso contrario:
! Encontrado = falso
! (e Localizacao = ultima posicao examinada)
!-------------------------------------------------------------------------
SUBROUTINE Procura_Binaria(Item, ItemProcurado, Encontrado, Localizacao)
CHARACTER(*), DIMENSION(:), INTENT(IN) :: Item
CHARACTER(*), INTENT(IN) :: ItemProcurado
LOGICAL, INTENT(OUT) :: Encontrado
INTEGER, INTENT(OUT) :: Localizacao
INTEGER :: Primeiro, Ultimo, Meio
João Miguel da Costa Sousa 226
Subrotina: Procura_Binaria
Primeiro = 1
Ultimo = SIZE(Item)
Encontrado = .FALSE.
! Enquanto Primeiro <= Ultimo e Encontrado falso faz:
DO
IF ((Primeiro > Ultimo) .OR. Encontrado) EXIT
! Se fim da lista ou item encontrado, termina procura
! Caso contrario continua com o seguinte procedimento:
Meio = (Primeiro + Ultimo) / 2
IF (ItemProcurado < Item(Meio)) THEN
Ultimo = Meio - 1
ELSE IF (ItemProcurado > Item(Meio)) THEN
Primeiro = Meio + 1
ELSE
Encontrado = .TRUE.
Localizacao = Meio
END IF
END DO
END SUBROUTINE Procura_Binaria
� Exercício: Desenvolver o mesmo algoritmo de forma recursiva.
26
João Miguel da Costa Sousa 227
Tabelas multidimensionais
� Tabelas podem ser ordenadas por linhas, colunas, etc. Para isso são necessárias tabelas multi-dimensionais.
� Exemplo: tabela com temperaturas em 3 locais diferentes a 4 horas do dia:
Localização
Tempo 1 2 3
1 65.5 68.7 62.02 68.8 68.9 64.53 70.4 69.4 66.34 68.5 69.1 65.8
� Declaração:
REAL, DIMENSION(4, 3) :: Temperatura
ou:REAL, DIMENSION(1:4, 1:3) :: Temperatura
� reserva 12 espaços em memória para a tabela.Temperatura(2,3)
� refere-se ao elemento da 2ª linha e 3ª coluna.
João Miguel da Costa Sousa 228
Declaração de tabelas genéricas
Declaração de tabelas compiladas_______________________________________________________________________________________________
Forma:
tipo, DIMENSION(l1:u1, l2:u2,..., lk:uk) :: lista_nome_tabelas
outipo :: lista_especificadores_tabelas
� A lista_nome_tabelas é uma lista de nomes de tabelas separadas por vírgulas;
� A lista_especificadores_tabelas é uma lista de especificadores da forma:
nome_tabela(l1:u1, l2:u2,..., lk:uk)
� O número k de dimensões (rank) é no máximo sete.� Cada par l
i:u
ideve ser um parte de constantes inteiras especificando os
limites dos valores do índice i de li
a ui; l
ipode ser omitido se o seu
valor é 1.
27
João Miguel da Costa Sousa 229
Tabelas n-dimensionais: exemplos
� Cada um dos identificadores da lista é uma tabela k-dimensional, cuja memória é atribuída (alocada) aquando da compilação do programa.
� Exemplos:REAL, DIMENSION(1:2, -1:3) :: Gamma
REAL, DIMENSION(0:2, 0:3, 1:2) :: Beta
INTEGER, DIMENSION(5:12) :: Kappa
ouREAL :: Gamma(1:2,-1:3), Beta(0:2,0:3,1:2)
INTEGER :: Kappa(5:12)
� Tabela Gamma bidimensional 2 × 5, com o primeiro índice de 1 a 2 e o segundo de -1 a 3
� Tabela Beta tridimensional 3 × 4 × 2� Tabela Kappa unidimensional com índices de 5 a 12
João Miguel da Costa Sousa 230
Tabelas n-dimensionais alocáveis
Definição de tabelas alocadas____________________________________________________________________
Forma:
tipo, DIMENSION(:, …,:), ALLOCATABLE :: lista
outipo, DIMENSION(:, …,:) :: lista
ALLOCATABLE :: lista
� A variável lista é uma lista de tabelas;� A dimensão k (rank) é no máximo sete.� Declara que o tamanho de cada uma das tabelas em lista é k-dimensional,
onde k é o número de “:” na especificação de DIMENSION. O número de índices em cada dimensão, chamada a extensão da tabela, será especificado durante a execução.
� Exemplos:REAL, DIMENSION(:, :, :), ALLOCATABLE :: Beta
REAL, DIMENSION(:,:), ALLOCATABLE :: Gamma
28
João Miguel da Costa Sousa 231
Alocação n-dimensional
Instrução ALLOCATE____________________________________________________________________
Forma:
ALLOCATE(lista)
ouALLOCATE(lista, STAT = estado_variavel)
� A variável lista é dada por:nome_tabela(l
1:u
1, l
2:u
2, …, l
k:u
k)
� Atribui espaço em memória para cada uma das k-dimensionais tabelas da lista. Todas as definições anteriores permancem válidas.
� À variável estado_variavel é atribuído o valor zero se a alocação for bem sucedida. Se não existir mais memória ou a tabela já tiver sido previamente alocada, é atribuído um valor de erro.
� Exemplo:ALLOCATE(Beta(0:2, 0:3, 1:2), Gamma(1:N,-1:3), &
STAT = EstadoAlocacao)
João Miguel da Costa Sousa 232
Entrada/Saída de tabelas
� Processamento elemento a elemento� tabelas unidimensionais: ordem sequencial� tabelas bidimensionais:
�por linha - 1ª linha processada em 1º lugar, seguida pelas linhas seguintes.
� Exemplo: A(1:2, 1:3)A(1, 1)
A(1, 2)
A(1, 3)
A(2, 1)
A(2, 2)
A(2, 3)
�por coluna - 1ª coluna processada em 1º lugar� Exemplo: A(1:2, 1:3)A(1, 1)
A(2, 1)
A(1, 2)
A(2, 2)
A(1, 3)
A(2, 3)
29
João Miguel da Costa Sousa 233
Entrada/Saída de tabelas (cont.)
�O Fortran processa as tabelas por coluna por defeito (primeiros índices são percorridos primeiro).
�Tabelas multidimensionais: usam ordem por elemento de tabela.
�Tipos de Entrada/Saída com tabelas:� Utilizando um ciclo DO� Utilizando o nome da tabela� Utilizando um DO implícito� Utilizando uma secção da tabela
�E/S com ciclos DO� utilizam-se ciclos DO encadeados
João Miguel da Costa Sousa 234
Exemplo de leitura de tabelas
� Exemplo: ler a tabela A declarada por:INTEGER, DIMENSION(3, 4) :: Tabela
� e que é dada por:
33788948
461001099
25325677
� As instruções seguintes lêem a tabela:DO Linha = 1, 3
DO Coluna = 1, 4
READ (*, *) Tabela(Linha, Coluna)
END DO
END DO
� Lê a primeira linha em primeiro lugar, etc.
30
João Miguel da Costa Sousa 235
E/S com ciclos DO
� Para ler por colunas:DO Coluna = 1, 4
DO Linha = 1, 3
READ (*, *) Tabela(Linha, Coluna)
END DO
END DO
�E/S utilizando o nome da tabela�Exemplo:READ (*, *) Tabela
� lê por colunas. Se os dados de entrada forem:77, 99, 48, 56, 10, 89
32, 100, 78, 25, 46, 33
� o valor atribuído a Tabela será a matriz dada na página anterior.
João Miguel da Costa Sousa 236
Saída com nome de tabela
� Exemplo escrita:WRITE (*, ‘(1X, 4I5/)’) Tabela
� coloca os elementos por colunas, produzindo a seguinte saída:
77 99 48 56---------------------
---------------------
10 89 32 100---------------------
---------------------
78 25 46 33---------------------
---------------------
� É de notar que a disposição dos elementos é diferente da matriz Tabelaoriginal (pág. 234)!
31
João Miguel da Costa Sousa 237
Ciclos DO implícitos
� Definição:
(lista, var_controlo = inicial, limite, passo)
� Onde lista corresponde à lista de variáveis de entrada/saída, e var_controlo, inicial, limite e passo são as mesmas variáveis de um ciclo DO.
� Podem ser utilizados ciclos DO implícitos dentro de outros ciclos DOímplicitos.
� Exemplo leitura:READ(*,*) ((Tabela(Linha,Col), Col=1,4), Linha=1,3)
� é equivalente a:READ(*,*) (Tabela(Linha,1),Tabela(Linha,2), &
Tabela(Linha,3),Tabela(Linha,4), Linha=1,3)
� e a:READ(*,*) (Tabela(1,1),Tabela(1,2),Tabela(1,3),Tabela(1,4), &
(Tabela(2,1),Tabela(2,2),Tabela(2,3),Tabela(2,4), &
(Tabela(3,1),Tabela(3,2),Tabela(3,3),Tabela(3,4)
João Miguel da Costa Sousa 238
Ciclos DO implícitos (concl.)
� A leitura por colunas é dada por:READ(*,*) ((Tabela(Linha,Col), Linha=1,3), Col=1,4)
� Uso de parêntesis e vírgulas são importantes para definir os ciclos a executar primeiro.
� READ é executado só uma vez; as variáveis podem ser inseridas numa linha ou várias, é indiferente.
� Escrita com ciclos DO� Combinam-se os DO com os DO ímplicitos
� Exemplo:DO Linha = 1, 3
WRITE(*, ‘(1X, 4I5)’) (Tabela(Linha,Col), Col=1,4)
END DO
� produz:77 56 32 25
---------------------
99 10 100 46---------------------
48 89 78 33---------------------
32
João Miguel da Costa Sousa 239
Processamento tabelas
� Tabelas constantes� Tabelas unidimensionais podem ser redimensionadas para tabelas
multidimensionais:
RESHAPE(tabela_fonte,forma,preenche,ordem)
� Retorna tabela derivada de tabela_fonte, com a forma especificada, seguida por elemen-tos da tabela preenche, se necessário. A tabela ordem especifica a ordem variação dos índices.
� Argumentos preenche e ordem são opcionais.
� Exemplo 1:A = RESHAPE((/ 11,22,33,44,55,66 /), (/2, 3/))
� ouA = RESHAPE((/ 11*N, N = 1, 6 /), (/2, 3/))
� atribui a A a matriz 2 × 3:
664422
553311
João Miguel da Costa Sousa 240
Tabelas constantes (exemplos)
� Exemplo 2:A = RESHAPE((/ 11,22,33,44,55,66 /), (/2, 3/), &
ORDER = (/2, 1/))
� atribui a A a matriz:
665544
332211
0044
332211
� Exemplo 3:A = RESHAPE((/ 11,22,33,44 /), (/2, 3/), &
PAD = (/0 , 0/), ORDER = (/2, 1/))
� ouA = RESHAPE((/ 11,22,33,44 /), (/2, 3/), &
(/0 , 0/), (/2, 1/))
� atribui a A a matriz:
33
João Miguel da Costa Sousa 241
Expressões e sub-tabelas
� Expressões com tabelas� Exemplo:
INTEGER, DIMENSION(2,2) :: A,B
� sendo A uma matriz de 2 × 2 dada por:
−
−
10
128
−
−
11
2515
� a instruçãoB = 2*A + 1
� atribui a B a matriz:
� Sub-tabelas são definidas como:nome_tabela(seccao_sub-indices)
� onde cada item na seccao_sub-indices é um índice, ou um vector de índices.
João Miguel da Costa Sousa 242
Sub-tabelas (exemplos)
� Exemplo:
INTEGER, DIMENSION(2,3) :: A
6655
3322
3322
6655
11 22 33
44 55 66A
=
� Exemplo sub-tabela 1:A(1:2:1, 2:3:1)
A(:, 2:3)
� é a tabela de 2 × 2 dada pelas 2 últimas colunas de A:
� Exemplo sub-tabela 2:A(2, 1:3:1)
A(2, :)
� é a tabela:
� Exemplo sub-tabela 3:A((/ 2, 1 /), 2:3)
[ ]44 55 66
34
João Miguel da Costa Sousa 243
Atribuição a tabelas n-dimensionais
variavel_tabela = expressao
� onde expressao pode ser:� uma tabela da mesma dimensão� um valor simples
� Exemplo 1:INTEGER, DIMENSION(2,3) :: A
INTEGER, DIMENSION(3,2) :: B
� Instrução 1:A = 0
� retorna:
000
000
00
00
00
� Instrução 2:B = RESHAPE(A, (/3 ,2/))
� retorna a tabela:
João Miguel da Costa Sousa 244
Atribuição a tabelas (exemplos)
� Instrução 3:A(:, 2:3) = RESHAPE((/ I**2, I=1,4) /), (/2,3/))
� muda A para:
1640
910
0.50.100.0
0.00.20.1
2.01.00.0
0.05.00.1
� Exemplo 2:REAL, DIMENSION(2,3) :: Alfa, Beta
� Alfa é dado por:
� Exemplo com a instrução WHERE :WHERE (Alfa /= 0)
Beta = 1.0 / REAL(Alfa)
ELSEWHERE
Beta = 0.0
END WHERE
retorna tabela Beta:
35
João Miguel da Costa Sousa 245
Funções com tabelas n-dimensionais
� Funções intrínsecas - mais usadas:� ALLOCATED(A)
� MATMUL(A, B)
� MAXVAL(A, D)
� MAXLOC(A)
� MINVAL(A, D)
� MINLOC(A)
� PRODUCT(A, D)
� RESHAPE(A, S, P, O)
� SHAPE(A)
� SUM(A, D)
� SPREAD(A, D, N)
� TRANSPOSE(A)
João Miguel da Costa Sousa 246
Tabelas definidas pelo programador
� Os parâmetros actuais e formais do tipo tabela devem ter o mesmo tipo e formato.
� Existem 3 formas de definir tabelas dentro de subprogramas.
1. Tabela definida explicitamente em dimensão e extensão no subprograma.
2. Subprograma recebe a extensão das dimensões da tabela como argumentos.
3. Tabela recebe uma tabela de dimensões pré-assumidas.
� Estas três formas são extrapolações das definições para tabelas unidimensionais
36
João Miguel da Costa Sousa 247
Processamento de matrizes
� Matriz: tabela bidimensional de m × n.� Operações em Fortran são efectuadas elemento a elemento:
� Soma:
A + B
� Subtracção:
A - B
� Multiplicação:
A * B
� A multiplicação uma matriz A de m × n por outra B de n × p, é dada por:
MATMUL(A, B)
� Outras operações como a transposta são dadas por funções intrínsecas.