Subprogramas

Subprogramas, comumente conhecidos na literatura geral de programação procedural de computadores por procedimento ou procedure, são um grupo de instruções que executam uma tarefa bem definida.

Os subprogramas podem ser chamados a partir do seu programa principal (ou de outros programas de escopo superior) e as informações (ou dados) podem ser transmitidas entre eles através de argumentos.

Existem dois tipos de subprogramas:

  • Funções
  • Subrotinas

Estes suprogramas podem ser de dois tipos, internos (dentro do
programa principal) ou externos (fora do programa principal). A
principal vantagem da opção de subprogramas externos é a possibilidade
de modularização em arquivos separados com finalidade de criação de
bibliotecas para compartilhamento.

Funções

Uma função é um procedimento que retorna uma quantidade única. Uma função não deve modificar seus argumentos.

A quantidade devolvida é conhecida como valor da função, e é denotado pelo nome da função.

Sintaxe

function name(arg1, arg2, ....)  
   

[declarations, including those for the arguments]

[executable statements]

end function [name]

O exemplo a seguir demonstra uma função chamada area_do_circulo. A função calcula a área de um círculo com o raio r.

program chama_func
implicit none
real :: a
real :: area_do_circulo !!! IMPORTANTE declarar o tipo função quando externa
a = area_do_circulo(2.0)
print *, “A área do circulo com raio 2.0 é “
print *, a
end program chama_func
! Esta função calcula a área de um círculo de raio r
function area_do_circulo(r)
implicit none
! argumentos fictícios
real :: area_do_circulo
! variaveis locais
real :: r
real :: pi
pi = 4 * atan (1.0)
! resultado da função
area_do_circulo = pi * r**2
end function area_do_circulo

view rawpf-subprogramas-01.f90 hosted with 

❤

 by GitHub

Quando você compilar e executar o programa acima, produz o seguinte resultado:

A área do circulo com raio 2.0 é 
   12.5663710   

NOTA: Você deve especificar que nenhuma variável seja de tipo implícito implicit none tanto no programa principal quanto no subprograma.

O argumento r na função chamada é chamado de argumento fictício dummy, entenda-o como argumento auxiliar.

A opção de retorno/resultado

Se quiser que o valor retornado para ser armazenado em algum outro nome que o nome da função, você pode usar a opção resultado result.

Você pode especificar o nome da variável de retorno como:

function name(arg1, arg2, ....) result (return_var_name)  
   

[declarations, including those for the arguments]

[executable statements]

end function [name]

Obs: Funções recursivas sempre exigem valor de retorno. Você seria capaz de se preguntar e responder o porquê?

Subrotina

A subrotina não retorna um valor, no entanto, pode modificar seus argumentos.

Sintaxe

subroutine name(arg1, arg2, ....)    
   

[declarations, including those for the arguments]

[executable statements]

end subroutine [name]

Chamando uma subrotina

Você precisa chamar uma subrotina utilizando a instrução de chamada call.

O exemplo a seguir demonstra a definição e uso de uma subrotina chamada “troca”, que troca os valores de seus argumentos:

program calling_func
implicit none
real :: a, b
a = 2.0
b = 3.0
Print *, “Before calling swap”
Print *, “a = “, a
Print *, “b = “, b
call swap(a, b)
Print *, “After calling swap”
Print *, “a = “, a
Print *, “b = “, b
end program calling_func
subroutine swap(x, y)
implicit none
real :: x, y, temp
temp = x
x = y
y = temp
end subroutine swap

view rawcalling_func.f90 hosted with 

❤

 by GitHub

Quando você compilar e executar o programa acima, produz o seguinte resultado:

Before calling swap
a = 2.00000000    
b = 3.00000000

After calling swap
a = 3.00000000    
b = 2.00000000   

Especificando a “intenção” dos Argumentos

O atributo intent permite que especificar a intenção com que argumentos são usados no subprograma. A tabela 1 apresenta as caracterísiticas desse atributo:

