Você está na página 1de 33

REVISÃO ALGORITMOS

Prof. Christiano Colen Venancio


UNIPAC – Campus Vale do Aço – Ipatinga - 2007
INDICE
1Introdução............................................................................................................................................................4
2Portugol................................................................................................................................................................4
2.1 Tipos básicos........................................................................................................................................... ...................4
2.2 Comandos básicos..................................................................................................................................................... .4
2.19 Blocos e comandos básicos de controle....................................................................................... ...........................4
2.4 Outras Estruturas de Repetição................................................................................................................ ...............6
2.5 Seleção de Múltipla Escolha............................................................................................................ .........................7
2.6 Definição de Novos Tipos de Dados................................................................................................................... .......7
2.7 Cadeia de Caracteres.................................................................................................................... ............................8
2.8 Ordenação e Busca em Vetor....................................................................................................................... .............8
2.9 Ordenação pelo método Bolha............................................................................................................................. .....9
2.10 Ordenação pelo método de Inserção......................................................................................... ...........................11
2.11 Busca Linear................................................................................................................................... .......................13
2.12 Busca Binária................................................................................................................................................ .........15
2.13 Estruturas Condicionais Encadeadas...................................................................................... ............................17
3Matrizes..............................................................................................................................................................17
3.1 Matrizes Bidimensionais........................................................................................................................ .................17
4Modularização....................................................................................................................................................18
4.1 Benefícios da Modularização.................................................................................................................... ..............19
4.2 Ferramentas para Modularização.................................................................................................................... ......19
4.19 Modos de Transferência de Parâmetros............................................................................................................. ..20
4.4 Passagem por Valor............................................................................................................................... ..................20
4.5 Passagem por Referência..................................................................................................................... ...................20
4.6 Passagem por valor x por referência......................................................................................................... .............21
4.7 Criando Funções............................................................................................................................................... .......21
4.8 Criando Procedimentos..................................................................................................................................... ......22
4.9 Solicitando a execução de um módulo.............................................................................................................. ......23
4.10 Exemplo de um Algoritmo Modularizado........................................................................................................... .24
5Recursividade.....................................................................................................................................................25
5.1 Exemplo de Problema Recursivo........................................................................................................................ ....25
5.2 Recursão X Iteração................................................................................................................................... .............26
6Apontadores........................................................................................................................................................26
7Estrutura de Dados Heterogênea......................................................................................................................27
7.1 Introdução......................................................................................................................................................... .......27
7.2 Registros.......................................................................................................................................................... .........27
7.3 Trabalhando com Registro................................................................................................................................ ......28
7.4 Vetores de Registro.................................................................................................................................. ................29

Prof. Christiano Colen Venancio 2


UNIPAC Ipatinga - 2007
Prof. Christiano Colen Venancio 3
UNIPAC Ipatinga - 2007
1 Introdução
Esta apostila tem como objetivo revisar os conceitos de algoritmos, apresentando de uma maneira sintética os
conceitos de algoritmos e portugol. Iremos introduzir o conceito de Matrizes e funções.

2 Portugol
É uma linguagem de expressão de algoritmos. É considerada uma pseudolinguagem, cuja função é fornecer a
notação para a criação de algoritmos.

2.1 Tipos básicos


No PORTUGOL existem quatro tipos básicos, isto é, tipos básicos de dados que podem ser utilizados:
INTEIRO, REAL, CARACTER e LÓGICO.
Uma variável pode ser entendida como um local onde se pode colocar qualquer valor do conjunto de valores
possíveis do tipo básico associado. O nome da variável é o identificador tal como definido anteriormente. Por
exemplo:
Toda variável deve ser declarada conforme a sintaxe apresentada na figura abaixo.
A semântica de uma declaração de variáveis corresponde à criação de locais na memória, rotulada com o nome
do identificador (variável) e marcada com o tipo de valores que ela pode conter.

Diagrama que representa a definição de uma variável.


Podemos ter uma sequencia de caracteres, denominada CADEIA. Abaixo segue um exemplo do uso desse tipo:
Cadeia : Nome;
2.2 Comandos básicos
O comando de ATRIBUIÇÃO é utilizado para atribuir um valor a uma variável. Para isso usa-se o símbolo ← ,
conforme a seguinte sintaxe:

A notação usada para expressões é basicamente uma forma linear comumente usada na matemática, que pode
conter operadores:
ARITMÉTICOS: +, -, /, *, raiz( ), **, sen( ), cos( ), mod, div,...
LÓGICOS: e, ou, não ( Λ, V, . )
RELACIONAIS: =, ≠, >, ≥ (ou >=), <, ≤ (ou <=)
É importante observar que o resultado da expressão (do lado direito do comando de atribuição) deve ser
coerente com o tipo declarado para a variável (do lado esquerdo).

2.19 Blocos e comandos básicos de controle


Um bloco pode ser definido como um conjunto de comandos com uma função bem definida.
Serve também para definir os limites onde as variáveis declaradas em seu interior são conhecidas.

Prof. Christiano Colen Venancio 4


UNIPAC Ipatinga - 2007
Exemplo:
Uma seqüência simples é um conjunto de comandos separados por ponto e vírgula (;), que serão executadas
numa seqüência linear de cima para baixo.
Exemplo:
comando1;
comando2;
comando3;
...
comandoN;

Quando a ação a ser executada depender de uma inspeção (teste), teremos uma alternativa, ou estrutura
condicional, simples ou composta.
Exemplo de uma estrutura condicional simples:

Exemplo de uma estrutura condicional composta:

Nos comandos apresentados, < condição > é qualquer expressão cujo resultado seja falso ou verdadeiro.
Uma estrutura de repetição é quando um conjunto de ações é executado repetidamente enquanto uma
determinada condição permanece válida (ou seja, quando o resultado de da expressão é um valor lógico
verdadeiro).
Exemplo de uma estrutura de repetição:

