Algoritmos –
Modularização
Modularização

Sempre é possível dividir problemas grandes e
complicados em problemas menores e de solução
mais simples. A decomposição de um problema é
fator determinante para a redução da sua
complexidade.

Um algoritmo que envolve um problema grande
pode ser dividido em um algoritmo principal e em
diversos subalgoritmos ou módulos (tantos
quantos forem necessários ou convenientes).
Modularização

O algoritmo principal é aquele por onde começa
a execução, e chama, eventualmente, os demais
subalgoritmos.

Subalgoritmo é um algoritmo que, geralmente,
resolve um pequeno problema, e que está
subordinado a um outro algoritmo que solicitará
seu acionamento. É possível que um subalgoritmo
chame outro subalgoritmo.
Construindo sub-algoritmos
Critérios para orientar o processo de decomposição.




Dividir o problema em suas partes principais.
Analisar a divisão obtida para garantir coerência.
Se alguma parte ainda permanecer complexa, subdividi-la mais.
Analisar o resultado para garantir entendimento e
coerência.
Vantagens da Modularização

Dividir problemas grandes em vários problemas
menores, de baixa complexidade.
 Número pequeno de variáveis
 Poucos caminhos de controle (caminhos do
início ao fim)

Possibilidade de utilizar-se soluções gerais para
classes de problemas em lugar de soluções
específicas para problemas particulares.
 Reusabilidade
 Solucionar uma única vez o problema
Vantagens da Modularização

Permite delimitar o escopo (nivel de abrangência)
de variáveis.
 Variáveis locais.

Evita a repetição, dentro de um mesmo algoritmo,
de uma sequência de ações em diferentes pontos.
Variáveis globais e locais



Todo módulo é constituído por um sequência de
comandos que operam sobre um conjunto de
variáveis que podem ser globais ou locais.
Variáveis globais : Podem ser usadas em módulos
internos a outro módulo do algoritmo onde foram
declaradas.
Variáveis locais: Podem ser usadas no módulo do
algoritmo onde foram declaradas. Elas não
possuem significado fora deste módulo.
Variáveis globais e locais





Uma variável local é criada (alocada na memória)
no momento em que o sub-algoritmo que a define
é chamado
Uma variável local é liberada da memória no
momento em que o sub-algoritmo que a define
termina
Uma variável local somente existe (só pode ser
utilizada) dentro do subalgoritmo que a define
Caso um mesmo identificador (nome de variável)
seja declarado em sub-algoritmos distintos, esses
identificadores são considerados distintos entre si
(variáveis distintas)
O uso de variáveis locais minimiza a ocorrência de
“efeitos colaterais” : o programador pode definir e
utilizar as variáveis que desejar em um subalgoritmo sem interferir com outros subalgoritmos
Tipos de sub-algoritmos

Sintaxe de um algoritmo modularizado
Algoritmo <nome>
Definição de tipos
Declaração de variáveis globais
Definição de módulos
Inicio
Conjunto de ações do algoritmo principal
(incluidas as chamadas aos módulos)
Fim

Tipos de Sub-algoritmos:
 Funções (functions)
 Procedimentos (procedures)
Procedimentos
Procedimento:
 Um conjunto de ações que não irá devolver
valores ao (sub)algoritmo chamador.

Forma geral de um procedimento (sintaxe):
Procedimento <nome>(<parâmetros>)
Declaração de variáveis locais do procedimento
Inicio
Comandos do procedimento
Fim

Procedimentos
Chamada de um procedimento (sintaxe):
Nome_procedimento(argumentos)
 Quando o nome de um procedimento é
encontrado, ocorre um desvio no (sub)algoritmo
para que os comandos do procedimento sejam
executados. Ao término do subalgoritmo, a
execução retornará ao ponto subsequente a da
chamada do Procedimento.

Procedimentos

Juntando definição e chamada de um procedimento :
Algoritmo <nome_algoritmo>
Definição de tipos
Declaração de variáveis globais
Procedimento <nome_procedimento>(<parâmetros>)
Declaração de variáveis locais do procedimento
Inicio
Comandos do procedimento
Fim
/* algoritmo principal*/
Inicio
Comandos do algoritmo principal
nome_procedimento(argumentos)
Comandos do algoritmo principal
Fim
Procedimentos