Tabela 1 – Uso do argumento intent em subprogramas Fortran

IntençãoSintaxeDescrição
entradaintent(in)usado como valor de entrada, não mudará no subprograma
saidaintent(out)usado como valor de saída, ele será alterado no subprograma
ambosintent(inout)Argumentos são ambos usados e substituídos

O exemplo seguinte demonstra esse conceito:

program calling_func
implicit none
real :: x, y, z, disc
x= 1.0
y = 5.0
z = 2.0
call intent_example(x, y, z, disc)
Print *, “O valor do discriminante vale”
Print *, disc
end program calling_func
subroutine intent_example (a, b, c, d)
implicit none
! dummy arguments
real, intent (in) :: a
real, intent (in) :: b
real, intent (in) :: c
real, intent (out) :: d
d = b * b – 4.0 * a * c
end subroutine intent_example

view rawcallling_func_intent.f90 hosted with 

❤

 by GitHub

Quando você compilar e executar o programa acima, produz o seguinte resultado:

O valor do discriminante vale
   17.0000000    

Subprogramas recursivos

Recursão ocorre quando uma linguagem de programação permite que você chamar uma função dentro da mesma função. Chamamos isso de chamada recursiva da função.

Quando um subprograma chama a si mesmo, direta ou indiretamente, ele é chamado de subprograma recursivo. Você deve declarar este tipo de subprograma precedendo-o da da palavra recursive antes de sua declaração.

NOTA Quando uma função é usada de forma recursiva, a opção de retorno ou resultado result obrigatoriamente deve ser usada.

Exemplo que calcula fatorial para um determinado número usando um subprograma recursivo:

program teste
integer :: fatorial
integer :: a
a = fatorial(5)
print *, a
end program teste
recursive function fatorial(n) result (fac)
integer :: n, fac
if (n == 0) then
fac = 1
else
fac = n * fatorial(n – 1)
endif
end function fatorial

view rawrecursive_external.f90 hosted with 

❤

 by GitHub

Subprogramas Internos

Quando um procedimento está contido dentro de um programa que chama o procedimento interno do programa, devemosprestar a atenção para a palavra chave contains.
A sintaxe de um programa que contém um procedimento interno é como se segue:

program program_name
implicit none
! type declaration statements
! executable statements
. . .
contains
! internal procedures
. . .
end program program_name

view rawinternal_subprogram.f90 hosted with 

❤

 by GitHub

O programa a seguir exemplifica esse conceito:

program mainprog
implicit none
real :: a, b
a = 2.0
b = 3.0
Print *, “Before calling swap”
Print *, “a = “, a
Print *, “b = “, b
call swap(a, b)
Print *, “After calling swap”
Print *, “a = “, a
Print *, “b = “, b
contains
subroutine swap(x, y)
real :: x, y, temp
temp = x
x = y
y = temp
end subroutine swap
end program mainprog

view rawsubprogramas_internos.f90 hosted with 

❤

 by GitHub

Quando você compilar e executar o programa acima, produz o seguinte resultado:

Before calling swap
a = 2.00000000    
b = 3.00000000    

After calling swap
a = 3.00000000    
b = 2.00000000   

Desafio

  • Ler o material sobre Subprogramas do curso CS201
  • Refletir respondendo às questões seguintes:
    1. Elabore um mapa conceitual sobre os subprogramas em Fortran exemplo para inspiração.
    2. Quais regras devem ser obedecidas em relação ao programa principal e a função e/ou subrotina?
    3. Com base no texto lido, quando seria mais apropriado o uso de funções ao invés de subrotinas?
    4. Qual foi o seu entendimento com respeito ao escopo das variáveis?
    5. Descreva a sintaxe básica e as características dos elementos dos subprogramas.
    6. Exemplifique a utilização de subprogramas desenvolvendo um código fonte em Fortran à sua escolha.
    Nível: Médio

IDPGPF-1820