Enquanto o valor da < condição > for verdadeiro, as ações dos comandos são executadas e quando se tornar
falso, o comando é abandonado. Se já da primeira vez o resultado é falso, os comandos não são executados.
Até agora todos os valores calculados pelos algoritmos foram gerados e permaneceram na memória. Para obter
ou para fornecer dados ao ambiente exterior ao algoritmo, por exemplo do teclado e para o vídeo, é preciso
utilizar comandos de entrada e saída. O comando de entrada é leia e o comando de saída é imprima, e suas
sintaxes são apresentadas a seguir.

Prof. Christiano Colen Venancio 5


UNIPAC Ipatinga - 2007
Exemplo de um algoritmo que usa comandos de entrada e saída:

2.4 Outras Estruturas de Repetição


Serão apresentadas a seguir outras duas estruturas de repetição que também podem ser utilizadas na construção
de algoritmos usando o PORTUGOL, são elas: repita e para.
A estrutura de repetição repita difere da enquanto no que diz respeito ao momento em que o teste da condição é
submetido.

Na estrutura enquanto o teste é realizado antes da execução do primeiro loop, ou seja, pode ser que os
comandos não sejam realizados sequer uma vez, caso a condição seja falsa já na primeira vez em que foi
testada. Já na repita os comandos sempre serão executados pelo menos uma vez, até que a condição seja
testada, no final da estrutura.

A estrutura de repetição para difere das estruturas enquanto e repita, pois utiliza uma variável de controle, que
atua como um contador de repetições.

Observando o exemplo, percebe-se que foi utilizada uma variável do tipo inteiro (I), que deve ter sido declarada
anteriormente. Esta estrutura irá executar os comandos 10 vezes, pois possui I variando automaticamente de 1
em 1 (passo 1) até 10, ou seja, não é necessário fazer o incremento deste dentro da estrutura de repetição.
O comando abandone só tem sentido dentro de um comando de repetição (enquanto, repita e para). Além
disso, estará sempre associado ao teste de uma condição com comando se.
Sintaxe: abandone;
A semântica do comando é a seguinte: quando o abandone é encontrado, o próximo comando a ser executado é
o primeiro logo após o fim do comando de repetição mais interno onde este aparece.
Exemplo:

Prof. Christiano Colen Venancio 6


UNIPAC Ipatinga - 2007
2.5 Seleção de Múltipla Escolha
Algumas vezes, em um problema necessitamos escolher uma entre várias alternativas, apesar da seleção
encadeada ou aninhada ser uma opção para este tipo de construção, ela não é uma maneira elegante de
construção, além de muitas vezes dificultar o entendimento de sua lógica. Neste caso, utilizamos a seleção de
múltipla escolha.

Exercício: Determinar se uma letra digitada é vogal ou consoante..

2.6 Definição de Novos Tipos de Dados


Nem sempre os tipos básicos (inteiro, real, caracter e lógico) são suficientes para exprimir estruturas de dados
em algoritmos. Daí a necessidade de novos tipos de dados serem criados. Um destes tipos é o vetor.
No PORTUGOL a criação de um vetor segue as especificações:
tipo nome_do_tipo = vetor [li:ls] <tipo_básico>; ou tipo nome_do_tipo = vetor [quantidade] <tipo_básico>;
É dado um nome_do_tipo ao novo tipo de vetor criado, onde li é o limite inferior e ls é o limite superior de um
intervalo que define o tamanho do vetor (valores inteiros), e tipo_básico é um dos tipos básicos já conhecidos.
Esta especificação apenas indica um modelo para a criação de variáveis deste novo tipo. Para efetivar esta
estrutura dentro do algoritmo, é necessário declará-la dando um nome a variável que será criada segundo o
modelo especificado.
Exemplo: um vetor que armazena as notas de todos os alunos de uma turma com 25 alunos.
tipo v = vetor [1:25] real;
v: NOTAS;
O número de elementos de um vetor é dado por ls-li+1. Isto significa que as posições do vetor são identificadas
a partir de li, com incrementos unitários até ls.

Cada elemento de um vetor é tratado como se fosse uma variável simples. Para referência a um elemento do
vetor utiliza-se o nome do vetor e a identificação do elemento (índice) entre colchetes ([ ]).
Por exemplo, se quisermos atribuir o valor de uma 45 a nota do 6o aluno (que é identificado pelo índice 6 do
vetor de notas): NOTAS[6] <- 45;
Prof. Christiano Colen Venancio 7
UNIPAC Ipatinga - 2007
Exemplo: O que será impresso no algoritmo abaixo?

Exercício: Um professor de uma turma com 30 alunos quer armazenar as notas de seus alunos em um vetor e
depois calcular a média geral da turma. Escreva um algoritmo que solucione este problema usando uma
estrutura de vetor.

2.7 Cadeia de Caracteres


A maior parte dos processamentos efetuados atualmente exige a manipulação de cadeias de caracteres. Uma
cadeia de caracteres é uma seqüência de letras, algarismos ou símbolos (sinais de pontuação parênteses etc).
Portanto, uma cadeia de caracteres é uma lista linear (vetor) em que cada elemento é um caracter.
Devido à grande utilização de cadeias de caracteres vamos definir o tipo de dados cadeia que descreve todas as
seqüência de caracteres, bem como a cadeia vazia. O tipo de dados cadeia determina que toda cadeia seja
finalizada pelo caracter ASCII 0(zero), ou seja a uma variável do tipo cadeia somente com caracter 0 indica que
ela está vazia, e o seu tamanho é 0.
Como exemplo, será criado primeiramente o tipo de dado cadeia, e depois uma variável do tipo cadeia. A
atribuição de um valor válido a variável cadeia, a sua impressão e depois a leitura de uma cadeia através da
instrução Leia.