Exemplo 1: Faça um algoritmo que dado um valor real
global x, chame um procedimento que calcula o quadrado
de x.
Algoritmo <Quad>
real: x
Procedimento Quadrado()
real: z
Início
z ← x*x
Escreva (“O quadrado do número é =“,z)
Fim
Início
Escreva (“Digite um número: “)
Leia ( x )
Quadrado()
Fim
Procedimentos

Exemplo 2 (muito simples com finalidade de explicar a
diferença entre variáveis locais e globais) : Faça um
algoritmo que use um procedimento para ler o nome de
uma pessoa e outro para mudá-lo.
Algoritmo <EscreveNome>
literal: nome
Procedimento le_nome()
Início
Leia (nome)
Fim
Procedimento muda_nome()
Inicio
escreva (“Vamos mudar o nome”)
leia (nome)
Fim
Início
Le_nome
Escreva (nome)
Muda_nome
Escreva (nome)
Procedimentos

Exemplo 3 (muito simples com finalidade de explicar a diferença
entre variáveis locais e globais) : Faça um algoritmo que use um
procedimento para ler o nome de uma pessoa e outro para mudá-lo
(use nome como var local)
Algoritmo <EscreveNome>
literal: nome
Procedimento le_nome()
Início
Leia (nome)
Fim
Procedimento muda_nome()
literal:nome
Inicio
escreva (“Vamos mudar o nome”)
leia (nome)
Fim
Início
Le_nome
Escreva (nome)
Muda_nome
Escreva (nome)
Procedimentos

No exemplo 3, a variável global nome e a variável
local nome representam posições de memória
totalmente diferentes, logo, qualquer mudança no
conteúdo da variável local, não afetará o conteúdo
da variavel global.
Parâmetros

Parâmetros são canais pelos quais se estabelece
uma comunicação bidirecional entre um
subalgoritmo e o algoritmo chamador (algoritmo
principal ou outro subalgoritmo). Os dados são
passados pelo algoritmo chamador através de
argumentos (parâmetros reais), e são
recepcionados por meio de parâmetros formais.

Parâmetros Formais: São os nomes simbólicos
introduzidos no cabeçalho dos subalgoritmos,
usados na definição dos parâmetros do mesmo.
Dentro de um subalgoritmo trabalha-se com estes
nomes da mesma forma como se trabalha com
variáveis locais ou globais.
Parâmetros Reais (ou argumentos):São aqueles
que substituem os parâmetros formais quando da
chamada do subalgoritmo.

Parâmetros


Passagem de parâmetros
Por valor ("by value")
O argumento da chamada (parâmetro real) é
avaliado, gerando um valor que é copiado para a
variável declarada na função (parâmetro formal)
Qualquer alteração do parâmetro formal não é
"transmitida" para o a variável do argumento
O argumento da chamada (parâmetro real) pode
ser uma constante, uma variável ou uma
expressão:
5, v1, v1+5-v2
Parâmetros

Exemplo:
Algoritmo <teste>
Inteiro:x
Procedimento porvalor(inteiro:a)
Inicio
a←5
Fim
Inicio
x ← 10
porvalor(x)
escreva (x)
Fim
Parâmetros




por referência ("by reference")
O argumento da chamada (parâmetro real) tem que
ser uma variável: v1, v2 ...
A variável do argumento (parâmetro real) é
associada com a variável declarada no
subalgoritmo (parâmetro formal) durante a
execução do subalgoritmo.
Qualquer alteração da variável do subalgoritmo
(parâmetro formal) acontece também na variável
do argumento.
Parâmetros

Exemplo:
Algoritmo <teste>
Inteiro:x
Procedimento porreferencia(inteiro:&a)
Inicio
A←5
Fim
Inicio
x ← 10
porreferencia(&x)
escreva (x)
Fim
* Na nossa matéria, o símbolo & indicará a
passagem por referência, na definição do
procedimento, e também na chamada do mesmo.
Funções


Função
O conceito de funções é originário da idéia de
função matemática, onde um valor é calculado a
partir de outro(s) valor(es) fornecido(s) à função.
Forma geral de uma função (sintaxe):
Função tipo <nome>(<parâmetros-formais>)
Declaração de variáveis locais da função
Inicio
Comandos
Fim
onde, tipoé o tipo do valor que será retornado
lista-de-parâmetros-formais é a lista das variáveis
(com seus tipos) que recepcionam as variáveis
fornecidas quando da chamada da função