Os valores atribuídos à variável frase devem estar entre aspas duplas, tal como “Entre com o seu nome:”.
Quando a variável nome é inicializada pela instrução Leia, automaticamente é inserido o caracter 0 no final da
cadeia. Lembremos que “a” e ‘a’ são valores pertencentes a tipos distintos. No primeiro caso, temos uma cadeia
de tamanho 1 que contém apenas a letra a; no segundo, temos a letra a, que é um valor válido para tipo de dado
caracter.

2.8 Ordenação e Busca em Vetor


A importância de mantermos “coisas” ordenadas é fundamental em muitas atividades. Você já imaginou se os
sobrenomes dos assinantes da lista telefônica de São Paulo não estivessem dispostos em ordem alfabética?
Seria uma tarefa monumental encontrar o telefone de um usuário da companhia telefônica, não?
No processamento de dados, a tarefa de ordenação também exerce um papel fundamental, pois a ordem na qual
os dados são processados por um programa pode exercer uma grande influência em seu desempenho e

Prof. Christiano Colen Venancio 8


UNIPAC Ipatinga - 2007
simplicidade. Por esta razão, a ordenação (ou classificação) de dados tem sido um assunto estudado
exaustivamente em Computação, e muitas soluções interessantes foram propostas ao longo dos últimos 40 anos.
Na maioria das vezes, a ordenação de dados é realizada com o objetivo de facilitar a busca de dados. Isto
porque se os dados a serem recuperados em um certo conjunto de dados estiverem dispostos segundo uma dada
ordem, a tarefa de encontrá-los no conjunto se tornará mais rápida e simples.

2.9 Ordenação pelo método Bolha


Um método simples de ordenação por troca é a estratégia conhecida como bolha que consiste, em cada iteração,
“borbulhar” o maior elemento para fim da lista inicialmente percorre-se a lista dada da esquerda para a direita,
comparando pares de elementos consecutivos, trocando de lugar os que estão fora de ordem. Considere um
vetor de seis elementos com índices de 0 até 5:

A ordenação do vetor em ordem crescente é:

A idéia é comparar os elementos dois a dois e ir jogando os elementos maiores para as últimas posições do
vetor até obter o vetor classificado. Uma vez que o maior elemento tenha atingido a mais alta posição é
reduzido o tamanho do vetor a ser classificado, como se pode ver pelos passos no esquema que se segue:

Prof. Christiano Colen Venancio 9


UNIPAC Ipatinga - 2007
Prof. Christiano Colen Venancio 10
UNIPAC Ipatinga - 2007
2.10 Ordenação pelo método de Inserção
O algoritmo de ordenação por inserção simula o processo de ordenação utilizado por um jogador de baralho.
Suponha que exista um maço de cartas de baralho em uma mesa e que um jogador retira uma carta desse maço
por vez.
O jogador utiliza sua mão direita para retirar uma carta do maço e sua mão esquerda para segurar as cartas
retiradas com a mão direita. Inicialmente, a mão esquerda está vazia, pois todas as cartas estão na mesa. Após
retirar a primeira carta, o jogador a põe imediatamente na mão esquerda, que está vazia.
Em seguida, ele retira uma outra carta e a põe na mão esquerda, comparando-a com a carta lá existente. Se a
carta retirada é menor do que a carta na mão esquerda, ela deve ficar à esquerda desta. Caso contrário, ela deve
ficar à direita. Neste momento, as duas cartas na mão esquerda encontram-se ordenadas.
O processo segue com a retirada da terceira carta. O jogador, então, insere a terceira carta na mão esquerda.
Esta inserção é realizada comparando-se a carta retirada com as duas cartas já existentes na mão esquerda.
Como tais cartas estão dispostas ordenadamente, a comparação se inicia pela carta mais à direita. Se a carta
retirada é maior do que ela, então aquela é inserida à direita desta. Caso contrário, a carta retirada é comparada
com a carta mais à esquerda. Caso ela seja maior do que esta, ela ficará entre as duas. Caso contrário, ela passa
a ser a carta mais à esquerda das três.
Para as demais cartas, o processo segue da mesma forma. A mão esquerda sempre conterá cartas ordenadas da
esquerda para a direita. Digamos, então, que a mão esquerda possua n cartas. Ao tentarmos inserir uma nova
carta na mão esquerda, devemos compará-la primeiro com a carta mais à direita, a n-ésima carta da esquerda
para a direita. Se a nova carta é maior do que ela, colocamos a nova carta a sua direita. Caso contrário,
comparamos a nova carta com a carta na (n-1)-ésima posição e assim por diante. Desta forma, após inserirmos a
última carta do maço na mão esquerda, teremos nela as cartas completamente ordenadas.
Vamos, agora, examinar um algoritmo de ordenação de dados que utiliza a idéia descrita antes para classificar
um conjunto de números armazenados em um vetor. Este algoritmo inicia considerando o elemento na primeira
posição do vetor como sendo a única “carta na mão esquerda” e o restante do vetor como sendo o “maço”.
Daí, o algoritmo segue por inserir o elemento na segunda posição do vetor em sua posição correta. Isto é,
comparando-o com o elemento na primeira posição e inserindo-o na primeira posição se necessário. Neste
ponto, tem-se que o segmento do vetor formado pelas duas primeiras posições encontra-se ordenado. O
algoritmo segue, então, com a inserção do terceiro elemento do vetor na posição correta do segmento formado
pelas duas primeiras posições e sua própria posição.
De forma geral, o algoritmo varre o vetor do segundo ao último elemento. Na i-ésima varredura, o algoritmo
insere o (i + 1)-ésimo elemento do vetor na posição correta do segmento que vai do primeiro elemento do vetor
até o (i + 1)-ésimo.
O algoritmo encontra a posição correta de um elemento por compará-lo com os elementos do segmento do
vetor a sua esquerda, da esquerda para a direita. A posição correta é encontrada quando o elemento do segmento
sendo comparado é menor ou igual a ele. Obviamente, para se inserir um elemento no meio de um segmento de
um vetor, deve-se deslocar os elementos que ficarão a sua direita uma casa para a direita. Caso contrário,
danificaríamos o vetor. Considere a variável V como um vetor de números com n elementos.

Prof. Christiano Colen Venancio 11


UNIPAC Ipatinga - 2007
Vamos simular a ordenação pelo método de inserção, considerando um vetor com 6 elementos:

Prof. Christiano Colen Venancio 12


UNIPAC Ipatinga - 2007
2.11 Busca Linear
O algoritmo de busca a ser estudado nesta seção recebe um vetor de dados não ordenados e um elemento a ser
encontrado neste vetor.
O resultado do algoritmo é a posição em que o elemento se encontra no vetor, caso ele esteja lá, ou um valor
inválido que represente o insucesso da busca, caso o elemento não esteja no vetor.
A busca é realizada comparando o valor do elemento a ser encontrado com os elementos do vetor, um a um, da
esquerda para a direita. O pior dos casos na busca linear, se dá quando o valor procurado é igual ao do último
elemento do vetor, o algoritmo realizará a comparação do valor procurado com todos os elementos do vetor.

Prof. Christiano Colen Venancio 13


UNIPAC Ipatinga - 2007
Prof. Christiano Colen Venancio 14
UNIPAC Ipatinga - 2007
2.12 Busca Binária
A idéia do algoritmo de busca binária é comparar um elemento do vetor ordenado de dados, sorteado
aleatoriamente, com o elemento a ser encontrado.
Se o elemento procurado é igual ao elemento sorteado, a busca termina. Entretanto, se o elemento sorteado for
menor do que o elemento a ser encontrado, então devemos restringir a busca ao segmento do vetor à direita do
elemento sorteado, pois o segmento formado pelos elementos à esquerda deste é formado apenas por elementos
menores do que o elemento procurado.
Raciocínio análogo pode ser aplicado caso o elemento procurado seja menor do que o elemento sorteado. O
próximo passo é aplicar o mesmo processo de busca ao segmento que pode conter o elemento procurado. Este
processo continua até o elemento ser encontrado ou não haver mais segmento para procurar o elemento. O
algoritmo a seguir representa esta idéia.

Prof. Christiano Colen Venancio 15


UNIPAC Ipatinga - 2007
Prof. Christiano Colen Venancio 16
UNIPAC Ipatinga - 2007
2.13 Estruturas Condicionais Encadeadas
Existem casos em que é necessário se estabelecerem verificações de condições sucessivas, onde uma
determinada ação poderá ser executada se um conjunto anterior de condições for satisfeito.
Isto significa usar uma condição dentro de outra. Este tipo de estrutura pode possuir diversos níveis de
condição, sendo chamada de aninhamento ou encadeamento de estruturas condicionais. Exemplo:

3 Matrizes
Uma matriz é uma estrutura de dados homogênea, ou seja, todos os elementos de uma matriz são do mesmo
tipo. Um vetor é uma matriz unidimensional, a partir de agora serão apresentadas matrizes com mais de uma
dimensão.
3.1 Matrizes Bidimensionais
A forma mais comum de trabalhar com matrizes é utilizando duas dimensões, apesar de que em alguns casos
possa ser necessário trabalhar com mais de duas. Uma matriz bidimensional é composta por linhas e colunas.
As linhas podem ser consideradas como a primeira dimensão e as colunas a segunda dimensão. É preciso
definir o tamanho de cada uma dessas dimensões, ou seja, o número de linhas e o número de colunas que esta
matriz deverá possuir.
Exemplo: Definição de uma matriz com 8 linhas e 5 colunas.

Exemplo de algoritmo utilizando matriz com duas dimensões:


Seja uma matriz a representação das notas obtidas pelos alunos em uma determinada disciplina. A quantidade
de linhas deverá ser equivalente ao número de alunos, neste caso 25. Cada coluna deverá conter o valor de uma
das avaliações de cada aluno, neste caso são 3 avaliações. O algoritmo deve preencher a matriz com as notas.

Exercício: Escreva um algoritmo que receba as notas referentes a três avaliações realizadas por 25 alunos, e as
armazene numa matriz, juntamente com a média total obtida pelo aluno. Sabendo que: as duas primeiras
avaliações têm peso de 35 cada uma e a terceira tem peso de 30 pontos. Além disso, para cada média total deve

Prof. Christiano Colen Venancio 17


UNIPAC Ipatinga - 2007
ser enviada uma mensagem informando se o aluno foi aprovado (>=50) ou reprovado (<50) e qual foi a
porcentagem da turma aprovada.

4 Modularização
No fim da década de 60, alguns problemas no desenvolvimento de sistemas de programação levaram os países
desenvolvidos a um evento chamado “crise de software”. Os custos das atividades de programação mostravam
a cada ano uma clara tendência a se elevarem muito em relação aos custos dos equipamentos, e isto era devido
ao avanço tecnológico na fabricação dos equipamentos de computação e a lenta evolução de técnicas aplicadas
ao desenvolvimento de software.
A ausência de uma metodologia para a construção de programas conduzia a programas geralmente cheios de
erros e com altos custos de desenvolvimento que, conseqüentemente, exigiam custos elevados para a sua
correção e manutenção futuras. A programação estruturada foi o resultado de uma série de estudos e
propostas de metodologias para desenvolvimento de software. Uma das técnicas aplicadas na programação
estruturada, a modularização de programas é uma ferramenta para a elaboração de programas visando, os
aspectos de confiabilidade, legibilidade, manutenibilidade e flexibilidade, dentre outros.
A modularização é um processo que aborda os aspectos da decomposição de algoritmos em módulos. Módulo é
um grupo de comandos, constituindo um trecho do algoritmo, com uma função bem definida e o mais
independente possível em relação ao resto do algoritmo.
Há dois tipos de módulos:
• Função: sempre retorna um e apenas um valor ao algoritmo que lhe chamou. Cada função tem associada ao
seu valor de retorno um tipo explícito. Da mesma maneira com que os parâmetros são fixos para todas as
chamada o retorno também é fixo. Ela pode ser vista como uma expressão que é avaliada para um único
valor, sua saída, assim como uma função em Matemática.
Procedimento: é um tipo de módulo usado para várias tarefas, não produzindo valores de saída, ou seja, nunca
retornam valores. Em algumas linguagens não existem explicitamente.
Exemplo – Seja um algoritmo para calcular o salário líquido de um empregado, com as seguintes etapas:

Onde “Determine o salário” pode ser refinado como:


Calcule as vantagens
Calcule as deduções
SALARIOLIQ <- VANTAGENS – DEDUÇÕES
No refinamento anterior não houve preocupação de como o processo de cálculo das vantagens e deduções seria
efetuado. Essas ações constituem funções bem definidas e que serão executadas por módulos específicos, neste
caso, o algoritmo anterior ficaria:

Exemplo da descrição estrutural da modularização:

Prof. Christiano Colen Venancio 18


UNIPAC Ipatinga - 2007
A maneira mais intuitiva de proceder a modularização de problemas é feita definindo um módulo principal de
controle e módulos específicos para as funções do algoritmo. Recomenda-se que os módulos de um programa
tenham um tamanho limitado, pois módulos muito grandes são difíceis de ser compreendidos e, em geral, são
multifuncionais.
As linguagens de programação dispõem de recursos que facilitam a construção e manipulação de módulos,
permitindo não só a modularização dos comandos do programa, como também dos dados utilizados.
Cada módulo pode definir as próprias estruturas de dados, suficientes e necessárias apenas para atingir o
objetivo final do módulo. Todo módulo é constituído por uma seqüência de comandos que operam sobre um
conjunto de objetos, que podem ser globais ou locais.
Objetos globais são entidades que podem ser usadas em módulos internos a outro módulo do algoritmo onde
foram declaradas.
Objetos locais são entidades que só podem ser usadas no módulo do algoritmo onde foram declaradas. Estes
objetos não possuem nenhum significado fora deste módulo.
São exemplos de objetos globais ou locais: variáveis, arquivos, outros módulos, etc.
A comunicação entre módulos deverá ser feita através de vínculos, utilizando-se objetos globais ou
transferência de parâmetros.

4.1 Benefícios da Modularização


A independência do módulo permite uma manutenção mais simples e evita efeitos colaterais no restante do
algoritmo;
. A elaboração do módulo pode ser feita independentemente e em época diferente do restante do algoritmo;
. Testes e correções dos módulos podem ser feitos separados;
. Um módulo pode ser utilizado em outros algoritmos que requeiram o mesmo processamento por ele
executado.

4.2 Ferramentas para Modularização


Sub-rotinas e funções são módulos que servem aos objetivos:
. Evitar que em certa seqüência de comandos necessária em vários locais de um algoritmo tenha que ser escrita
repetidamente nesses locais;
. Dividir e estruturar um algoritmo em partes fechadas e logicamente coerentes;
. Aumentar a legibilidade de um algoritmo.
Sub-rotinas e funções são módulos hierarquicamente subordinados a um algoritmo, comumente chamado de
módulo principal. Da mesma forma uma sub-rotina ou uma função pode conter outras sub-rotinas e funções
aninhadas.
A sub-rotina e a função são criadas através das suas declarações em um algoritmo e para serem executadas,
necessitam de ativação por um comando de chamada. A declaração de uma subrotina ou função é constituída de
um cabeçalho, que a identifica e contém seu nome e uma lista de parâmetros formais, e de um corpo que
contém declarações locais e os comandos.

As funções têm a característica de retornar ao algoritmo que as chamou um valor associado ao nome da função.

Prof. Christiano Colen Venancio 19


UNIPAC Ipatinga - 2007
Ao terminar a execução dos comandos de uma sub-rotina ou função, o fluxo de controle retorna ao comando
seguinte àquele que provocou a chamada.

4.19 Modos de Transferência de Parâmetros


Os parâmetros de uma sub-rotina ou função classificam-se em:
• de entrada – são aqueles que têm seus valores estabelecidos fora da sub-rotina ou função e não podem ser
modificados dentro dela.
• de saída – são aqueles que têm seus valores estabelecidos dentro da sub-rotina ou função.
• de entrada-saída – são aqueles que têm seus valores estabelecidos fora da sub-rotina ou função, mas
podem ter seus valores alterados dentro dela.
A vinculação entre módulos pode ser feita através da transferência ou passagem de parâmetros, que associam
parâmetros atuais com parâmetros formais. Dentre os modos de transferência de parâmetros, pode-se destacar: a
passagem por valor, a passagem por resultado e a passagem por referência.
Na passagem de parâmetros por valor, as alterações feitas nos parâmetros formais, dentro da sub-rotina ou
função, não se refletem nos parâmetros atuais. O valor do parâmetro atual é copiado no parâmetro formal, na
chamada da sub-rotina ou função. Assim, quando a passagem é por valor significa que o parâmetro é de
entrada.
Na passagem de parâmetros por resultado, as alterações feitas nos parâmetros formais, na sub-rotina ou
função, refletem-se nos parâmetros atuais. O valor do parâmetro formal é copiado no parâmetro atual, ao
retornar da sub-rotina ou função. Assim, quando a passagem é por resultado significa que o parâmetro é de
saída.
Na passagem de parâmetros por referência, a toda alteração feita num parâmetro formal corresponde a mesma
alteração feita no seu parâmetro atual associado. Neste caso, quando a passagem é por valor significa que o
parâmetro é de entrada-saída.
Para definir o corpo precisamos identificar o conjunto de variáveis e instruções para
realizar sua tarefa.