Funções
Chamada de uma função (sintaxe):
nome(lista-de-parâmetros-reais)
onde, lista-de-parâmetros-reais é a lista das variáveis
que se corresponderão com os parâmetros formais
durante a execução da função. Os parâmetros
atuais devem concordar em números, ordem e tipo
com os parâmetros formais.


Exemplo:
Funções

Exemplo: Faça um algoritmo que dado um valor real x,
chame uma função que retorne o quadrado de x.
Algoritmo <Quad>
real: x, y
Função real quadrado(real:w)
real: z
Início
z ← w*w
Retorne (z)
Fim
Início
Escreva (“Digite um número: “)
Leia ( x )
y ← quadrado (x)
Escreva (“ y = “ , y )
Fim
Funções




INSTRUÇÃO Retorne
A instrução Retorne é um comando simples usado
apenas nas funções e tem o efeito de parar a
execução da função e enviar um valor para o
algoritmo principal ou para outro subalgoritmo que
o tenha chamado. Toda função deve ter em seu
corpo de instruções, pelo menos, uma instrução
Retorne.
Sintaxe:
Retorne ( <expressão> )
Exemplos:
Retorne ( area )
Retorne ( pi*r*r )
Funções


Faça uma função para determinar se um número
inteiro é par ou não. Utilize esta função para
calcular dois somatórios: um com os números
pares e outro com os números ímpares, sendo
dados os n números inteiros positivos.
Faça um algoritmo que leia n pontos no plano e
determine se os pontos estão dentro, fora ou sobre
uma circunferencia de raio R e centro em (h,k).
Funções e Procedimentos