4.4 Passagem por Valor


Os valores dos parâmetros passados por valor são passados por um mecanismo denominado cópia. O valor do
parâmetro (uma constante ou o valor de uma variável ou expressão) é atribuído ao parâmetro quando da
chamada do procedimento/função.
Até o momento utilizamos somente passagem por valor. Por exemplo, na chamada da função quadrado, x é um
parâmetro passado por valor, e, assim sendo, o valor de x copiado para o parâmetro da função. Na chamada da
função Quadrado(x), o valor da variável x é atribuído ao parâmetro num da função Quadrado, o parâmetro num
assume o papel de uma variável do procedimento/função e o quadrado é calculado para esse valor. Na chamada
da função Quadrado(y) , o parâmetro num recebe o valor da variável y, portanto o módulo retornará o quadrado
da variável y.

4.5 Passagem por Referência


A passagem por referência ocorre quando alterações nos parâmetros, dentro da função, alteram os valores das
variáveis que foram passadas para a função. Este nome vem do fato de que, neste tipo de chamada, não se passa
para a função o valor das variáveis, mas sim suas referências (a função usa as referências para alterar os valores
das variáveis, que foram passadas como parâmetro, fora da função).
A referência de uma variável é seu endereço de memória, quando realizamos uma passagem de parâmetro por
referência, o parâmetro não recebe a cópia do valor da variável, e sim, o endereço de memória onde está
armazenada essa variável. Assim, qualquer alteração no valor do parâmetro feita pelo procedimento/função
acarretará uma modificação no valor da variável passada como parâmetro.
Para indicar que um parâmetro é passado por referência, na especificação dos parâmetros de um módulo
utilizaremos a palavra-chave REF antes do tipo de dado do parâmetro.
Por exemplo, para criarmos um procedimento para realizar a troca de valores entre duas variáveis devemos
passar as suas respectivas referências para que o módulo possa alterá-las.
Quando a chamada Troca(num1, num2) é executada, a variável a e b (que estão precedidas da palavra-chave
REF) receberam o endereço de memória das variáveis num1 e num2 respectivamente. Quando as variáveis a e
Prof. Christiano Colen Venancio 20
UNIPAC Ipatinga - 2007
b forem alteradas no procedimento, esta atualização afetará o valor de num1 e num2. Se essas variáveis fossem
passadas por valor esta atualização não seria possível.

Devemos observar que os parâmetros passados por referência devem ser obrigatoriamente variáveis, uma vez
que não faz sentido modificar o valor de uma constante ou de uma expressão.

4.6 Passagem por valor x por referência


Sempre que desejarmos passar parâmetros para uma função, devemos distinguir e saber quando utilizar
passagem de parâmetros por valor ou por referência. Quando a função/procedimento precisa apenas de um
valor inicial para o parâmetro utilizaremos passagem por valor. Quando desejarmos que as atualizações
realizadas pelo módulo alterem as variáveis externas a ele, devemos utilizar passagem por referência. Para
exemplificar vamos criar módulos com passagem por valor e por referência.

4.7 Criando Funções


Para criar uma função utilizaremos a seguinte forma geral:

Prof. Christiano Colen Venancio 21


UNIPAC Ipatinga - 2007
Em que:
• nome é um identificador único que representa o nome da função;
• os parâmetros são uma lista formada pela declaração dessas variáveis especiais definida pelo tipo de dado e
o nome do parâmetro da função. Essa lista de parâmetros também pode ser vazia.
• tipo de retorno é o tipo de dado do valor de retorno da função (REAL,INTEIRO, CARACTER ou
BOOLEANO). Exemplo de um lista de parâmetros: (inteiro num1, num2 ; caracter opção)
• Conjunto de instruções é a seqüência de instruções que compõe o módulo e que sempre finaliza com um
comando especial denominado a instrução de retorno que é da seguinte forma: RETORNA <valor de
retorno>
• valor de retorno é o valor de saída produzido pela função que deve ser do mesmo tipo de dado definido no
tipo de retorno.
Logo após a descrição da interface podemos descrever o corpo do algoritmo da função correspondente. Para
delimitar as instruções que fazem parte da função, utilizamos Fim-Função.
Exemplo: Vejamos um exemplo de uma função. Suponha que desejemos construir uma função para calcular o
quadrado de um número. O número deve ser passado para a função, que calculará o seu quadrado e o devolverá
para o algoritmo que a solicitou. Vamos denominar esta função de Quadrado, como é mostrado a seguir:

4.8 Criando Procedimentos


A diferença entre funções e procedimentos é que o procedimento não retorna valor. Para criar um procedimento
utilizaremos a seguinte forma geral:

Em que:

Prof. Christiano Colen Venancio 22


UNIPAC Ipatinga - 2007
• nome é um identificador único que representa o nome do procedimento;
• os parâmetros são uma lista formada pela declaração dessas variáveis especiais definida pelo tipo de dado e
o nome do parâmetro da função. Essa lista de parâmetros pode possuir vários parâmetros ou ser vazia.
• Conjunto de instruções é a seqüência de instruções que compõe o módulo.
Como um procedimento não retorna valor, não é necessário utilizar a instrução
de retorno.
Para delimitar os comandos que fazem parte do procedimento, utilizamos FIM-PROCEDIMENTO.

Exemplo: Suponha que desejemos construir um procedimento para apresentar informações do algoritmo.

4.9 Solicitando a execução de um módulo