Faça um algoritmo que realize o cálculo dos atrasos e horas
trabalhadas (mensais) de um empregado (cartão de ponto).
Algoritmo <cartaodeponto>
Tipo dia = registro
Inteiro : em,sm, et, st
Fim registro
Tipo totDia = registro
Inteiro: atraso,horas
Fim registro
dia: cartao[31]
totDia: totalDia[31]
Inteiro: cont,i,toth,totatr
Procedimento entrada ()
inteiro: dia
Inicio
cont ←0
leia (dia)
enquanto (dia>0 e dia <32) faça
leia (cartao[dia].em, cartao[dia].sm,cartao[dia].et,cartao[dia].st)
cont←cont+1
leia (dia)
fim enquanto
Fim
Funções e Procedimentos
Função inteiro minuto(inteiro:H)
Inteiro: m
Inicio
m←(H div 100)*60 + H mod 100
retorne(m)
Fim
Função inteiro atraso(inteiro: H, periodo)
Inteiro:a
Inicio
a ←minuto(H)-periodo
retorne(a)
Fim
Função inteiro total (inteiro: HE,HS)
Inteiro: t
Inicio
t ←minuto(HS)-minuto(HE)
retorne(t)
Fim
Funções e Procedimentos
Procedimento calculo()
Inicio
Para i de 1 até cont repita
totalDia[i].atraso ← atraso(cartao[i].em,480)+atraso(cartao[i].et,840)
totalDia[i].horas ← total(cartao[i].em,cartao[i].sm)+total(cartao[i].et,cartao[i].st)
toth ← toth+totalDia[i].horas
totatr ← totatr+totalDia[i].atraso
Fim
Procedimento impressão()
Inicio
Para i de 1 até cont repita
escreva (cartao[i].em,cartao[i].sm)
escreva(cartao[i].et, cartao[i].st)
escreva (totalDia[i].horas div 60)
escreva (totalDia[i].horas mod 60)
escreva (totalDia[i].atraso div 60)
escreva (totalDia[i].atraso mod 60)
FimPara
escreva ((toth/cont)div 60,(toth/cont)mod 60)
escreva ((toth div 60, toth mod 60)
escreva ((totatr/cont)div 60, (totatr/cont)mod 60)
Funções e Procedimentos
Inicio
Entrada()
Se (cont>0) então
calculo()
impressão()
Fim se
Fim
Funções e Procedimentos

Faça uma função que recebe a idade de uma pessoa em
anos, meses e dias e retorna essa idade expressa em dias.
Função inteiro idadedias(inteiro:anos, meses,dias)
inteiro: diast
Inicio
diast←anos*365+meses*30+dias
retorne(diast)
Fim
Funções e Procedimentos

Faça uma função que verifique se um valor é perfeito ou não. Um
valor é dito perfeito quando ele é igual a soma dos seus divisores
excetuando ele próprio (Ex. 6´é perfeito, 6=1+2+3, que são seu
divisores). A função deve retornar um valor booleano.
Função logico perfeito (inteiro: num)
inteiro:soma,i
Inicio
soma ←0
para i de 1 até num/2 repita
se (mod(num,i)=0)
soma←soma+i
fim se
fim para
se (soma=num)
retorne(1)
senão
retorne(0)
Fim
Funções e Procedimentos

Foi realizada uma pesquisa de algumas características físicas de 50
habitantes de uma certa região. De cada habitante foram coletados
os seguintes dados: sexo, cor dos olhos (azuis, verdes ou
castanhos), cor dos cabelos (louros, pretos ou castanhos) e idade.
Faça um procedimento que leia esses dados em um vetor de
registro. O vetor de registro deve ser enviado por referência.
Procedimento leia (habitante:&dados[50])
inteiro: i
Inicio
Para i de 1 até 50 repita
leia(dados[i].sexo,dados[i].cor_olhos,dados[i].cor_cab)
leia(dados[i].idade)
Fim para
Fim
Nota: No algoritmo principal deve ser definido o tipo habitante.
Funções e Procedimentos
Faça um procedimento que receba o vetor de registro definido no
exercício anterior, por parâmetro, e retorna também por parâmetro:
a maior idade entre os habitantes e a quantidade de individuos do
sexo feminino cuja idade está entre 18 e 35 (inclusive) e que
tenham olhos verdes e cabelos louros.
Procedimento informacoes(habitante:dados[50], &maioridade,&soma)
inteiro: i
Inicio
soma←0
maioridade ← 0
Para i de 1 até 50 repita
se (dados[i].idade>maioridade)
maioridade ← dados[i].idade
se (dados[i].sexo=“F” e dados[i].idade>=18 e
dados[i].idade<=35 e dados[i].cor_olhos=“verdes” e
dados[i].cor_cab=“louros”)
soma ←soma+1
fim se
Fim para

Funções e Procedimentos

1.
2.
3.
Faça uma função para calcular o máximo divisor comum (MDC) de
dois numeros dados como parâmetros. Sabe-se que o MDC tem as
seguintes propriedades :
MDC(x,y)=MDC(x-y,y), se x>y
MDC(x,y)=MDC(y,x)
MDC(x,x)=x
Exemplos
MDC(24,8)=MDC(16,8)=MDC(8,8)=8
MDC(13,4)=MDC(9,4)=MDC(5,4)=MDC(1,4)=MDC(4,1)=
MDC(3,1)=MDC(2,1)=MDC(1,1)=1
MDC(13,5)=MDC(8,5)=MDC(3,5)=MDC(5,3)=MDC(2,3)=
MDC(3,2)=MDC(1,2)=MDC(2,1)=MDC(1,1)=1
Funções e Procedimentos
Função inteiro mdc (inteiro: x,y)
Inicio
enquanto (x<>y)
enquanto (x>y)
x ←x-y
enquanto (y>x)
y ←y-x
fim enquanto
retorne(x)
fim
Funções e Procedimentos
Um banco está informatizando seus controles de clientes e contas.
No primeiro momento o banco deseja guardar as informações de
até 20000 clientes. Cada cliente tem os seguintes dados: Nome,
idade, endereço, número de suas contas (15 no máximo) e CGC.
As contas válidas tem número diferente de 0. Cada conta possui
um só cliente. As informações das contas são as seguintes:
numero, cliente, tempo de cliente e saldo atual. (Se existem 2000
clientes com 15 contas no máximo então devem existir 30000
contas).
(a)
Definição das estruturas de dados e também das variáveis
utilizadas.
Supondo que as estruturas de dados já contêm as informações
armazenadas, crie:
(b)
Uma função que retorne o número de clientes com saldo negativo
em mais de uma conta.
Uma função que retorne o número de clientes que abriram conta
há mais de 10 anos e que tenham idade menor que 30 anos.
(c)
Funções e Procedimentos
(a)
tipo dadosconta=registro
inteiro numero,CGC,tempo
real: saldo
fim registro
tipo dadoscliente=registro
literal:nome,idade,endereço
inteiro:nrocontas,CGC
dadosconta:contas[15]
fim registro
dadoscliente:clientes[20000]
Funções e Procedimentos
(b) Função inteiro saldonegativo(dadoscliente:clientes[],numclientes)
inteiro i,cont,flag
inicio
cont ←0
para i de 1 até numclientes repita
flag ←0
j ←1
enquanto (flag<=1 e j<=clientes[i].nrocontas) faça
se (clientes[i].contas[j].saldo<0)
flag←flag+1
fim se
j←j+1
fim enquanto
se (flag>1)
cont←cont+1
fim se
fim para
retorne(cont)
fim
Funções e Procedimentos
(c) Função inteiro conta2(dadoscliente:clientes[],numclientes)
inteiro i,cont,flag
inicio
cont ←0
para i de 1 até numclientes repita
flag←0, j ←1
se (clientes[i].idade<30) então
enquanto (!flag e j<=clientes[i].nrocontas) faça
se (clientes[i].contas[j].tempo>10) então
flag ←1
fim se
j←j+1
fim enquanto
se (flag)
cont←cont+1
fim se
fim se
fim para
retorne(cont)
Funções e Procedimentos
Resolver os exercícios propostos do Capítulo 3 (Modularização) do
livro de Harry Farrer.
Funções e Procedimentos
Para encontrar uma raiz do polinômio
p( x)  a0  a1x  a2 x2  ... an xn , n  2,
pode-se aplicar o método de Newton que consiste em refinar uma
aproximação inicial x0 dessa raíz através da expressão
p ( xn )
xn 1  xn 
p ' ( xn )
n=0,1,2,…, onde p ' ( x) é a primeira derivada de p(x).
Usualmente, repete-se esse refinamento até que | xn1  xn |  ,   0, ou
até que m iterações tenham sido executadas.
Dados um polinômio p(x), uma aproximação inicial x0 da raiz de p(x),
  0 é o número máximo de iterações que devem ser executadas,
determine uma aproximação da raíz de p(x) pelo método de Newton.
Utilize um módulo que, dado um polinômio p(x), calcule a derivada
p’(x) e, para calcular p(xn) e p’(xn) em cada iteração, um módulo que
calcule o valor de um polinômio em um ponto.
Funções e Procedimentos
Algoritmo raizes
real :xanterior,x,epsilon,a[100],b[100]
inteiro :i,n,numeromaximodeiteracoes,iteracoes
procedimento derivada (real: a[],real:&b[],inteiro:n)
inteiro:i
início
para i de 1 até n repita
b[i]←i*a[i+1]
fim
função real valor_polinômio(real:a[],real:x,inteiro:n)
real:valor
inteiro:i
Início
valor ←a[1]
para i de 2 até n+1 repita
valor ←valor + a[i]*x**(i-1)
fim para
retorne(valor)
Funções e Procedimentos
Início /* algoritmo principal*/
leia(n)
para i de 1 até n+1 repita
leia (a[i])
fim para
leia (xanterior)
leia (epsilon)
leia (nromaximodeiteracoes)
derivada(a,&b,n)
iteracoes ←0
x ← xanteriorvalor_polinomio(a,xanterior,n)/valor_polinomio(b,xanterior,n-1)
enquanto(abs(x-xanterior)>=epsilon e iteracoes<=nromaxiteracoes)
x ← xanteriorvalor_polinomio(a,xanterior,n)/valor_polinomio(b,xanterior,n-1)
iteracoes ←iteracoes+1
fim enquanto
Funções e Procedimentos
Escreva um algoritmo que solucione o problema de preenchimento das
vagas nos cursos de uma universidade. Cada aluno que prestou
vestibular em uma determinada universidade, originou um registro
com os seguintes campos: número de inscrição, nota geral obtida
(de 0.0 a 10.0) e código do curso para o qual ele se candidatou. A
universidade oferece 5 cursos com 50 vagas cada. O problema
consiste em distribuir os candidatos entre os cursos, de acordo com
a nota final e com a opção apresentada pelo candidato. Em caso de
empate, será atendido primeiro, o candidato com menor número de
inscrição. Sabe-se que o final de dados será determinado pelo
campo de inscrição negativo ou por ter alcançado o número de
30000 candidatos, que é o máximo permitido pelo regulamento da
universidade. Observação: os resultados dos alunos são lidos
independente da sua classificação, por isso a distribuição deve
também ordenar os alunos nos cursos.
Download

Funções e Procedimentos