Quando queremos utilizar os módulos que criamos para resolver uma tarefa, ou seja solicitar sua execução,
devemos fazer chamada ao módulo. A chamada ao módulo é a forma de solicitar a execução do módulo em um
determinado passo do algoritmo.
Funções e procedimentos não são diferentes apenas na forma como são implementados, mas também na forma
como a solicitação da execução deles, ou simplesmente chamada, deve ser realizada.
A chamada de uma função é usada como um valor constante que deve ser atribuído a uma variável ou como
parte de uma expressão, enquanto a chamada de um procedimento é realizada com uma instrução.
Para fazer a chamada de um módulo devemos especificar qual o nome módulo e passar valores iniciais para
seus parâmetros. Esses valores iniciais devem ser do mesmo tipo de dado e especificados na mesma ordem em
que foram definidos na interface do módulo.

Exemplo de chamadas do módulo Quadrado:

Exemplos de chamadas do módulo Apresentacao:

Prof. Christiano Colen Venancio 23


UNIPAC Ipatinga - 2007
4.10 Exemplo de um Algoritmo Modularizado
Um algoritmo para realizar a soma dos quadrados de dois números inteiros utilizando a função Quadrado e o
procedimento Apresentacao seria da seguinte forma:

Prof. Christiano Colen Venancio 24


UNIPAC Ipatinga - 2007
5 Recursividade
Um objeto é dito recursivo se ele consistir parcialmente ou for definido em termos de si próprio.

Uma função é recursiva quando no corpo dessa função existe uma chamada a si própria, podendo utilizar os
mesmos parâmetros de entrada (correndo riscos de provocar um ciclo infinito) ou outros.

5.1 Exemplo de Problema Recursivo


Imagine que temos um monte de pregos e queremos saber quantos são. Se pegarmos num prego, sabemos que
temos um prego, mas não sabemos quantos ainda existem no monte restante... efetuamos a mesma operação
(recursividade) e somamos o prego ao que já temos.
Fazemos o mesmo até não existir mais pregos para contar, isto é, pegamos num e somamos aos que temos,
repetimos a mesma operação perguntando sempre entre as operações, "ainda há mais pregos para contar?", caso
haja, repetimos, caso contrário paramos.
A recursividade é uma ferramenta muita poderosa quando bem implementada, senão pode ser muita perigosa. É
preciso ter cuidado com as condições de parada, se faltar alguma condição de parada ou alguma condição de
parada está errada pode acontecer um ciclo infinito.

Prof. Christiano Colen Venancio 25


UNIPAC Ipatinga - 2007
5.2 Recursão X Iteração
Paradigma iterativo: uma seqüência de instruções é executada de uma forma repetitiva, controlada por uma
dada condição (ciclo iterativo).
Paradigma recursivo:
• existência de casos simples, em que a resposta é determinada diretamente;
• s er possível uma decomposição recursiva de uma instância do problema, em instâncias mais simples da
mesma forma.
Numa função recursiva, são criadas várias ativações dela própria que desaparecem à medida que a execução
avança. Em cada momento apenas uma das ativações está ativa, estando as restantes à espera que essa termine
para continuarem.
Os dois paradigmas são equivalentes: dada uma função recursiva existe sempre uma iterativa e vice-versa.

Exemplos Mais Famosos de Problemas Recursivos

São dados três suportes (a, b e c) e n discos de tamanhos diferentes. Os discos estão empilhados num dos
suportes por ordem crescente de tamanhos. Pretende-se mover os discos para outro suporte de modo que:
em cada passo exatamente um disco seja movido de um suporte para o outro um disco não pode nunca estar por
cima de um menor o terceiro suporte pode ser usado como auxiliar

6 Apontadores
É na memória RAM que são carregados os nossos programas e também onde são armazenadas as variáveis que
fazem parte dos programas. A memória RAM pode ser vista como um enorme vetor de Bytes consecutivos,
cada um ocupando uma posição bem determinada, que é identificada por um número único que varia entre 0 e a
totalidade de Bytes.
Para os programadores, é muito mais simples referenciar uma variável pelo seu nome do que referenciá-la pela
posição que essa variável ocupa em memória. O compilador associa a cada nome de variável uma posição única
em memória, capaz de suportar os dados do tipo dessa variável.
Sempre que num programa se faz referência a uma variável, na realidade é o endereço ou conjunto de
endereços que essa variável ocupa, que está sendo referenciado.
Prof. Christiano Colen Venancio 26
UNIPAC Ipatinga - 2007
O apontador é um mecanismo particularmente flexível de manipulação de dados, pois permite manipular
diretamente dados contidos em endereços específicos de memória. Supondo que exista um apontador

denominado ptr, que como qualquer variável ocupa uma posição em memória. Como ptr é um apontador,
deverá conter o endereço de memória de outra variável (notar que o endereço de uma variável não é mais do
que o número da casa que ocupa em memória). A Figura abaixo mostra este exemplo.

7 Estrutura de Dados Heterogênea


7.1 Introdução
Um registro é uma estrutura de dados que agrupa dados de tipos distintos ou, mais raramente, do mesmo tipo.
Um registro de dados é composto por um certo número de campos de dados, que são itens de dados individuais.
Por exemplo, suponha que desejemos criar um algoritmo que armazene informações referentes a 5 alunos, o seu
nome e suas 2 notas bimestrais, com as estruturas de dados que temos até agora seriam necessárias duas
estruturas distintas:
Variáveis
caracter nome = matriz [ 5 ] [ 40 ]
real notas = matriz [ 5 ] [ 2 ]

A primeira estrutura, nome, armazena os nomes dos 5 alunos e a estrutura notas as suas respectivas notas
bimestrais. Nesse caso, seria mais fácil agruparmos os dois tipos de dados em uma mesma estrutura. É
exatamente isto que se consegue fazer como a utilização de registros.

7.2 Registros
Os tipos registros devem ser declarados ou atribuídos antes das variáveis, pois pode ocorrer a necessidade de
declarar uma variável com o tipo registro anteriormente declarado. A declaração de um registro é realizada
conforme a seguir:

Defina Tipo
REGISTRO
< tipo do campo1 > < campo1 >,
< tipo do campo2 > < campo2 >,
...
< tipo do campon > < campon >
FIM-REGISTRO nome do tipo

Em que:
• < nome do tipo> é o nome do registro cuja estrutura está sendo criada,
• < campon> é o nome do n-ésimo campo do registro e
• <tipo do campon> é o tipo do n-ésimo campo do registro.

A lista de campos é uma relação de variáveis, com o seu respectivo tipo, podendo ser REAL, INTEIRO,
LÓGICO, CARACTER ou outro tipo estruturado definido previamente. Como exemplo, vamos criar um
registro para representar o nome de um aluno e suas notas bimestrais e sua média:
Defina Tipo
REGISTRO
caracter nome= vetor [40],
real nota1,
real nota2,
real media
FIM-REGISTRO NOTAS_ALUNOS
Variáveis
NOTAS_ALUNOS aluno
Prof. Christiano Colen Venancio 27
UNIPAC Ipatinga - 2007
Nesse exemplo foi criado um tipo registro NOTAS_ALUNOS, o qual é um conjunto de dados heterogêneos
(um campo tipo VETOR de caracter e cinco campos do tipo REAL). Desta forma é possível guardar em uma
mesma estrutura vários tipos diferentes de dados. Uma vez que um tipo de dado registro tenha sido definido,
podemos criar tantas variáveis daquele tipo desejarmos, assim como fazemos com qualquer outro tipo de dado.
Por exemplo, para criarmos três registros do tipo NOTAS_ALUNOS:

Variáveis
NOTAS_ALUNOS aluno1, aluno2, aluno3

Cada uma dessas três variáveis é um registro do tipo NOTAS_ALUNOS ,e, portanto, cada uma delas possui
seis campos de dado: nome, nota1, nota2 e media. Assim como variáveis do tipo de vetores e matrizes,
variáveis do tipo registros são manipuladas através de suas partes constituintes, os campos.

7.3 Trabalhando com Registro


Exemplo: Considere o seguinte problema: Calcular a média aritmética das 2 notas bimestrais utilizando um
tipo registro.

Em particular, uma variável registro é manipulada através de seus campos. Então, se desejarmos atribuir um
valor a uma variável registro, temos de efetuar a atribuição de valores para seus campos constituintes.
Por exemplo, a leitura de um registro é efetuada com a instrução LEIA seguido do nome da variável registro e
seu campo correspondente separado por um caractere “.” ponto. Uma leitura de registros também poderá ser
feita como:
LEIA aluno

Nesse caso, está sendo feita uma leitura em todos os campos do registro. A atribuição de um campo em um
registro é realizada de forma análoga a atribuição a uma variável. O processo de impressão é feito com
instrução IMPRIMA, semelhante a leitura, podendo também imprimir todo o registro:
IMPRIMA aluno

Note que a estrutura registro apresentada permite somente a leitura e escrita de um único conjunto de campos
para um registro. Mais adiante será apresentado como fazer para conseguir ler e escrever mais de um registro.

Prof. Christiano Colen Venancio 28


UNIPAC Ipatinga - 2007
7.4 Vetores de Registro
Registros nos fornecem uma forma de agrupar dados de natureza distinta. Entretanto, criarmos uma única
variável de um registro não parece ser muito diferente de criarmos uma variável para cada campo do registro e
tratá-las individualmente. Isto é, criar uma única variável de um registro não nos ajudaria a resolver nossos
problemas mais facilmente do que com o que aprendemos antes.
A grande força dos registros reside no uso deles combinado com vetores. Por exemplo, um grupo de 100 alunos
iria requerer um conjunto de 100 variáveis registros, o que pode ser conseguido através da criação de um vetor
de 100 elementos do tipo registro em questão. Um vetor de registros é criado da mesma forma que criamos
vetores de qualquer um dos tipos que aprendemos até então. Suponha, por exemplo, que desejemos criar um
vetor de 100 elementos do tipo NOTAS_ALUNOS. Isto é feito da seguinte forma:

Para manipular um registro individual do vetor alunos, utilizamos o nome da variável vetor e o índice do
elemento correspondente ao registro que queremos acessar, como fazemos com um vetor de qualquer outro
tipo. Daí, em diante, faremos como aprendemos anteriormente. Por exemplo, se quisermos atribuir o conjunto
de valores “Sicrano de Tal”, 10.0, 7.0 ao primeiro registro de alunos, faremos da seguinte forma:

Para demonstrar a utilização de problemas com tabelas de dados heterogêneos, considere o seguinte problema:
Exemplo: Efetuar a leitura de 2 notas bimestrais de n alunos, calcule a média de cada aluno e no final
apresentar os dados, nome e média, classificados por nome. Considere n ≤20.

Prof. Christiano Colen Venancio 29


UNIPAC Ipatinga - 2007
Prof. Christiano Colen Venancio 30
UNIPAC Ipatinga - 2007
Prof. Christiano Colen Venancio 31
UNIPAC Ipatinga - 2007
No algoritmo, na seção de definição de tipos são declarados três tipos, o tipo cadeia e o tipo bimestre, e após
isso o tipo registro NOTAS_ALUNOS, com os campos nome, notas e média.
Sendo que nome é do tipo cadeia, e notas é do tipo bimestre, que é um vetor de número reais de 2 posições. O
algoritmo utiliza o método de ordenação bolha, que, é efetuada com base no nome de cada aluno.

Prof. Christiano Colen Venancio 32


UNIPAC Ipatinga - 2007
Prof. Christiano Colen Venancio 33
UNIPAC Ipatinga - 2007