Sei sulla pagina 1di 140

Sebenta da Disciplina de Introdução à Programação

Índice de Matérias

1- Conceitos Básicos de Ciências da Computação.................................................................................................... 4


1.1 - Motivação ............................................................................................................................................................ 4
1.2 - Resolução de Problemas .................................................................................................................................... 4
1.2.1 - Criação de Algoritmos ................................................................................................................................. 5
1.2.2 - Técnicas de Descrição de Algoritmos ......................................................................................................... 7
1.3 - Do Algoritmo ao Programa ................................................................................................................................ 15
1.3.1 - Representação Digital da Informação ....................................................................................................... 15
1.3.2 - Componentes de um Computador ............................................................................................................ 16
1.4 - Linguagens de Programação ............................................................................................................................ 17
1.4.1 - Tradução de Linguagens de Programação ............................................................................................... 17
1.5 - A Linguagem Java............................................................................................................................................. 18
1.5.1 - Compilar um Programa em Java............................................................................................................... 18
1.5.2 - Exemplo de um Programa em Java .......................................................................................................... 19
1.6 - Exercícios Práticos ............................................................................................................................................ 19
2 - Introdução as noções de Classe e Objecto.......................................................................................................... 21
2.1 - Conceito de Objecto e Classe ........................................................................................................................... 21
2.2 - Exercícios .......................................................................................................................................................... 25
3 - Conceitos básicos de programação em Java....................................................................................................... 27
3.1 - Identificadores ................................................................................................................................................... 27
3.2 - Palavras Reservadas ........................................................................................................................................ 27
3.3 - Símbolos e Valores ........................................................................................................................................... 28
3.4 - Variáveis............................................................................................................................................................ 28
3.4.1 - Variáveis de Instância: Atributos ............................................................................................................... 29
3.5 - Tipos de Dados ................................................................................................................................................. 29
3.5.1 - Tipos de Dados Primitivos......................................................................................................................... 30
3.5.2 - Tipos de Dados Referenciados ................................................................................................................. 33
3.6 - Operadores e Expressões................................................................................................................................. 35
3.6.1 - Operadores de Atribuição ......................................................................................................................... 35
3.6.2 - Operadores Aritméticos............................................................................................................................. 35
3.6.3 - Operadores Lógicos .................................................................................................................................. 37
3.6.4 - Operadores Relacionais............................................................................................................................ 38
3.6.5 - Expressões................................................................................................................................................ 38
3.7 - Métodos............................................................................................................................................................. 39
3.7.1 - Método construtor sem argumentos.......................................................................................................... 40
3.7.2 - Invocação de métodos e passagem de parâmetros ................................................................................. 41
3.7.3 - Métodos construtores com argumentos .................................................................................................... 45
3.7.4 - Métodos selectores ................................................................................................................................... 47
3.7.5 - Métodos modificadores ............................................................................................................................. 48
3.8 - Estrutura de Aplicações em JAVA..................................................................................................................... 49
3.8.1 - Estrutura do programa principal ................................................................................................................ 49
3.8.2 - Visibilidade das Variáveis.......................................................................................................................... 50
3.8.3 - Entrada e Saída de Dados ........................................................................................................................ 50
3.8.4 - Definição de Novas Classes ..................................................................................................................... 53
3.8.5 - Utilização de classes existentes em JAVA................................................................................................ 54
3.8.6 - Comentários .............................................................................................................................................. 56
3.8.7 - Paragrafação / Indentação ........................................................................................................................ 56
3.9 - Exercícios Práticos ............................................................................................................................................ 57
4 - Instruções de Controlo ......................................................................................................................................... 58
4.1 - Selecção............................................................................................................................................................ 58
4.1.1 - Selecção Simples: if............................................................................................................................... 58
4.1.2 - Selecção Em Alternativa: if-else....................................................................................................... 60

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 1


Sebenta da Disciplina de Introdução à Programação

4.1.3 - Selecção Múltipla: switch - case .................................................................................................. 65


4.2 - Repetição .......................................................................................................................................................... 68
4.2.1 - Instrução de Repetição while ............................................................................................................... 68
4.2.2 - Instrução de Repetição do-while ....................................................................................................... 70
4.2.3 - Instrução de Repetição for .................................................................................................................... 72
4.3 - Exercícios Práticos ............................................................................................................................................ 76
5 - Tópicos Avançados de Classes ........................................................................................................................... 82
5.1 - Variáveis de Instância e variáveis de Classe .................................................................................................... 82
5.2 - Modificadores de visibilidade............................................................................................................................. 85
5.3 - Encapsulamento................................................................................................................................................ 85
5.4 - O Operador de Auto-Referenciação this ...................................................................................................... 85
5.5 - Passagem por Parâmetros Referenciados........................................................................................................ 86
5.6 - Sobrecarga de Métodos .................................................................................................................................... 87
5.7 - Exercícios Práticos ............................................................................................................................................ 88
6 - Tabelas................................................................................................................................................................. 90
6.1 - Motivação .......................................................................................................................................................... 90
6.2 - Tabela Unidimensional ...................................................................................................................................... 92
6.2.1 - Introdução ................................................................................................................................................. 92
6.2.2 - Passos para utilizar uma tabela ................................................................................................................ 92
6.3 - Tabelas de Objectos.......................................................................................................................................... 96
6.4 - Passagem de tabelas como parâmetros de métodos ..................................................................................... 107
6.5 - Tabela Multidimensional.................................................................................................................................. 108
6.6 - Classe Vector .................................................................................................................................................. 110
6.6.1 - Introdução ............................................................................................................................................... 110
6.6.2 - Alguns métodos da classe Vector...................................................................................................... 110
6.7 - Exercícios Práticos .......................................................................................................................................... 111
7 - Algoritmos de Procura/Pesquisa ........................................................................................................................ 114
7.1 - Introdução........................................................................................................................................................ 114
7.2 - Procura Sequencial ......................................................................................................................................... 114
7.2.1 - Simples.................................................................................................................................................... 114
7.2.2 - Com Sentinela......................................................................................................................................... 116
7.3 - Procura Binária................................................................................................................................................ 117
7.4 - Exercícios práticos .......................................................................................................................................... 119
8 - Algoritmos de Ordenação................................................................................................................................... 121
8.1 - Introdução........................................................................................................................................................ 121
8.2 - BubbleSort....................................................................................................................................................... 122
8.3 - ShellSort .......................................................................................................................................................... 124
8.4 - Ordenação por selecção ................................................................................................................................. 126
8.5 - Algoritmo QuickSort......................................................................................................................................... 127
8.6 - Exercícios práticos .......................................................................................................................................... 129
9 - Recursividade..................................................................................................................................................... 130
9.1 - Definições........................................................................................................................................................ 130
9.2 - Exercícios práticos .......................................................................................................................................... 132
10 - Anexo I – Exemplo Introdutório em Java ...................................................................................................... 134
11 - Anexo II – Glossário...................................................................................................................................... 136
12 - Anexo III - Bibliografia ................................................................................................................................... 138

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 2


Sebenta da Disciplina de Introdução à Programação

Nota: Ao longo da leitura deste documento, sempre que não entender o significado de determinado termo, por favor
dirija-se ao glossário que é apresentado em anexo para descobrir uma possível definição para o mesmo.
Caso não esteja lá definida a palavra que procura, não hesite em questionar os colegas ou professores para melhor
ficar esclarecido.
Ao notificar o professor estará também a contribuir para melhorias futuras no documento, pois novas palavras poderão
ser adicionadas ao glossário que possivelmente esclarecerão outros colegas com dúvidas semelhantes à sua.

Este documento, para além de ter sido elaborado pelos professores já mencionados, conta com a participação dos
docentes da cadeira de IP dos anos lectivos de 2000/2001 até 2004/2005, visto terem sido utilizados os respectivos
acetatos como referência para alguns dos conteúdos aqui utilizados. A sebenta do ano lectivo 2004/2005 foi
reestruturada e melhorada.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 3


Sebenta da Disciplina de Introdução à Programação

1- Conceitos Básicos de Ciências da Computação

1.1 - Motivação
Nas sociedades modernas todos os sectores de actividade dependem directa ou indirectamente do apoio dos
computadores.

O funcionamento dos computadores depende da conjunção do Hardware, componentes físicos, e do Software,


instruções que os computadores devem executar. Pode dizer-se que os programas fornecem conhecimentos e
estratégias de resolução de problemas. A programação é a “arte” de analisar um problema e encontrar uma sequência
de acções (um algoritmo) capaz de o resolver correctamente.

1.2 - Resolução de Problemas


O objectivo de um programador, quando escreve um programa, é o de resolver um ou mais problemas. Para que se
possa resolver um problema é necessário que seja primeiramente encontrada uma maneira de o descrever de forma
clara e precisa. É necessário que encontremos uma sequência de passos que permitam que o problema possa ser
resolvido de maneira automática e repetitiva. Esta sequência de passos é chamada de Algoritmo. Assim, podemos
afirmar que o passo fundamental na criação de um programa é a definição de um algoritmo isto é, a forma como a
partir de um problema se consegue obter a solução. Contrariamente ao que se possa pensar, na maioria das vezes, a
principal dificuldade não reside na sintaxe1 ou na semântica2 da linguagem de programação utilizada, mas sim na
procura de soluções para o problema em causa.

Um algoritmo pode ser definido como um conjunto finito de instruções bem definidas e não ambíguas, que
executadas por uma determinada ordem resolvem um problema.

Para que se possa encontrar uma boa solução para um problema, é necessário começar pela sua compreensão. Em
seguida, o problema deve ser analisado no sentido de procurar soluções para o mesmo. Quando se faz a análise de
um problema é importante considerar três componentes:
ƒ estado inicial, isto é quais os dados de entrada do problema;
ƒ a transformação, que especifica os passos necessários para transformar o estado inicial no estado final;
ƒ estado final, ou seja, o que se pretende obter como resultado.

Muitos dos erros dos programadores são causa de uma deficiente compreensão e análise do problema.

A resolução de problemas é uma tarefa para a qual não há receitas nem fórmulas, pois cada problema é um caso
diferente, tal como podem ser inúmeras as soluções que o resolvem. Umas serão mais correctas ou terão melhor
desempenho que outras, umas ainda serão mais ou menos exaustivas; cabe-nos a nós, como programadores, saber
averiguar qual das soluções encontradas se adequa melhor às necessidades da tarefa que temos em mãos.

Exemplo:

Vamos supor que temos como tarefa resolver o problema da confecção de um bolo. Uma receita não é mais do que
uma descrição de passos ou acções que fazem a combinação de um conjunto de ingredientes com vista a obter um
produto final (bolo).

1 Sintaxe de uma linguagem é o conjunto de regras que define as relações válidas entre componentes da linguagem.
2 Semântica de uma linguagem define o significado de cada frase da linguagem.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 4


Sebenta da Disciplina de Introdução à Programação

Analisando tudo o que é necessário para cumprir essa tarefa e tendo em conta os passos atrás mencionados, quais
são os passos a seguir?

ƒ Estado inicial: ingredientes (respectivas quantidades)


ƒ Transformação: processo de confecção do bolo (Algoritmo)
1. Misturar ingredientes
1.1 Bater a margarina e o açúcar até obter um creme;
1.2 Adicionar os ovos
1.3 Juntar a farinha e o fermento;
1.4 Colocar a massa numa forma
2. Cozinhar o bolo
2.1 Aquecer o forno à temperatura desejada
2.2 Colocar no forno e esperar que o bolo esteja cozido
ƒ Estado final: um bolo

Afinal não é só na programação de computadores que podemos aplicar algum método ou tipo de raciocínio para
resolver problemas!

Com este exemplo vimos aplicada a um caso da vida quotidiana exactamente a mesma ordem de pensamento que
iremos seguir daqui por diante na implementação de programas de computadores.

1.2.1 - Criação de Algoritmos


A criação de algoritmos é fundamental no desenvolvimento de programas de computador. Quando se trata de
programas complexos, surgem dificuldades adicionais devidas há quantidades de aspectos que é necessário
considerar no momento. A complexidade tanto pode ser gerada pela dimensão, como pela dificuldade do problema a
resolver.

1.2.1.1 - Abordagens Top-Down e Bottom-Up


Existem duas abordagens para a resolução de problemas. Uma, a mais utilizada, é a conhecida como “abordagem do
topo para a base” (abordagem Top-Down), por partir de um problema geral e procurar chegar aos detalhes. Nesta
abordagem o problema complexo é dividido em problemas mais simples e procura-se soluções para esses problemas
mais simples.

Existe também a abordagem contrária, apelidade de Bottom-Up que parte da base para o topo, ou seja, partindo de
problemas pequenos, visualizar a solução para algo mais amplo e mais genérico.

Pode até utilizar-se um misto destas duas abordagens, desde que no fim consigamos atingir uma boa solução para o
problema.

Em qualquer uma delas está inerente um conceito que é a base de resolução de qualquer problema: a divisão em
elementos de solução mais simples, que trabalhando em conjunto nos fazem chegar à solução que nos interessa.

Independentemente do sentido em que procuramos a solução, estamos sempre a utilizar uma técnica que se chama
“Divide and Conquer” , ou seja, Dividir para Conquistar. Ninguém ganha uma corrida só porque decide ganhar, tem de
correr as etapas todas uma por uma com o objectivo de no fim ter conseguido uma média de tempos inferior à dos
outros corredores!

Exemplo:

Fazer sumo de laranja

Aplicando o método anteriormente descrito, significa que temos de dividir um problema em partes menores (ou
subproblemas) de modo a que seja mais fácil a sua resolução

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 5


Sebenta da Disciplina de Introdução à Programação

Algoritmo:

Lavar a laranja
Partir a laranja ao meio
Espremer a laranja
Filtrar o sumo
Servir o sumo

O que se pode destacar com este exemplo é que cada passo é completado antes que o próximo comece. Como por
exemplo, é impossível ouvir rádio sem primeiro o ligar.

1.2.1.2 - Passos para elaboração de um algoritmo


Quando pretendemos escrever um algoritmo é importante que se sigam um conjunto de passos:

ƒ Compreender o problema
ƒ Identificar os dados de entrada
ƒ Identificar os dados de saída
ƒ Determinar o que é necessário para transformar dados de entrada em dados de saída, isto é, deve-se
descrever todas as transformações necessárias para resolver o problema, fazendo-o em termos que
possam ser executáveis pelo computador
- usar a estratégia de dividir em problemas mais pequenos
- observar regras e limitações
- identificar todas as acções a realizar
- eliminar ambiguidades (qualquer pessoa que o execute obtém os mesmos resultados)
ƒ Construir o algoritmo, tendo em consideração que:
-Para um mesmo conjunto de dados deve produzir sempre os mesmos resultados (se com os
mesmos ingredientes, nas mesmas quantidades tivéssemos bolos diferentes algo de errado se tinha
passado)
- Produzir resultados correctos, qualquer que seja o conjunto de dados legítimos utilizado.
ƒ Testar o algoritmo
ƒ Executar o algoritmo

No entanto, quando se concebem algoritmos para serem transformados em programas é importante exprimi-los
utilizando acções que o computador seja capaz de executar:

ƒ Receber e fornecer informação


ƒ Guardar informação para posterior utilização
ƒ Operações aritméticas
ƒ Operações lógicas
ƒ Escolher entre várias acções (selecção)
ƒ Repetir um grupo de acções (repetição)

Outro aspecto importante é que os nossos algoritmos vão ter que manipular valores, estes têm que ser guardados em
algum lugar. Para tal utilizam-se variáveis. Uma variável é um lugar na memória do computador onde podemos
colocar um valor, ou consultar o valor que lá está. Cada variável é identificada por um nome.

Exemplo:

Elaborar um algoritmo que calcule a área total das paredes de uma caixa de secção rectangular a partir das suas
dimensões.

Identificação das variáveis que o algoritmo vai manipular:


Dados de entrada: comprimento -> comp, largura -> largura, altura -> altura
Valores intermédias: area_base, area_lateral1, area_lateral2

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 6


Sebenta da Disciplina de Introdução à Programação

Dados de saida: área da caixa -> area_caixa

Algoritmo:
1. Introdução dos valores iniciais
1.1. Pedir comprimento da caixa
1.2. Ler comp
1.3. Pedir largura da caixa
1.4. Ler largura
1.5. Pedir altura da caixa
1.6. Ler altura
2. Transformação
2.1. area_base = comp * largura
2.2. area_lateral1 = comp * altura
2.3. area_lateral2 = largura * altura
2.4. area_caixa = 2 * area_base + 2 * area_lateral1 + 2 * area_lateral2
3. Apresentação dos resultados
3.1. Escrever area_caixa

1.2.2 - Técnicas de Descrição de Algoritmos


Os algoritmos não são directamente executáveis pelo computador, a forma como são descritos é um pouco livre,
ainda que deva ser suficientemente exacta para que não haja qualquer ambiguidade.

Existem várias técnicas para a descrição de algoritmos. Uma maneira de descrever algoritmos é usando linguagem
natural, em que os algoritmos são expressos directamente em linguagem natural (isto é, o português como no
exemplo do bolo). Outra maneira é usando pseudocódigo (exemplo calculo da área). O pseudocódigo é um código
de escrita em que se utilizam termos convencionais para indicar as instruções do programa; esses termos são
geralmente um misto de palavras da nossa linguagem natural com palavras e notações típicas das linguagens de
programação. A utilização de pseudocódigo permite ao programador expressar as suas ideias sem ter de se
preocupar com a sintaxe da linguagem de programação. Os algoritmos podem também ser descritos utilizando
fluxogramas. Os fluxogramas são diagramas representativos do fluxo de acções de um programa, através de
símbolos, que representam os diferentes tipos de acções e seu encadeamento na sequência do programa (ver figura
abaixo).

Figura 1. Representação gráfica de um algoritmo.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 7


Sebenta da Disciplina de Introdução à Programação

Processamento em geral

Leitura/Escrita de Dados

Início/Fim de processamento

Linha de fluxo

Decisão condicional

Escolha múltipla

Subprograma

Figura 2. Principais símbolos utilizados nos fluxogramas.

Actualmente os fluxogramas não são efectivamente muito utilizados. No entanto, talvez possam ser úteis para ajudar
a visualizar melhor determinadas estruturas típicas de programação. Mas, para representar programas de média e
grande extensão, tornam-se difíceis de concretizar.

Exemplo

Elaborar um algoritmo que calcule o quadrado de um número.

Pseudocódigo
Início
Pedir valor de a
Ler a
Calcular quadrado de a
result = (a*a)
Escrever “O quadrado é:” result
Fim

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 8


Sebenta da Disciplina de Introdução à Programação

Fluxograma

Início

Pedir a

Ler a

result = a*a

Escrever “O
quadrado é:”
result

Fim

1.2.2.1 - Estruturas de controlo


Uma estrutura de controlo é a unidade básica da lógica de programação. Podemos dizer que qualquer programa pode
ser construído através da combinação de 3 estruturas básicas: sequência, selecção e repetição.

Numa sequência é processado um conjunto de acções (ou instruções) em série. O conjunto de acções é executado
exactamente pela ordem em que as instruções estão indicadas, não havendo qualquer possibilidade de alterar a
ordem de processamento dessas acções.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 9


Sebenta da Disciplina de Introdução à Programação

Uma estrutura de selecção (ou decisão) é uma estrutura que permite, com base numa condição, decidir sobre a
execução ou não de determinada acção ou optar entre duas alternativas expressas. Ou seja, o processo segue por
uma de duas vias, dependendo do valor lógico (verdadeiro ou falso) da expressão que é avaliada no início da
estrutura.

Falso Verdadeiro Falso Verdadeiro


Expressão Expressão

Exemplo

Elaborar um algoritmo que calcule o zero da equação ax+b=0.

Pseudocódigo
Início
Pedir valor a
Ler a
Pedir valor b
Ler b
Se a ≠ 0 então
Calcular o valor de x (ax+b=0)
Escrever valor de x
Senão
Escrever “Não há zero”
Fim

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 10


Sebenta da Disciplina de Introdução à Programação

Fluxograma

Início

Pedir
Ler a

Ler ab

Pedir
Ler ab

Ler b

Não
a≠0

Sim

x= - b/a

Escrever Escrever “Não


valor de x Existe zero.”

Fim

Exemplo

Elaborar um algoritmo que verifique qual o maior de dois números.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 11


Sebenta da Disciplina de Introdução à Programação

Pseudocódigo:
Início
Pedir “Introduza dois números”
Ler valor 1
Ler valor 2
Se valor1 > valor 2 então
Escreve valor1 “é maior”
Senão
Se valor1 < valor 2 então
Escreve valor2 “é maior”
Senão
Escreve “valores iguais”
Fim_Se
Fim_Se
Fim

Fluxograma:

Início

Pedir
Ler dois
a valores

Ler valor 1

Ler valor 2

Não Não
valor 1 > valor 2 valor 1 < valor 2

Sim Sim

Escrever Escrever Escrever


valor 1 é maior valor 2 é maior valores iguais

Fim

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 12


Sebenta da Disciplina de Introdução à Programação

Por último falta falar das estruturas de repetição (também conhecidas por ciclos). Neste caso também é necessário
tomar a decisão com base no valor lógico de uma expressão. No entanto, a mesma acção é expressa repetidamente
enquanto o resultado da expressão lógica se mantiver verdadeiro.

Nas estruturas de repetição o teste da expressão lógica pode preceder a acção ou pode suceder a acção, isto é na
primeira situação a acção só é realizada se a condição tiver o valor lógico verdadeira, no segundo caso a acção é
sempre realizada qualquer que seja o valor lógico da expressão pois este só é verificado depois da acção ter sido
realizada.

Expressão
Verdadeiro
Falso Expressão
Verdadeiro
Falso

Expressão
Verdadeiro
Falso

Esta última estrutura de repetição é idêntica às duas anteriores. A diferença é que logo à partida é especificado o
número de ciclos (ou iterações) que serão efectuados, isto é o número de vezes que a acção é realizada.

Estas estruturas apresentam grandes vantagens para a programação em termos de economia de escrita de código,
uma vez que, com um determinado número de instruções, pode repetir-se um conjunto de acções um determinado
número de vezes ou enquanto se quiser, mediante uma expressão de controlo.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 13


Sebenta da Disciplina de Introdução à Programação

Exemplo

Elaborar um algoritmo em que um utilizador introduz um número e outro utilizador vai tentar advinhar esse número,
introduzindo números até a acertar. O segundo utilizador só para de introduzir número quando acertar.

Algoritmo Fluxograma

Início
Pedir a Início
Ler a (número a acertar)
Repetir
Pedir b
Ler b
Até que a = 0 Pedir a
Escrever “Acertou”
Fim
Ler a

Pedir b

Ler b

Não
a=b

Sim

Escrever
“Acertou”

Fim

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 14


Sebenta da Disciplina de Introdução à Programação

Não existe consenso entre os especialistas sobre qual é a melhor maneira de representar um algoritmo. Actualmente
a maneira mais comum de representar é através de pseudocódigo. A utilização de pseudocódigo tem a vantagem de
podermos utilizar um texto escrito dessa forma como base para a escrita de um programa, não apenas numa
determinada linguagem de programação, mas em qualquer outra, sem ter de se elaborar um novo algoritmo.
Outra vantagem da escrita de algoritmos em pseudocódigo é que esta forma de abordagem presta-se a uma
aproximação sucessiva à versão final do programa, ou seja, pode-se ir progredindo por fases, revendo o
pseudocódigo e substituindo-o progressivamente por termos e sinais próprios da linguagem de programação.

1.3 - Do Algoritmo ao Programa


1.3.1 - Representação Digital da Informação
Os computadores armazenam e processam toda a informação, utilizando o sistema de numeração Binário. O sistema
de numeração binário é um sistema de dois estados. A unidade básica deste sistema é o bit, que pode assumir
apenas dois estados distintos, representados pelos valores 0 e 1.
Observemos a tabela seguinte:

Num. Decimal 1 bit 2 bits 3 bits


0 0 00 000
1 1 01 001
2 10 010
3 11 011
4 100
5 101
6 110
7 111
... ... ... ...
Como podemos verificar na tabela N bits representam 2N itens distintos. Quer-se com isto dizer, com 1 bit
conseguimos representar 21 = 2 números, com 2 bits conseguimos representar 22 = 4 números distintos, com 3 bits
representam-se 23 = 8 números, e assim sucessivamente.
A conversão de números do sistema binário para o sistema decimal também é simples, vejamos o seguinte exemplo:

111 = 1*22 + 1*21 + 1*20 = 7


101 = 1*22 + 0*21 + 1*20 = 5

Do sistema decimal para o sistema binário, basta fazer divisões sucessivas por dois e aproveitar o resto da divisão
inteira:

7 / 2 = 3 e o resto da divisão é 1
3 / 2 = 1 e o resto da divisão é 1
1 / 2 = 0 e o resto da divisão é 1

Os computadores armazenam dados em séries de 8 bits, denominados bytes.


Consoante o número de bits ou de bytes podemos dar nomes diferentes às unidades (à semelhança do que acontece
no sistema métrico com metros, decímetros, centímetros, etc.). Vejamos a tabela seguinte:

Unidade Conversão Símbolo SI


1 bit N/A b
1 byte 8 bit B
1 Kilobyte 1024 byte KB
1 Megabyte 1024 Kilobyte MB
1 Gigabyte 1024 Megabyte GB

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 15


Sebenta da Disciplina de Introdução à Programação

Existem outros sistemas de numeração para além do decimal e do binário, tais como o octal e o hexadecimal, por
exemplo.

1.3.2 - Componentes de um Computador


Um computador tem uma parte física (hardware), constituída pelo monitor, teclado, rato, memória etc., e uma parte
não física (software), constituídas pelos programas.

Periféricos Unidade
Central de Processamento Periféricos
De Entrada De Saída
(CPU)

Memória Memória
Principal Secundária

Figura 3. Componentes de um computador.


O componente mais importante do computador é a unidade central (CPU – Central Processing Unit). A função básica
do CPU é obter, interpretar e executar instruções, uma de cada vez. Esta unidade executa continuamente um ciclo
que consiste nos passos seguintes:

• Aquisição (obtenção de uma instrução)


• Descodificação (determinação do tipo de instrução)
• Execução (execução da instrução).

O CPU é constituído por:

Efectua cálculos (adição, subtracção e


Unidade Aritmética/Lógica outras operações aritméticas, bem como a
comparação de valores) e toma decisões
Determina a próxima instrução a ser
Unidade Controle
executada (controla todos os passos do
processamento)

Pequeno número de registos com grande


Registos
velocidade de acesso, para armazenamento
de resultados temporários

Figura 4. Componentes da CPU.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 16


Sebenta da Disciplina de Introdução à Programação

Outro elemento fundamental é a memória central, também conhecida por RAM (Random Access Memory). É uma
área de armazenamento de informação que apresenta as seguintes características:
ƒ Perde o conteúdo quando se desliga o computador – memória volátil;
ƒ Pode ser imaginada como sucessão de células (ver figura abaixo);
ƒ Cada célula de memória armazena um único valor;
ƒ Quando se escreve um novo valor numa célula de memória, perde-se o valor que anteriormente lá estava;
ƒ A capacidade da memória é expressa no número de bytes que ela consegue armazenar: kilobytes (KB –
1024 bytes), megabytes (MB – 1024 KB ou 1024000 bytes), gigabytes (GB – 1024 MB ou 1024000000
bytes)

Supondo que tínhamos uma memória RAM de 1MB, a sua representação gráfica poderia ser a seguinte (em que os
números abaixo da tabela de células representam os índices que identificam cada célula. Célula número 1, 2, ... 256,
etc):

z a 12 x
0 1 2 3 ... 256 ... 512 ... 1024

Figura 5. Representação gráfica da memória central de um computador (RAM)

Para além da CPU e da memória central, existem diversos tipos de dispositivos que permitem a comunicação entre o
computador e o utilizador, como por exemplo:

• dispositivos de entrada: teclado, rato;


• dispositivos de saída: monitor, impressora;
• dispositivos de entrada/saída: modem.

O armazenamento permanente da informação é conseguido em dispositivos de armazenamento secundário:


ƒ Armazém de dados ligado à memória principal
ƒ Mantém o conteúdo mesmo com o computador desligado – memória não volátil – armazenamento
permanente (também se diz persistente) da informação

Estes dispositivos de armazenamento secundário persistente são os Discos rígidos, disquetes, CD-Roms, DVDs,
FlashDrives, cartões de memória usados nas máquinas fotográficas digitais, entre outros.

1.4 - Linguagens de Programação


Para que um computador possa executar determinada tarefa, é necessário que lhe seja fornecido um programa. Os
programas são escritos utilizando linguagens de programação.

Há diversos níveis de linguagem de acordo com as afinidades que apresentam com as linguagens humanas:
ƒ Linguagens Máquina: são utilizadas para comandar directamente as acções do computador. As instruções
são constituídas por 0s e 1s, e manipulam directamente entidades dentro do computador.
ƒ Linguagens Assembly: são linguagens com características semelhantes às das de máquina, diferindo
apenas por usarem nomes simbólicos em vez de sequências de 0s e 1s.
ƒ Linguagens de Alto Nível: são linguagens mais próximas das linguagens humanas e, por isso, são mais
fáceis de utilizar do que as outras.
Há muitas linguagens que se podem incluir nesta categoria: C, Pascal, Lisp, Prolog, C++ e Java.

1.4.1 - Tradução de Linguagens de Programação


Um programa é fornecido ao computador para que este o possa executar. No entanto, os computadores só entendem
linguagem máquina, pelo que é necessário proceder à tradução do programa. Para efectuar essa tradução utilizamos

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 17


Sebenta da Disciplina de Introdução à Programação

compiladores. Os compiladores são programas que fazem a tradução do código fonte (escrito numa linguagem de
alto nível) para código executável (em linguagem máquina).

A primeira função dos compiladores é verificar se o código fonte que lhe é fornecido cumpre as regras sintácticas da
linguagem em causa e assinalar os erros que eventualmente existam, denominados por erros de compilação. Aos
erros que ocorrem durante a execução do programa e que não podem ser detectados durante a compilação dá-se o
nome de erros de execução.

Um programa sem erros de compilação não significa necessariamente que funcione como era desejado. Pode ter
erros semânticos (ou seja, erros lógicos, derivados de um raciocínio errado que levou a uma solução também
incorrecta). Neste caso, teremos de proceder a uma revisão do código e novos testes para que os erros sejam
resolvidos.

1.5 - A Linguagem Java


JAVA é uma linguagem de programação orientada a objectos, desenvolvida pela Sun Microsystems. Esta linguagem
resultou da ideia de criar uma linguagem que pudesse ser executada em qualquer tipo de computador.

1.5.1 - Compilar um Programa em Java


Um dos objectivos principais do desenvolvimento do Java era a possibilidade de um programa escrito nesta linguagem
ser executado em qualquer tipo de computador sem ter de ser alterado ou compilado novamente. No entanto, este
objectivo não pode ser atingido com a utilização de compiladores tradicionais.

Este problema fica resolvido considerando um computador virtual que se imagina capaz de executar um código
constituído por instruções simples. O compilador Java não gera código executável mais sim bytecode, um código
que é independente do computador em que seja executado. Esse código tem de ser interpretado pela chamada
Máquina Virtual Java, que é um programa em execução no computador e que é responsável por executar programas
Java.
Existem versões diferentes desta Máquina Virtual para diferentes sistemas operativos (Windows, Unix, Linux, Solaris,
MacOS, etc).

A figura seguinte descreve o processo de criação, compilação e execução de um programa em Java.

Código Fonte Java O “código-fonte”, quando passa pelo compilador, é


transformado num conjunto de
Tradução bytes formatados – designados de bytecodes.
Nesta fase não se trata ainda de “código-máquina”,
Compilador Java mas sim de um código intermédio.
Os bytescodes não podem ser executados
directamente nos diversos processadores.
São necessários interpretadores, essa interpretação
Bytecode Java é feita pela JVM (Java Virtual Machine).

Execução

Máquina Virtual Java


(JVM, Interpretador Java)

Figura 6. Processo de criação, compilação e execução de um programa em Java.

A utilização do código intermédio tem a vantagem de permitir aos computadores criar programas que podem ser
executados em qualquer tipo de computador, sem que tenham que se preocupar com as suas especificações. Desde

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 18


Sebenta da Disciplina de Introdução à Programação

que esse computador tenha a máquina virtual correspondente instalada, qualquer programa Java poderá ser lá
executado.

Para criar programas em Java é necessário ter instalado no computador, pelo menos o Java Standard Edition
Software Development Kit (J2SE SDK) instalado no computador.

1.5.2 - Exemplo de um Programa em Java


De seguida apresentada um programa simples em Java para imprimir uma pequena mensagem no ecrã .

public class OlaMundo {


public static void main (String[] args){
System.out.println(“Ola Mundo!”);
}
}
Figura 7. Código fonte de um programa em Java.

Ola Mundo!

Figura 8. Ecrã com o resultado da execução do programa.

1.6 - Exercícios Práticos


Escreva um algoritmo para resolver cada um dos seguintes problemas.

Exerc. 1: Descrever a sequência de passos necessários para pôr um carro a trabalhar.

Exerc. 2: Verificar se um número se encontra entre 1 e 10.

Exerc. 3: Calcular a nota de uma disciplina que é composta por 20% para o trabalho e 80% para o exame. O
utilizador introduz as duas nota e é apresentada a nota final.

Exerc. 4:
a) Calcular o salário de um funcionário obtendo o valor e o número de horas semanais sabendo que se o número de
horas for superior a 40, as 40 horas são pagas pelo preço normal e as restantes pelo dobro do valor.
b) Altere o algoritmo anterior de forma a incluir um valor diferente para o número de horas superior a 60. Isto é:
Até 40 horas – preço da hora
Das 40 às 60 horas – dobro do preço da hora
A partir das 60 horas – triplo da hora.

Exerc. 5:
a) Calcular a média da nota de três exames introduzidos pelo utilizador.
b) Altere o algoritmo anterior de forma a receber só notas compreendidas entre 0 e 20 valores.
c) Alterar o algoritmo de forma a indicar se o aluno está aprovado (média superior a 10 valores) ou reprovado.

Exerc. 6: Dado um valor de temperatura, em graus Celsius, Farenheit ou Kelvin, converter esse valor para as
restantes unidades. (Nota: ºC = (ºF-32)*5/9; ºK = ºC+273.15)

Exerc. 7: Fazer uma chamada de um telefone público. Deve considerar casos tais como “o telefone está ocupado”, “o
telefone está avariado”, “o número desejado está interrompido”, etc.

Exerc. 8: Somar um conjunto de 100 números inteiros.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 19


Sebenta da Disciplina de Introdução à Programação

Exerc. 9: Receber uma seqência de números e determinar se um dado número (também recebido) aparece ou não
na sequência.

Exerc. 10: Determinar o resultado de uma expressão matemática que utilize os operadores: + e -

Exerc. 11: Calcular o perímetro e a área de uma figura geométrica, sabendo que a figura só pode ser um rectângulo
ou uma circunferência.

Exerc. 12: Procurar uma nota de um aluno numa pauta, através do seu número

Exerc. 13: Descobrir um número entre 0 e 1000, pensado por um colega. Após ter acertado informar o colega do
número de tentativas efectuadas.

Exerc. 14: Determinar se o número é primo.

Exerc. 15: Receber uma sequência ordenada de números e determinar se um dados número aparece ou não na
sequência. Qual a principal diferenção entre este algoritmo e o exercício 9.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 20


Sebenta da Disciplina de Introdução à Programação

2- Introdução as noções de Classe e Objecto

2.1 - Conceito de Objecto e Classe


Antes de introduzirmos os conceitos relacionados com a programação orientada por objectos convém relembrarmos
algumas definições que nos acompanham no nosso dia a dia e as quais nos fazem falta daqui para a frente.

Ao consultarmos um dicionário constatamos que a definição de conceito é “ Tudo o que o espírito e a alma concebem
ou entendem”, mais terra a terra, “ é uma ideia ou noção que aplicamos às coisas, ou objectos da nossa consciência.
Por exemplo, para dizermos que temos o conceito de barco apenas precisamos da capacidade de identificar uma
instância de um barco.

Tendo por base, a definição de conceito e as abstracções que realizamos no nosso dia a dia, é nos possível definir
classes. Uma classe não é mais que um grupo de pessoas, animais ou coisas. Mas como os agrupamos? Se
pensarmos bem, chegamos à conclusão que ao definir por exemplo um grupo de animais, o fazemos através dos seus
atributos, das suas características. Vejamos, no reino animal podemos definir vários grupos, tais como carnívoros vs
herbívoros, ovíparos vs mamíferos, entre outras.

A linguagem de programação Java diz-se orientada aos objectos. Num paradigma de objectos, ao contrário do que se
possa pensar, não se procura uma nova forma de programar, mas sim orientarmo-nos para uma forma de pensar
abstracta relativamente a qualquer problema, utilizando para isso conceitos do mundo real.

Por exemplo, peguemos num conceito que todos nós conhecemos, o de aluno. Aluno é todo aquele que é educado
por um segundo elemento, normalmente numa instituição. Ao conceito de Aluno chamamos de classe, em
programação orientada por objectos. Mais, de acordo com a definição de classe mencionada em cima, podemos
afirmar que são várias as características de um aluno – nome, número, curso em que está inscrito, turma, entre
outras. A estas características chamamos atributos.

Atributo define uma característica das futuras instâncias de uma classe. Têm um nome único dentro da mesma
classe.

Nome - João Número - 2134

Curso - EI
Turma - A

Ano – 1º

Por outro lado, sabemos ainda que, o aluno pode pagar propinas, pode transitar de ano, pode inscrever-se numa
determinada turma, pode mudar de turma. Estes são alguns dos comportamentos que um aluno pode desempenhar,

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 21


Sebenta da Disciplina de Introdução à Programação

definindo aquilo que em orientação a objectos designamos de métodos. Os métodos representam funcionalidades
específicas da classe.

Relembrando o conceito introduzido até aqui,

Uma classe é uma descrição de grupos de objectos com propriedades, comportamentos e relações comuns. Define,
assim uma categoria de objectos.

Analisemos de seguida a seguinte figura:


Isabel
João 2135
2134 EI
EI Turma A
Turma A 1º Ano
1º Ano
Pedro
Ana 2131
2133 EI
EI Turma A
Turma A 1º Ano
1º Ano

Temos vários elementos a serem identificados com as mesmas características, nome, número, curso e turma.
Aproveitando a classe descrita anteriormente, podemos afirmar que estamos na presença de vários alunos, ou seja,
debaixo do mesmo conceito de Aluno. Estamos perante aquilo a que em programação orientada por objectos
chamamos de objectos.

Visualizamos então vários objectos da classe aluno e verificamos que:

Um objecto é um elemento de uma classe e possui as mesmas características e modo de funcionamento que os
outros elementos (objectos) da mesma classe.

Podemos dizer que o objecto é uma instância de uma classe . Aluno1 é uma instância da classe Aluno.

Os objectos colaboram com outros objectos através da troca de mensagens (invocação de métodos) para produzir
resultados relevantes para o domínio do problema.

Os objectos são normalmente descritos (através das classes) recorrendo a nomes, pronomes, adjectivos ou
advérbios.

Na figura em cima apresentada temos vários objectos representados:

Classe Aluno Atributos


Objecto Nome Número Curso Turma
Aluno1 João 2134 EI A
Aluno2 Ana 2133 EI A
Aluno3 Pedro 2131 EI A
Aluno4 Isabel 2135 EI A

Assim, os objectos têm:

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 22


Sebenta da Disciplina de Introdução à Programação

• Identidade (definida pela classe) e pelo nome de identificação do objecto;


• Estado (atributos) – Cada um conhece e guarda os seus dados, ou seja os valores dos atributos;
• Comportamento – métodos, também definidos pela classe. Todos os objectos da mesma classe sabem
executar o mesmo comportamento.

É possível dizer neste momento que as classes não são mais do que uma espécie de moldes a partir dos quais
criamos instâncias (objectos).

Imaginemos que um dos alunos pretende mudar de turma, como faze-lo? Basta recorrer aos métodos existentes na
classe, que foram previamente definidos. Vejamos:

O objecto Aluno1 pretende mudar da turma A para a Turma E.

O objecto Aluno1 invoca o método que altera a turma.

Classe Aluno Atributos


Objecto Nome Número Curso Ano Turma
Aluno1 João 2134 EI 1 E
Aluno2 Ana 2133 EI 1 A
Aluno3 Pedro 2131 EI 1 A
Aluno4 Isabel 2135 EI 1 A

Método define uma funcionalidade das futuras instâncias de uma classe. São normalmente descritos recorrendo a
verbos, por indicarem algum tipo de acção. Permitem modificar ou interrogar os objectos relativamente ao seu estado
actual.

A utilização dos métodos passa normalmente por duas fases:

• Definição - definir o que e que um método sabe fazer no âmbito do objecto a que pertence.
• Invocação - processo de enviar mensagens a um objecto para que determinado método do seu
comportamento seja executado.

Supondo que uma nova aluna ingressa na escola, será necessário registar um novo aluno. Como?
• Criar uma instância da classe Aluno - objecto Aluno5.
• Que informação será necessária para criar essa instância? - Nome, número, curso, turma

Classe Aluno Atributos


Objecto Nome Número Curso Ano Turma
Aluno1 João 2134 EI 1 E
Aluno2 Ana 2133 EI 1 A
Aluno3 Pedro 2131 EI 1 A
Aluno4 Isabel 2135 EI 1 A
Aluno5 Rita 2137 EM 1 A

Supondo que desejamos consultar o número de um aluno .

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 23


Sebenta da Disciplina de Introdução à Programação

• Deve-se invocar um método que devolva o número do aluno. Esse método deve ser implementado na classe
Aluno.
E que desejamos consultar a turma de um aluno .
• Deve-se invocar um método que devolva a turma do aluno. Esse método deve ser implementado na classe
Aluno.

No mundo que nos rodeia lidamos com vários grupos de pessoas, animais ou coisas, ou seja, várias classes que
coexistem para algum fim. Em programação, podemos criar também várias classes. Imaginemos o seguinte: No
domínio Escola que outro conceito podemos encontrar ? O de Professor.

Nome - Pedro Número - 231

Categoria - Adjunto
Departamento - DSI

A classe Professor tem os seguintes atributos


• Nome
• Numero de Identificação Fiscal
• Departamento
• Ordenado
• Categoria

Relembrando a classe Aluno :

A classe Aluno tem os seguintes atributos


• Nome
• Numero
• Ano
• Turma
• Curso
• Valor da Propina
• ValoPago de Propina

Podem verificar que as duas classes possuem atributos com a mesma designação. Isto acontece porque para
caracterizar tanto o aluno como o professor precisamos de em ambos definir o atributo nome, por exemplo.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 24


Sebenta da Disciplina de Introdução à Programação

Aluno Professor
Nome Nome
Numero Numero de Identificação
Ano Fiscal
Turma Departamento
Curso Ordenado
Valor da Propina Categoria
ValoPago de Propina

Nota : Classes diferentes podem ter atributos com o mesmo nome.

2.2 - Exercícios
Grupo I
1. Uma classe e um objecto são a mesma coisa? Se não são, então qual (ou quais) as diferenças e relações
entre estes dois conceitos?
2. No seu ponto de vista o que são atributos, métodos e mensagens?

Grupo II
1. Pretende-se desenvolver uma aplicação para gestão de um empresa de aluguer de automóveis. Deverá ser
possível consultar todos os automóveis existentes na empresa e verficar se um determinado está disponível
ou não para aluguer. Quando um automóvel é alugado, o sistema regista este automóvel como ficando
indisponível.
a. Quais as classes que a aplicação deve conter?
b. Identifique os atributos de cada classe
c. Identifique os métodos que cada uma das classes deve ter.

2. Pretende-se desenvolver uma aplicação para desenho. A aplicação permite definir pontos cartesianos e
linhas que se definem dando dois pontos.
a. Quais as classes que a aplicação deve conter?
b. Identifique os atributos de cada classe
c. Identifique os métodos que cada uma das classes deve ter.

3. Pretende-se desenvolver uma aplicação para gestão de uma biblioteca. A aplicação permite consultar os
livros que existem na biblioteca, assim como fazer reserva de livros. Para cada livro, a aplicação guarda a
seguinte informação : Autor, titulo, editora. Um utilizador para fazer a reserva de um livro tem que dar os
seguintes dados: nome , numero do BI e morada.
a. Quais as classes que a aplicação deve conter?
b. Identifique os atributos de cada classe
c. Identifique os métodos que cada uma das classes deve ter.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 25


Sebenta da Disciplina de Introdução à Programação

4. Pretende-se desenvolver uma aplicação para jogar o totoloto. A aplicação deve permitir preencher um
boletim realizar o sorteio da chave premiada e realizar a selecção dos boletins premiados.
a. Quais as classes que a aplicação deve conter?
b. Identifique os atributos de cada classe
c. Identifique os métodos que cada uma das classes deve ter.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 26


Sebenta da Disciplina de Introdução à Programação

3- Conceitos básicos de programação em Java

3.1 - Identificadores
Os identificadores são nomes atribuídos aos diferentes elementos de um programa (classes, objectos, métodos,
variáveis, constantes e outras entidades que este manipula), os quais em java seguem as seguintes regras:

Devem ser iniciados por uma letra, underscore (_) ou cifrão ($)
Podem ter outros caracteres (letras, dígitos, underscore ou cifrão)
Não podem conter espaços!

Contrariamente ao que acontece noutras linguagens, o Java distingue entre maiúsculas e minúsculas, ou seja:

A ≠ a
B ≠ b
public static void ≠ PUBLIC STATIC VOID

Ainda que as convenções não sejam obrigatórias e o compilador não verifique se são cumpridas, é aconselhável a
sua utilização, pois facilitam a compreensão dos programas por programadores a elas habituados. Também para o
Java é comum usar convenções para os identificadores a criar quando se desenvolve um programa:

• Os nomes das classes começam por letras maiúsculas (ex: Aluno)


• Qualquer outro nome começa por letras minúsculas, por exemplo o de um método (ex: main())
• As palavras seguintes à primeira, começam com maiúscula (ex: disciplinaDoCurso)
• Os identificadores devem sugerir o seu valor semântico, isto é, devem ter nomes sugestivos de acordo com o
propósito a que se destinam.

Exemplo

Quais dos seguintes identificadores são válidos em Java e quais não são?

1_x inválido, começa por dígito


X1 válido
M&M inválido, carácter & é ilegal
int inválido, é uma palavra reservada
$dólar inválido, carácter acentuado no nome
limite Inf inválido, espaço em branco

3.2 - Palavras Reservadas


Os identificadores podem ser escolhidos pelos programadores (ex: numeroDoAluno). No entanto, também se podem
utilizar identificadores previamente definidos na linguagem, designados por palavras reservadas. Estas são palavras
utilizadas na definição da linguagem e que têm um significado próprio nesse contexto. A sua semântica não pode ser
alterada pelo programador.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 27


Sebenta da Disciplina de Introdução à Programação

abstract boolean break byte byvalue


case cast catch char class
const continue default do double
else extends false final finally
float for future generic goto
if implements import inner instanceof
int interface long native new
null operator outer package private
protected public rest return short
static super switch synchronized this
Throw throws transient true try
var void volatile while
*

Figura 9. Lista das principais palavras reservadas existentes na linguagem Java

3.3 - Símbolos e Valores


Os Símbolos definidos em Java incluem diversos:

Operadores: +, -, * e =
Sinais de pontuação: {, }, (, ) e ;

Tal como as palavras reservadas, os símbolos têm um significado bem definido e não podem ser utilizados para outro
fim.

Os Valores são dados explícitos que podem ser manipulados pelo programa, isto é são todos os valores aceites pela
linguagem.

Por exemplo:

Número inteiros: 65 e -301


Números reais: 3.14159, -0.02 e 5.88f
Os caracteres: ‘a’, ‘A’ e ‘\n’
Cadeias de caracteres: “Bom dia!”

3.4 - Variáveis
Uma variável é uma localização em memória na qual podemos guardar um valor de um dado tipo. A cada variável
estão associados um tipo e um nome.

O valor de uma variável pode variar durante a execução do programa. No entanto, em cada momento uma variável
pode apenas conter um valor. Como podemos verificar na figura seguinte, o armazenamento de um novo valor numa
variável destrói o valor anterior dessa mesma variável.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 28


Sebenta da Disciplina de Introdução à Programação

char turma = ‘A’ turma = ‘E’


turma -> endereço de memória 1002 turma -> endereço de memória 1002

A E
Célula de Célula de
memória memória
1002 1002

Figura 10. Representação gráfica do conceito de variável

3.4.1 - Variáveis de Instância: Atributos

Como vimos em 3.1 os atributos definem as características das futuras instâncias de uma classe. Têm um nome único
dentro da mesma classe. Para referenciar um atributo de um objecto devemos indicar o nome do objecto e o nome do
atributo. Classes diferentes podem ter atributos com o mesmo nome.

Mais concretamente os atributos são variáveis que guardam os valores que caracterizam os objectos. Mas para cada
característica teremos que indicar qual o tipo de dados a que pertence.

Ao definir uma classe em Java que represente as características de um aluno teremos os seguintes atributos:

int numero;
String nome;
int ano;
String curso;
char turma;
double valorPropina;
double valorPago;

Para podermos definir atributos em Java precisamos de dominar os seguintes conceitos:


• Como declarar uma variável.
• Tipos de dados que uma variável pode ter.
• O que significam as palavras reservadas (char, int, double, String).

3.5 - Tipos de Dados


Em Java temos dois grupos de tipos de dados:

Tipos de Dados Primitivos: são utilizados para guardar números, caracteres e valores booleanos. Armazenam
directamente os valores.

Tipos de Dados Referenciados: não guardam os dados directamente, mas são utilizados para guardar os endereços
de memória onde se encontram estes dados.
Exemplo:

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 29


Sebenta da Disciplina de Introdução à Programação

int numero = 2133;


// a variável numero é do tipo primitivo

String nome = new String (”Pedro”);


// a variável nome é uma referencia

memória
numero 2133 20A20
nome 40B40 30A40

referência
“Pedro” 40B40

Figura 11.
Figura 12.Representação gráfica da possível localização em memória das variáveis declaradas nos dois
exemplos anteriores

• A variável número guarda o valor 2133.


• A variável nome guarda o valor 40B40. Este valor representa a zona de memória onde está guardada a
cadeia de caracteres “Pedro”. Por isso diz-se que a variável nome é uma referência.

Um tipo de dados é definido pela gama de valores que pode representar e pelas operações que sobre eles se
podem efectuar.

3.5.1 - Tipos de Dados Primitivos

Por agora vamo-nos focar apenas nos tipos de dados primitivos. A linguagem Java coloca oito tipos de dados
primitivos à nossa disposição:

• Quatro representam inteiros: byte, short, int, long


• Dois representam números Reais: float, double
• Um representa caracteres: char
• Um representa valores Lógicos : boolean

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 30


Sebenta da Disciplina de Introdução à Programação

3.5.1.1 - Inteiros
Tipo Tama-
Inteiro nho Menor Valor Maior Valor
byte 1 byte −128 127
(8 bits)
short 2 bytes −32,768 32,767
(16 bits)
int 4 bytes −2,147,483,648 2,147,483,647
(32 bits)
long 8 bytes −9,223,372,036,854,775,808 9,223,372,036,854,775,807
(64 bits)

Figura 13. Diferentes tipos de inteiros oferecidos pela linguagem Java. Nesta tabela podemos ver o espaço ocupado
por uma
Figura 14. variável de cada um destes tipos, bem como o maior e menor valor que essa variável pode ter.

Como exemplos de valores típicos a guardar em variáveis de cada um dos tipos inteiro podem ser apresentados:

byte: 40
short: -22 500
int: 1 500 000
long: 4 000 000 000

3.5.1.2 - Reais
Um número real pode ser representado usando a notação decimal, tem um ponto decimal ou a notação exponencial,
tem um expoente (E) Ex: 5.0, 12.34, 0.0, -45.8, 12. , 5.6E27

Tipo Tamanho
float 4 bytes (32 bits)
double 8 bytes (64 bits)

Figura 15. Tipos de dados reais existentes em Java

Tipo Menor Valor Maior Valor


float 1.40129846432481707e-45 3.40282346638528860e+38
double 4.94065645841246544e-324 1.79769313486231570e+308

Figura 16. Maior e menor valor representáveis pelos diferentes tipos de dados reais do Java

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 31


Sebenta da Disciplina de Introdução à Programação

3.5.1.3 - Caracteres
O armazenamento de caracteres em Java é conseguido pelo tipo char. Na realidade, as variáveis do tipo char
armazenam números que identificam os caracteres de acordo com um código denominado UNICODE. Este código é
um standard internacional de representação de caracteres que contém símbolos e caracteres dos alfabetos ocidentais
e orientais.

Os valores do tipo char são delimitados por plicas( ' ):

Exemplos:
// 'a' 'X' '7' '$' ',' '\n'
// são valores do tipo char

char letra = 'a‘;

3.5.1.4 - Lógico
O armazenamento de valores lógicos em Java é conseguido pelo tipo boolean, que, evidentemente, apenas pode
assumir um de dois valores: verdadeiro, ou falso.

As palavras reservadas true e false são os únicos valores válidos para um tipo Lógico

Exemplo:

boolean terminado = false;

3.5.1.5 - Declaração, Inicialização e Utilização


Quando trabalhamos com uma variável destinguimos 3 etapas:
1. Declaração
2. Inicialização
3. Utilização

Para usar uma variável é necessário fazer a sua declaração previamente, isto é, a especificação do seu nome
(identificador) e da gama de valores que pode conter (tipo de dados). A declaração é terminada com um ponto e
vírgula (;). Este é o símbolo que se usa em Java para indicar o final de qualquer declaração ou instrução.

tipo de dado identificador da variável

char turma

Figura 17. Esquema representativo da declaração de variáveis

A declaração reserva um espaço em memória necessário para guardar o tipo de valor

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 32


Sebenta da Disciplina de Introdução à Programação

A inicialização consiste na atribuição de um valor a uma variável:


numero = 2133;
turma = ‘A’;

Não estamos a falar de um valor qualquer, mas sim do valor inicial da variável, que é guardado no espaço
reservado.

Podemos, no entanto, declarar e inicializar uma variável na mesma expressão.

Exemplo:

int sum = 0;
int base = 32, max = 149;

É de notar que a declaração de uma variável apenas provoca a reserva de espaço de memória necessário e a sua
identificação pelo nome declarado e não define um valor. É na inicialização que a variável fica com um valor definido,
podendo a partir de agora ser utilizada.

Quando uma variável é referenciada num programa, é utilizado o valor actual (ver código abaixo).

int numero, resultado; // declaração

numero = 213; //inicialização

resultado = numero + 100; //utilização do número


// e inicialização do resultado

3.5.2 - Tipos de Dados Referenciados


As classes são novos tipos de dados, no sentido que definam a possível gama de valores e operações que podem ser
efectuadas com estes valores.
Assim os tipos de dados referenciados são classes (e arrays, que estudamos mais tarde).
Para declarar uma variável do tipo referenciado deve se indicar o nome da variável e o nome da classe.

String nome;
// a variável nome é uma referencia do tipo String

Definição:A variável do tipo referenciado é chamada referência.

Uma referência é uma variável que guarda o endereço do local onde se encontra um objecto de uma dada classe.
Para atribuir valor a uma referencia, na maioria dos casos, deve ser executado o comando new seguido de nome da
classe utilizada na declaração dessa variável. (este comando será explicado em 3.7.1 - )

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 33


Sebenta da Disciplina de Introdução à Programação

String nome;
nome = new String(“Pedro”);

O Java tem um conjunto de classes já elaboradas que permite aceder a um conjunto de funcionalidades e
propriedades já definidas. Uma destas classes é a classe String que já foi referida aquando da definição dos atributos
nome e curso da classe Aluno.

É uma classe bastante utilizada e que serve para manipular cadeias de caracteres.

Quando é declarada uma variável do tipo String ( String nome) é reservado um espaço em memória para guardar um
endereço da futura cadeia de caracteres. Enquanto essa variével não está inicializada, o valor da variável nome é
NULL ( isto é a referência não tem valor) . A inicialização pode ser efectuada pela instrução: nome = “Rita”;

Cada instância da classe String é uma cadeia de caracteres.

Uma String serve para guardar valores constantes, isto é, uma vez que seja atribuido um valor a uma String
este não pode ser alterado. Assim, qualquer operação sobre uma String devolve uma nova String (String
modificada)

String frase = “Introdução à Programação”;


String nome = “Rita”;
nome = “Pedro”;

frase
“Introdução à Programação”

nome
“Rita”

“Pedro”

Para além de referenciar os objectos das classes já existentes em Java, pode-se referenciar também os objectos de
classes por nós criadas, como veremos mais à frente.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 34


Sebenta da Disciplina de Introdução à Programação

3.6 - Operadores e Expressões


3.6.1 - Operadores de Atribuição
Por vezes é necessário efectuar uma operação sobre uma variável, e em seguida armazenar-se o valor obtido nessa
mesma variável. Os operadores de atribuição Java simplificam essas operações.

A instrução num += conta;


é equivalente a num = num + conta;

Operador Exemplo Equivalente a

+= x += y x=x+y
-= x -= y x=x-y
*= x *= y x=x*y
/= x /= y x=x/y
%= x %= y x=x%y

Figura 18. Diferentes representações para os operadores de atribuição

Ao símbolo = chama-se operador de atribuição. A instrução de atribuição permite armazenar um valor numa variável.

A expressão da direita é calculada em primeiro lugar, sendo o resultado armazenado na variável da esquerda. Neste
contexto, o sinal = deve ler-se “toma o valor de”.

Só pode ser atribuído um valor a uma variável que seja consistente com o tipo de dados declarado para essa variável.

A mesma variável, pode estar no lado esquerdo e direito da instrução de atribuição. Considere-se o exemplo:

int conta ;
conta = 25; conta Å 25
sum = conta; sum Å 25
conta = sum + 15; conta Å 40
conta = conta + 1; conta Å 41

3.6.2 - Operadores Aritméticos


Operadores que podem ser utilizados sobre valores de tipo inteiro:

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 35


Sebenta da Disciplina de Introdução à Programação

Operação Símbolo Exemplo Resultado


Adição + 26 + 10 36
Subtracção - 26 - 1 25
Multiplicação * 26 * 10 260
Divisão / 26 / 10 2
Módulo % 26 % 10 6
(resto)

Figura 19. Conjunto de operações que podem ser efectuadas sobre valores do tipo inteiro

A precedência de operadores determina a ordem de execução das operações. Por exemplo considere-se a
instrução: System.out.println(30 + 10 / 2);

As interpretações possíveis são:

30 + 10 e 10
= 20 30 + = 35
2 2

errado! correcto!

Grau de Operação
Precedência
Alto ()
Médio -, + (unários)
*, /, %
Baixo +, -

Figura 20.
Figura 21. Interpretações possíveis da ordem dos operadores e tabela com as regras de precedência correctas

. Operadores que podem ser utilizados sobre valores de tipo inteiro:

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 36


Sebenta da Disciplina de Introdução à Programação

Operação Símbolo Exemplo Resultado

Adição + 5.4 + 2.0 7.4


Subtracção - 5.4 - 2.0 3.4
Multiplicação * 5.4 * 2.0 10.8
Divisão / 5.4 / 2.0 2.7

Figura 22. Operações possíveis sobre reais

Grau de Operação
Precedência
Alto ()
Médio -, + (unários)
*, /
Baixo +, -

Figura 23. Precedências dos operadores sobre números reais


Figura 24.

3.6.3 - Operadores Lógicos


As expressões lógicas podem utilizar os seguintes operadores lógicos:

! NOT
&& AND
|| OR

Operam sobre operandos lógicos e produzem resultados lógicos.

O NOT é um operador unário (tem apenas um operando), enquanto que o AND e o OR são operadores binários (têm
dois operandos)

A b a && b a || b a ! a
true true true true true false
true false false true true false
false true false true false true
false false false false false true
Figura 25.
Figura 26. Tabelas de verdade dos operadores &&, || e !
Figura 27.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 37


Sebenta da Disciplina de Introdução à Programação

3.6.4 - Operadores Relacionais


Relacionam duas expressões de um mesmo tipo de dados e retornam um valor de tipo boolean:

Operador Designação
> Maior que
>= Maior ou igual a
< Menor que
<= Menor ou igual a
== Igual a
!= Diferente de

3.6.5 - Expressões
Uma expressão é uma sequência de operadores e de valores. As expressões podem ser calculadas, obtendo-se um
novo valor.

Podemos ter:

Expressões Aritméticas – envolvem operadores aritméticos

5 * ( 2 + 3 ) + ( 7 – 3 ) / 2 Resultado: 27

As expressões aritméticas são calculadas levando em conta a prioridade dos diferentes operadores envolvidos

Expressões Lógicas – têm como resultado um valor lógico e são construídas com operadores relacionais e
operadores lógicos

Exemplos:

Exemplo1: Determine o valor das seguintes expressões, indicando também o tipo do valor obtido

Expressão Resultado
3-4*2+1 -4 int
2*(12%5)-(8-3)/2 2 int
2*12%5-8-3/2 -5 int
2.5+6%4*2.1 6.7 double
2*((20/6)+(3*(2-1.5)))% (2.5+1-1.5) 1.0 double

Exemplo 2: Determine o resultado das seguintes expressões ou instruções

Expressão Resultado
3+5/2) >= (1-4%2) true
x=3 == 4; x fica false
8-1 != 3 + 4 false
‘a’ < ‘b’ || ‘c’ < ‘a’ true
(!a && b)|| (a || !b) true para a=true e b=false

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 38


Sebenta da Disciplina de Introdução à Programação

3.7 - Métodos

Definem funcionalidade das futuras instâncias de uma classe. São normalmente descritos recorrendo a verbos, por
indicarem algum tipo de acção e permitem modificar ou interrogar os objectos relativamente ao seu estado actual.

Um método tem sempre uma assinatura, a qual é constituída por:


• Tipo de retorno
• Nome
• Número e tipo de parâmetros

O formato geral de um método é o seguinte:

tipoRetorno nomeMetodo(listaParametros)
{
declaracoes;
instruções;
return (se for o caso);
}

Nota:

Por convenção, em Java, os nomes de classes começam por letras maiúsculas (ex: NomeClasse), ao passo que os
nomes de objectos começam com minúsculas (ex: nomeObjecto).
Os nomes dos métodos começam também por minúsculas (ex: nomeMetodo).

Os parâmetros são os dados de entrada . O objecto para executar uma determinada operação pode precisar de
dados. Essa informação é passada através dos parâmetros.

Exemplo:
• O aluno para pagar uma prestação da propina precisa de indicar o valor que vai pagar.
• O aluno para mudar de turma precisa de indicar qual a nova turma.

Parâmetros

São variáveis que referenciam diferentes tipos de dados dos quais o método necessita para levar a cabo a sua tarefa.

Através da instrução return é determinada qual o valor que o método devolve

return <expressão>;

Nota :

Dois métodos têm a mesma assinatura quando o nome, o valor de retorno e a lista de parametros são idênticos em
ambos. Não é possível na mesma classe a existência de métodos com a mesma assinatura.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 39


Sebenta da Disciplina de Introdução à Programação

3.7.1 - Método construtor sem argumentos


Uma das partes mais importantes da programação orientada por objectos é saber utilizar correctamente os
construtores de objectos.

O construtor é um método especial utilizado apenas na criação e inicialização de objectos de uma determinada classe.
O seu único e exclusivo objectivo é inicializar os atributos, ou seja, dar um estado inicial ao objecto.

Regras na construção de um construtor:

• É sempre de acesso publico.


• Tem o mesmo nome da classe.
• Não possui retorno.

Podem existir construtores com parâmetros e construtores sem parâmetros. Neste sub-capítulo apenas nos vamos
debruçar sobre os construtores sem parâmetros.

Vejamos o seguinte exemplo:

class Relogio
{
private int hora, segundo, minutos;

De acordo com as regras de criação de um construtor:

class Relogio
{
private int hora, segundo, minutos;

public Relógio()
{
hora = 24;
minutos = 0;
segundo = 0;

}
}

Quando não se define nenhum construtor na classe que especifica o objecto, a máquina virtual encarrega-se de criar
um em tempo de execução, equivalente a:

<nome da classe>()
{
//…….
}

Este construtor inicializa os atributos do objecto com valores default, que correspondem a:
• 0 se o atributo for de tipo numérico (short, byte, int, long, double,float, char)
• false se o atributo for de tipo boolean

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 40


Sebenta da Disciplina de Introdução à Programação

• null para referências

Nota: null representa uma referência nula, não existente, para um objecto pertencente a uma qualquer classe.

Instanciação é o processo de criar instâncias (objectos) de uma determinada classe. É uma operação feita sobre a
classe e não sobre os objectos (dado que os objectos já são instâncias não faz sentido criar instâncias a partir deles).

Para criar uma instância de uma classe utilizamos o operador new, que quando é executado aloca a memória
necessária para guardar o objecto em causa na memória.

new <nome da classe> (<lista de parâmetros actuais>);

Para o exemplo anterior da classe Relogio teriamos:

Relogio rel = new Relogio( );

Relogio despertador = new Relogio ( );

Teríamos um objecto denominado rel e outro denominado despertador, caracterizados por três atributos: hora,
minuto e segundo, cujos valores respectivamente são, 24, 0 e 0.
Poderão estes dois objectos existir ao mesmo tempo ? SIM!!!

3.7.2 - Invocação de métodos e passagem de parâmetros


A invocação de um método deve obedecer à seguinte regra:

nome_objecto.nome_método(<lista de Parâmetros>)

Vejamos um exemplo:
class Teste
{
public void metodoOla ()
{
System.out.println(“ola”);
}
}

class Programa
{
public static void main(String args[])
{
Teste obj = new Teste();
obj.metodoOla();//invocação do método

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 41


Sebenta da Disciplina de Introdução à Programação

Como foi possível ver o objecto obj invocou um método da sua classe. Será possível um objecto invocar um método
de outra classe ? Veja-se o próximo exemplo:

public class PrimeiraClasse


{

public PrimeiraClasse()
{
System.out.println("Sou o construtor por default da
PrimeiraClasse");
}

public void metodoPrimeiraClasse()


{
System.out.println("Sou o metodoPrimeiraClasse");
}
}
public class SegundaClasse
{

public SegundaClasse()
{
System.out.println("Sou o construtor por default da
SegundaClasse");
}
public void metodoSegundaClasse()
{
System.out.println("Sou o metodoSegundaClasse");
}
}

public class Principal


{
public static void main(String[] args)
{

SegundaClasse segunda = new SegundaClasse();

segunda.metodoPrimeiraClasse();

segunda.metodoSegundaClasse();

}
}

Ao analisarmos o código verificamos que a instrução segunda.metodoPrimeiraClasse( ) não está correcta. Porquê?
Porque o método metodoPrimeiraClasse() não faz parte da classe SegundaClasse.

Importante: Todo o objecto só pode invocar métodos da sua classe, tal como podemos ver no exemplo seguinte:

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 42


Sebenta da Disciplina de Introdução à Programação

Passar parâmetros a um método significa chamar esse método dando-lhe como entrada os dados que ele necessita.
Estes dados são chamados parâmetros actuais. Na chamada é efectuada a ligação entre parâmetros formais
(definidos no cabeçalho do método) e parâmetros actuais. A lista de parâmetros formais e actuais deve ter
correspondência. Cada parâmetro de lista de parâmetros actuais deve corresponder, pelo tipo e pela sua posição na
lista, a um parâmetro formal definido no cabeçalho do método.

Em Java, a passagem de parâmetros é sempre feita por valor.

Consideremos o seguinte código:

class Teste
{
public void passagem ( int var)
{
var = var * 2 ;
}
}

class Programa
{
public static void main(String args[])
{
int variavel = 7;
Teste obj = new Teste();
obj.passagem(variavel);
System.out.println(variavel);

}
}

O código apresentado ilusta a invocação de um método por parte de um objecto da classe Teste e a passagem de
parâmetros por valor. O parametro formal é var e parametro actual é variável.

No quadro seguinte podemos seguir o conteúdo das variáveis definidas no programa anterior :

Variáveis
Linha de código
variavel var
int variável = 7; 7 ---------
Obj.passagem(variavel); 7 7
var = var * 2 ; --------- 14
System.out.println(variável); 7 ---------

No exemplo acima as variáveis que estavam envolvidas na passagem de parâmetros (variável e var) eram
variáveis do tipo primitivo int. Na passagem de tipos referenciados, quando se está a lidar com variáveis do tipo
referenciado, o comportamento é diferente. Este ponto será explicado detalhadamente no capitulo 4 – Tópicos
Avançados de POO.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 43


Sebenta da Disciplina de Introdução à Programação

Para terminarmos este capítulo, iremos ver o retorno dos métodos. No início do capítulo foi dito que através da
instrução return é determinada qual o valor que o método devolve.
tipoRetorno nomeMetodo(listaParametros)
{
declaracoes;
instruções;
return (se for o caso);
}

Se o método não devolve valor, a instrução return não é especificada e no cabeçalho do método no lugar do
tipoRetorno deve se indicar void.

Vejamos o próximo exemplo:

class Calculo
{

public int somaValores()


{
int valorA = 10, valorB = 2;
int resultado = valorA+valorB;
return resultado;
}
}

class Programa
{
public static void main(String args[])
{

Calculo resultado = new Calculo();

int valorRetornado = resultado.somaValores();


System.out.println(valorRetornado);
}
}

O método somaValores é um método que retorna o valor que foi atribuído à variável resultado. Ao analisarmos o
método main podemos ver a seguinte instrução

valorRetornado = resultado.somaValores();

Que valor guardará a variável valorRetornado ? 12

Reparem que tipo da variável valorRetornado é igual ao tipo da variável resultado. Isto é muito importante, pois
devemos sempre garantir a correspondência dos tipos.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 44


Sebenta da Disciplina de Introdução à Programação

O seguinte exemplo é idêntico ao anterior, mas com passagem de parâmetros:

class Calculo
{

public int somaValores(int valorA, int valorB)


{
int resultado = valorA+valorB;
return resultado;
}
}

class Programa
{
public static void main(String args[])
{
Calculo resultado = new Calculo();

int valorRetornado = resultado.somaValores(2,5);


System.out.println(valorRetornado);

int x = 10, y = 5;
valorRetornado = resultado.somaValores(x,y);
System.out.println(valorRetornado);

}
}

• Da primeira vez que a variável valorRetornado guarda o valor retornado, qual o seu valor ? 7

• Da segunda vez que a variável valorRetornado guarda o valor retornado, qual o seu valor ? 15

• E qual será o valor de x depois de ser utilizado como parâmetro ? 10.

3.7.3 - Métodos construtores com argumentos


É possível agora avançar para a criação de objectos utilizando construtores com uma lista de parâmetros.

No exemplo da classe aluno podemos encontrar um:

public Aluno(String nom, int num, String curs, int an, char turm)
{…}

Seguindo a regra de criação de objectos teremos então:

Aluno aluno1 = new Aluno(“Pedro”, 2134,”EI”, 1, ‘A’);


// A variável aluno1 é uma referência a um objecto.
// A variável, na verdade, serve como apontador para o
// endereço de memória que o objecto irá ocupar.

Aluno aluno2 = new Aluno(“João”, 2133,”EI”, 1, ‘A’);

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 45


Sebenta da Disciplina de Introdução à Programação

Aluno aluno3 = new Aluno(“Ana”, 2131,”EI”, 1, ‘A’);

Aluno aluno5 = new Aluno(“Rita”, 2137,”EM”, 1, ‘A’);

Em seguida para consolidar os conhecimentos até aqui adquiridos, será apresentado o código da classe Aluno
referente à definição de atributos e definição do construtor:

public class Aluno

{
//ATRIBUTOS
private String nome;
private int numero;
private int ano;
private String curso;
private char turma;
private double valorPropina;
private double valorPago;

//CONSTRUTORES
public Aluno(String nom, int num, String curs, int an, char turm)
{
nome = nom;
numero = num;
ano = an;
curso =curs;
turma = turm;
valorPropina = 0;
valorPago=0;
}
}

A criação de objectos neste exemplo, será criada numa outra classe, na qual está definido o main:

class Programa
{
public static void main(String args[])
{
Aluno aluno2 = new Aluno(“João”, 2133,”EI”, 1, ‘A’);
Aluno aluno3 = new Aluno(“Ana”, 2131,”EI”, 1, ‘A’);
...
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 46


Sebenta da Disciplina de Introdução à Programação

No método construtor da classe Aluno, encontramos as seguintes instruções:

valorPropina=0;
valorPago=0;

No caso das variáveis valorPropina e ValorPago o valor é fornecido directamente. Contudo o valor atribuído pode
resultar do cálculo de uma expressão, tal como:

class Programa
{
public static void main(String args[])
{
int ano = 2005;
int anoNascimento = 1971
int idade = ano - anoNascimento

3.7.4 - Métodos selectores

Os métodos selectores são aqueles que devolvem o valor de um atributo da classe.

public int getNumero()


{
return numero;
}

O método getNumero( )
• devolve o valor da variável numero
• o nome do método é getNumero
• o tipo de retorno é do tipo inteiro (Como numero é uma variável do tipo inteiro o tipo de retorno também
é do tipo inteiro)

A seguir apresentam-se os restantes métodos selectores do nosso exemplo da classe Aluno


• getNome( ) – devolve o nome do aluno
• getCurso ( ) – devolve o curso em que o aluno esta inscrito
• getTurma ( )– devolve a turma em que o aluno esta inscrito
• get Ano( ) – devolve o ano em que o aluno esta inscrito
• getPropina ()- devolve o valor da propina paga
• getValorPago( ) – devolve o valor já pago da propina

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 47


Sebenta da Disciplina de Introdução à Programação

public String getNome()


{
return nome;
}
public String getCurso()
{
return curso;
}
public int getAno()
{
return ano;
}
public char getTurma()
{
return turma;
}

public double getPropina()


{
return valorPropina;
}
public double getValorPago()
{
return valorPago;
}

Utilizando um objecto da classe Aluno

Aluno aluno2 = new Aluno(“João”, 2133,”EI”, 1, ‘A’);

• Como consultar o número deste aluno ?

Pode-se utilizar um método selector, reparem:

aluno2.getNumero( );

Estará correcto? Não. Trata-se de um método que devolve um valor, logo devemos recebe-lo de alguma forma.

int numero = aluno2.getNumero( );

3.7.5 - Métodos modificadores

Chamam-se métodos modificadores aqueles que servem para alterar/modificar o valor de um atributo.

public void setTurma(char novaTurma)


{
turma=turm;
}

O método void setTurma(char novaTurma)


• Modifica o valor do atributo turma, (quando um aluno muda de turma o valor tem que se alterar)

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 48


Sebenta da Disciplina de Introdução à Programação

• nome do método é setTurma


• o tipo de retorno é do tipo void –não retorna valor nenhum
• Recebe como parâmetro o valor para a nova turma, que é do tipo carácter (char)

public void setCurso(String novoCurso)


{
curso=novoCurso;
}
O método void setCurso(String novoCurso)
• Modifica o valor do atributo curso ( quando um aluno muda de curso o valor tem que se alterar)
• nome do método é setCurso
• o tipo de retorno é do tipo void –não retorna valor nenhum
• Recebe como parâmetro o valor para o novo curso, que é do tipo String

Exemplo, utilizando a classe aluno

Aluno aluno2 = new Aluno(“João”, 2133,”EI”, 1, ‘A’);

Classe Aluno Atributos


Objecto Nome Número Curso Turma
Aluno1 João 2134 EI A

aluno2.setCurso(“EA”);

Ao invocar o método modificador setCurso os atributos deste objecto ficaram:

Classe Aluno Atributos


Objecto Nome Número Curso Turma
Aluno1 João 2133 EA A

3.8 - Estrutura de Aplicações em JAVA


3.8.1 - Estrutura do programa principal
Regra geral, seja em Java seja noutras linguagens, uma aplicação informática é constituída por um programa principal
onde é iniciada a aplicação e quando é executadaa última linha do programa principal a aplicação termina.

Em Java, uma aplicação é constituída por uma ou mais classes. Uma (e só uma) dessas classes contém um método
chamado main que é o programa principal. Este utiliza então métodos que podem existir na mesma classe ou
noutras.

Existem três regras importantes na estruturação de um programa (livro FCA – Fundamentos de Programação em
Java2):

• Um programa contém:
o Declarações de variáveis;
o Um método principal chamado main();
o Um conjunto de métodos definidos pelo programador.
• Os métodos contêm:
o Declarações de variáveis;
o Instruções;

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 49


Sebenta da Disciplina de Introdução à Programação

o Chamadas a outros métodos (predefinidos ou criados pelo programador).

Os detalhes de implementação de um método são irrelevantes, desde que se saiba para que é que ele serve, que
parâmetros recebe e que tipo de resultado deve produzir (é como se fosse uma caixa negra!).

3.8.2 - Visibilidade das Variáveis


Visibilidade de uma variável é uma noção associada ao local onde a variável é declarada no programa.

Podemos então classificar as variáveis da seguinte forma:


• Variáveis locais
• Variáveis globais

Uma variável declarada dentro de um subprograma é chamada de variável local a esse subprograma. Uma variável
local é criada sempre que o subprograma é activado e destruída quando este termina a sua execução.
Ainda que haja outro subprograma que contenha uma variável declarada com o mesmo nome, estamos a falar de
variáveis diferentes, que existem em espaços de memória separados, por períodos de tempo diferentes e visibilidades
diferentes, pois existem em subprogramas distintos.

Uma variável global é aquela que é declarada no início do programa e subsiste até que o programa termine, sendo
visível dentro de qualquer subprograma que o constitui. Para além de serem visíveis dentro de qualquer subprograma
que constitui a aplicação, as variáveis globais podem também ser utilizadas por esses subprogramas.
Não é no entanto aconselhado o uso abusivo deste tipo de variáveis dadas as limitações que causam na legibilidade
do código e a facilidade com que provocam o aparecimento de erros difíceis de detectar.
Para além disso não contribuem em nada para a reutilização de código pois tornam o código desenvolvido
dependente do contexto de utilização.

class VisibilidadeVariaveis
{
private int valor1;

// variável global
public static int valor2 = 10;

public static void mudaValor2(int v2) {


// novoValor é uma variável local ao método
int novoValor = v2 + valor2;
valor2 = novoValor;
} ...

public static void main(String args[]) { // Resultado = 43!


System.out.println(“Valor2 antes da chamada = ” + valor2);
mudaValor2(33);
System.out.println(“Valor2 depois da chamada = ” + valor2);
}
}

3.8.3 - Entrada e Saída de Dados

A interacção da aplicação com o utilizador é efectuada através de entrada e saída de dados. Para pedirmos
informação ao utilizador temos que ser capazes de ler do teclado. Para mostrar informação ao utilizador temos que
ser capazes de escrever para o ecran.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 50


Sebenta da Disciplina de Introdução à Programação

class Programa
{
public static void main(String args[])
{
Aluno aluno2 = new Aluno(“João”, 2133,”EI”, 1, ‘A’);
Aluno aluno3 = new Aluno(“Ana”, 2131,”EI”, 1, ‘A’);

aluno3.setTurma(‘E’);
int i= aluno3.getNumero();
char t= aluno3.getTurma();

System.out.println(“Numero” + i);
System.out.println(“Turma” + t);

}
No exemplo de código apresentado, a variável i e a variável t são do tipo de dados primitivo.

Será que é possível escrever a seguinte instrução?

System.out.println(aluno3);

Sim, mas para essa instrução imprimir informação sobre o objecto aluno3, é necessário definir na classe Aluno o
método toString().

public String toString()


{
String str= "Nome:" + nome + "Numero :" + numero + " curso : "
+ curso +
" ano" + ano;
return str;
};

Voltando ao nosso exemplo do Aluno, para este exemplo ser interactivo, os dados sobre o aluno (nome, numero etc.)
devem ser pedidos ao utilizador. A entrada de dados para o programa é feita através da leitura de dados do teclado. .
A escrita de informação para o ecran designa-se por saída de dados.

Como já temos visto ao longo dos exemplos anteriores, quando queremos escrever para o ecran utilizamos a
instrução em Java
System.out.println( x); // Onde x é a variável que se pretende mostrar no ecran.

Nota: x pode ser uma variável de um tipo de dados primitivo, ou se x é de um tipo referenciado, então a classe que
instancia tem que ter definido o método toString().

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 51


Sebenta da Disciplina de Introdução à Programação

Voltando ao nosso exemplo da classe Aluno…

class Programa
{
public static void main(String args[])
{
Aluno aluno2 = new Aluno(“João”, 2133,”EI”, 1, ‘A’);
Aluno aluno3 = new Aluno(“Ana”, 2131,”EI”, 1, ‘A’);

aluno3.setTurma(‘E’);
int i= aluno3.getNumero();
System.out.println(aluno3);
}
}

A classe Scanner, introduzida com a versão J2SE 5.0, é uma classe que permite converter o texto para tipos
primitivos.
Para ler de forma confortável texto do canal de entrada padrão, é preciso criar primeiro um Scanner sobre canal
System.in que esta associado ao teclado
Scanner sc = new Scanner(System.in);
Para cada um dos tipos primitivos há um método correspondente com a assinatura nextXxx() que retorne um valor
desse tipo.

Exemplo

import java.util.*;

class ExScanner
{
public static void main(String[] args)throws InputMismatchException
{
Scanner scanTeclado = new Scanner(System.in);
System.out.println ("Introduza um inteiro");
int num = scanTeclado.nextInt();
System.out.println ("Numero introduzido:" + num);
}

Tipo de dados metodo


int nextInt()
char nextChar()
double nextDouble()
float nextFloat()
String next()

Exemplo com a classe Aluno

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 52


Sebenta da Disciplina de Introdução à Programação

class Programa
{
public static void main(String[] args)throws InputMismatchException
{
Scanner scanTeclado = new Scanner(System.in);
System.out.println ("Introduza o numero do Aluno ");
int num = scanTeclado.nextInt();
System.out.println ("Introduza o nome do Aluno ");
int nome = scanTeclado.next ();
System.out.println ("Introduza o curso do Aluno ");
int curso = scanTeclado.next ();
System.out.println ("Introduza o ano de inscrição");
int ano = scanTeclado.nextInt ();
System.out.println ("Introduza a turma de inscrição ");
char turma = scanTeclado.nextChar ();

Aluno aluno = new Aluno(nome, num,curso, ano, turma);


}
}

3.8.4 - Definição de Novas Classes


Para além de utilizar as classes pré-definidas pela linguagem, é normal que seja necessário definir novas classes que
nos ajudem a resolver os nossos problemas (aliás, é isso que temos vindo a fazer em muitos dos exemplos. A classe
Aluno, por exemplo, não faz parte da linguagem).

Sumariando os passos que tem sido dados para a construção da classe exemplificativa Aluno. Para se definir uma
classe deve obedecer-se à seguinte estrutura:

• Definir atributos (variáveis) de instância


• Definir construtores
• Definir métodos (métodos selectores, modificadores e outros)

public class <nome da classe>


{

//definição dos atributos de Instância


<tipo1> <atributo1>;
<tipo2> <atributo2>, <atributo3>;

// definição dos construtores


<construtores>
...
// definição dos métodos de instância
void <método1>(){...}
void <método2>(<parâmetros>){...}
<tipo> <método3>(){...}
<tipo> <método4>(<parâmetros>){...}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 53


Sebenta da Disciplina de Introdução à Programação

3.8.5 - Utilização de classes existentes em JAVA.

Como já foi referido anteriormente o Java tem um conjunto de classes já elaboradas que permite aceder a um
conjunto de funcionalidades e propriedades já definidas. Estas classes estão guardadas em pastas compactadas.
Para podermos utilizar num programa uma dessas classes é necessário importa-las.

A instrução em Java é:

import <nome_do_pacote.nome_da_classe>

Vamos como exemplos analisar as classes String, Math e Random .

3.8.5.1 - Classe String


A classe String que já foi utilizada para definir os atributos da classe Aluno, disponibiliza vários métodos para
manipular cadeias de caracteres. Dos quais destacamos os seguintes:

Método Descrição
String() Cria um objecto do tipo String
char charAt(int index) Devolve o caracter da posição index da string
int compareTo(String anotherString) Compara duas
Strings
int indexOf(String str) Determina a localização da primeira ocorrência de uma
cadeia de caracteres dentro de uma cadeia de
caracteres
String toUpperCase() Transforma em maiúsculas a cadeia de caracteres
int lenght() Retorna o comprimento da string

Nota: Para mais informações sobre os métodos disponibilizados pela String consultar a documentação do Java.

Exemplo de utilização dos métodos da classe String


Codigo resultado
String frase = “Hoje é quinta feira”; frase = “Hoje é quinta feira”;
int tamanho = frase.lenght(); tamanho=19
String palavra = frase.substring(0,4); palavra=“Hoje ”
String novaPalavra = frase.toLowerCase(0,4); novaPalavra=“hoje ”
char c = palavra.charAt(2); c=‘j’
boolean b = novaPalavra.equals(“Hoje”); b=false
int indice = frase.indexOf(“qui”); indice=7
String outraPalavra = frase.substring(indice,indice+7); outraPalavra=“quinta ”
String outra = outraPalavra.trim(); outra=“quinta”

A classe String pertence ao package java.lang , este package é importado automaticamente sem
necessidade de inclusão específica no programa.

3.8.5.2 - Classe Math


Uma classe das classes previamente elaboradas é a classe Math que inclui um vasto número de subprogramas que
implementam diversas funções matemáticas (ex: Math.sqrt() – calcula a raíz quadrada; Math.sin() – calcula o seno de
um ângulo; etc.)

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 54


Sebenta da Disciplina de Introdução à Programação

A classe Math pertence ao package java.lang , este package é importado automaticamente sem
necessidade de inclusão específica no programa.

Para utilizar classes de outros pacotes é necessário importar (import) explicitamente a classe.

Exemplo:
Calcular a potência de um número elevado a outro.

public class Calculo {


public static void main (String args[]){

int base=2, expoente=8;


int resultado;

resultado = Math.pow(base, expoente);

System.out.println(“O resultado é: ”+resultado);


}
}

3.8.5.3 - Classe Random


A classe Random é parte do package java.util (fornece métodos para gerar números aleatórios). Como não é uma
classe do package java.lang é necessário importar explicitamente:

import java.util.Random;

Quando é necessário utilizar uma classe de um package mas não queremos usar a directiva import, pode ser utilizado
o seu nome completo.

Alguns métodos da classe Random

Método Descrição
Random() Cria gerador de números aleatórios
int next(int bits) Gera o número aleatório seguinte
int nextInt() Retorna um número inteiro aleatório
int nextInt(int n) Retorna um número inteiro aleatório de um intervalo de 0 a n
double nextDouble() Retorna um número real aleatório, entre 0.0 e 1.0

public class Calculo {


public static void main (String args[]){

int base=2, expoente=8;


java.util.Random r = new java.util.Random();
int resultado = r.nextInt();

System.out.println(“O resultado é: ”+resultado);


}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 55


Sebenta da Disciplina de Introdução à Programação

A desvantagem é que o nome que temos a escrever se torna demasiado extenso, pelo que nem sempre compensa
utilizar esta abordagem.
A outra abordagem possível, consiste em utilizar de forma explícita a directiva import:

import java.util.Random;

public class Calculo {


public static void main (String args[]){

Random r = new Random();

int resultado = r.nextInt();

System.out.println(“O resultado é: ”+resultado);


}
}

3.8.6 - Comentários
Os comentários de um programa documentam as instruções existentes. Devem ser incluídos de forma explicar o
propósito do programa e descrever passos do processamento. Não influenciam o funcionamento do programa pois
são ignorados pelo compilador.

Os comentários em Java têm dois formatos:

// formato utilizado para comentários no final da linha

/* formato para comentários que se


estendem por mais de uma
linha
*/

3.8.7 - Paragrafação / Indentação


Caracteres de espaço, linhas em branco e tabulação são genericamente designados por espaços em branco. Os
espaços em branco são utilizados para separar identificadores e símbolos no programa. Todos os espaços em branco
adicionais são ignorados.

Um programa Java pode ser formatado de múltiplas formas. Deve ser utilizada a paragrafação, para assegurar a
legibilidade dos programas

Exemplo de um programa Java com paragrafação

package meuteste;

public class OlaMundo


{
public static void main(String[] args)
{
System.out.println("Olá Mundo!");
}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 56


Sebenta da Disciplina de Introdução à Programação

Exemplo de um programa Java sem paragrafação

package meuteste; public class OlaMundo { public static void


main(String[] args) { System.out.println("Olá Mundo!"); } }

O Compilador ignora a paragrafação e os fins de linha.

3.9 - Exercícios Práticos


Objectivos da Série:

Com esta série de problemas pretende-se que o aluno:


Conheça as bases da programação orientada pelos objectos
Saiba criar novas classes e instanciá-las

1. Relativamente à classe Aluno do exemplo deste capítulo implemente em Java as seguintes alterações
a. Defina dois novos atributos relacionados com as notas de entrada para a escola. Nota da prova
especifica de matemática e valor da média do 12º ano.
b. Defina um novo construtor para a classe aluno que também inicialize estes dois novos atributos
c. Implemente um método que retorne a media aritmética entre a nota da prova específica e a nota do 12º
ano
d. Implemente na classe programa a criação de um novo aluno com os seguintes dados

Objecto Nome Número Curso Turma Especifica 12º ano


de Mat
aluno6 Joana 2155 EM B 13.1 11.2

e. Implemente na classe programa a criação de um novo aluno com dados pedidos ao utilizador.
f. Implemente na classe programa a funcionalidade da mudança de turma. Deverá pedir ao utilizador a
nova turma. E no final imprimir os novos dados do aluno, através do uso implícito do método toString.

2. O resultado do exercício do capitulo 2 - grupo2-ex1, deverá ser implementado em Java.


a. Defina a classe com os atributos e métodos identificados.
b. Implemente a classe programa onde testa o construtor, os métodos selectores e modificadores.

3. Defina a classe Ponto representada por duas coordenadas.


a. Implemente o método construtor para inicializar o ponto.
b. Implemente os métodos para visualizar as coordenadas do Ponto
c. Implemente um método que faça uma translação vertical do ponto.
d. Implemente um método que faça uma translação horizontal do ponto.
e. Implemente um método que calcule o ponto médio linha.

4. O resultado do exercício capitulo 2 - grupo2-ex4, deverá ser implementado em Java.


a. Defina as classes com os atributos e métodos identificados.
b. Implemente a classe programa onde testa o construtor, os métodos selectores e modificadores
c. Implemente o método que gera os 6 números da chave do totoloto. Devera utilizar a classe Random.

5. Implemente a classe Moeda que tem como atributos o valor monetário da moeda e tipo deMoeda (ex, dólar,
euro, Franco suisso).
a. Implemente o método construtor
b. Implemente os métodos
i. Verificar se duas moedas são iguais.
ii. Adicionar moeda
c. Implemente a classe programa onde testa o construtor e os métodos anteriormente implementados..

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 57


Sebenta da Disciplina de Introdução à Programação

4- Instruções de Controlo
Até aqui, todos os exemplos de código que vimos seguiam uma estrutura a que se dá o nome de sequencial. Não
tinham nenhuma instrução que de alguma forma fizesse mudar o fluxo de execução da aplicação. Ou seja, as
instruções são executadas uma após a outra de acordo com a ordem por que aparecem. Esta filosofia limita em muito
a utilidade dos programas que se possam vir a produzir.
Resolver problemas mais complexos exige um maior poder de decisão sobre a forma como o programa é executado
(fluxo de execução), o que nos é possibilitado pelas instruções de controlo. O que estas trazem de novo é a
capacidade de controlar a execução de uma aplicação mediante o estabelecimento de condições lógicas.

Existem essencialmente dois tipos de instruções de controlo:

Selecção: permitem determinar o caminho a seguir de acordo com o valor de uma expressão;
Repetição: permitem controlar o número de vezes que um determinado bloco de instruções é executado (são os
chamados ciclos).

4.1 - Selecção
Ao implementar aplicações podemos ter que tomar decisões com base em valores de expressões, dados fornecidos
pelo utilizador, resultados calculados, etc.
Deste tipo de necessidades surgiram as instruções de selecção: para impôr a execução condicional de instruções.

A selecção de instruções pode ser:

Simples: Com base na condição a avaliar executa um bloco de instruções ou então não executa;
Em alternativa: Tem duas possibilidades de blocos de instruções a executar. Com base na condição, ou executa um
ou executa outro.
Múltipla: As possibilidades são várias e as condições a verificar também, o bloco a executar é escolhido com base na
condição cuja verificação tenha sido positiva.

Em Java as instruções de selecção são as seguintes:

if/else
switch - case

Com estas instruções podemos concretizar cada um dos três tipos de selecções acima mencionados.

4.1.1 - Selecção Simples: if


Um exemplo de uma selecção simples representado por um fluxograma pode ser o seguinte:

Verdadeiro
Expressão Instruções...

Falso

Fluxograma de uma instrução de selecção simples

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 58


Sebenta da Disciplina de Introdução à Programação

Começa por ser avaliada uma expressão lógica. Se o seu resultado for verdadeiro, então é executado um
determinado bloco de instruções. Caso contrário, a execução do programa prossegue sendo esse bloco ignorado.

Em Java, este tipo de selecção concretiza-se recorrendo à instrução if, cuja sintaxe é a seguinte:

if ( expressão ) instrução

Figura 28. Instrução de selecção if

Código exemplo para uma instrução if:

if (condição) {
instruções;
}

Exemplo 1:

public class TesteIdade


{
public static void main(String args[])
{
int idade = 14;
// Verificar se um individuo tem
// idade para conduzir
if (idade < 16)
System.out.println(“Muito novo para guiar”);
}
}

Exemplo 2:

// Programa que gera um número aleatório e informa se


// o número gerado é ou não negativo

import java.util.Random;

public class NumNeg


{
public static void main(String args[])
{
Random random = new Random();
int n = random.nextInt();
System.out.println(“n = ” + n);

if (n < 0)
System.out.println(“O número é negativo”);

System.out.println(“Adeus.”);
}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 59


Sebenta da Disciplina de Introdução à Programação

Exemplo 3:
Relativamente à classe Aluno, do exemplo que temos vindo a acompanhar, implemente um método que retorne falso
se o valor da propina é igual a zero.

public boolean verificaValorPropina()


{
if (valorPropina == 0)
return false;
}

4.1.2 - Selecção Em Alternativa: if-else


Muitas vezes interessa-nos que, quando a condição a verificar seja falsa, haja um conjunto alternativo de instruções a
executar. É a isto que se dá o nome de selecção em alternativa, que, em termos de fluxograma pode ser representada
da seguinte forma:

B - Instruções... Falso Verdadeiro A - Instruções...


Expressão

Figura 29. Fluxograma de uma instrução com selecção alternativa

Recapitulando: Se a expressão for verdadeira, é executado o conjunto de instruções A. Se for falsa, é executado em
alternativa o conjunto de instruções B. O programa segue depois com as instruções que tiver para executar a seguir.

Em termos de sintaxe Java, este tipo de selecção representa-se da seguinte forma:

if ( expressão ) instrução

else instrução

Figura 30. Instrução de selecção if-else

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 60


Sebenta da Disciplina de Introdução à Programação

Código exemplo de uma instrução if/else:

if (condição) { // as chavetas aparecem quando há mais que


// uma instrução a executar dentro do if ou
// do else. Passa a ser composto!
instruções;
}
else {
instruções;
}

Exemplo 1:

public class TesteNota


{
public static void main(String args[])
{
int Nota = 14;

// Resultado da avaliação
if (nota < 10)
System.out.println(“Nota negativa”);
else
System.out.println(“Nota positiva”);
}
}

Exemplo 2:

// Programa que gera dois números aleatórios


// e informa qual deles é o menor.
import java.util.Random;

public class Menor


{
public static void main(String args[])
{
Random random = new Random();
int m = random.nextInt();
System.out.println("m = " + m);
int n = random.nextInt();
System.out.println("n = " + n);
if (m < n) // o que acontece se m=n?
System.out.println(“O menor numero e " + m);
else
System.out.println("O menor numero e " + n);
}
}

As instruções if podem ser representadas em paralelo ou encadeadas, caso haja várias alternativas a estudar e a
representar.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 61


Sebenta da Disciplina de Introdução à Programação

Exemplo 3:
Relativamente à classe Aluno, implemente um método que retorne falso se o valor da propina é igual a zero e
verdadeiro se o valor for diferente de zero.

public boolean verificaValorPropina()


{
if (valorPropina == 0)
return false;
else
return true;
}

Exemplo 4:
// Determinar a ordem de grandeza
// dos três números (a, b, c) usando if’s encadeados.

a<b<c
sim
a<c<b
sim (b < c) ? sim c<a<b
não
(a < c) ?
(a < b) ? não b<a<c
b<c<a
sim
c<b<a
não (a < c) ? sim
não
(b < c) ?
não

// código:
if (a < b)
if (b < c)
System.out.println("a < b < c");
else
if (a < c)
System.out.println("a < c < b");
else
System.out.println("c < a < b");
else
if (a < c)
System.out.println("b < a < c");
else
if (b < c)
System.out.println("b < c < a");
else
System.out.println("c < b < a");

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 62


Sebenta da Disciplina de Introdução à Programação

// Determinar a ordem da grandeza


// dos três números (a, b, c) usando if’s paralelos.
a<b? b<c? a<b<c

a<c? c<b? a<c<b

b<a? a<c? b<a<c

b<c? c<a? b<c<a

c<a? a<b? c<a<b

c<b? b<a? c<b<a

// código:
if (a < b && b < c) System.out.println("a < b < c");
if (a < c && c < b) System.out.println("a < c < b");
if (b < a && a < c) System.out.println("b < a < c");
if (b < c && c < a) System.out.println("b < c < a");
if (c < a && a < b) System.out.println("c < a < b");
if (c < b && b < a) System.out.println("c < b < a");

Essencialmente, ao tomar a decisão de usar if’s de forma encadeada ou em paralelo estamos apenas a ter em
conta o facto de cada condição a verificar depender ou não das anteriores.

Em relação ao uso específico da alternativa else, há uma nota importante a fazer. Há casos em que o else pode,
em termos semânticos, tornar-se ambíguo, ou seja, ser susceptível de interpretações diferentes numa mesma
situação.

Exemplo 5:

if ( numeroAluno > 1200)


if (numeroAluno < 2000)
System.out.println("O aluno tem um numero entre 1201 e
1999");
else
System.out.println("O aluno tem um numero inferior ou igual
a 1200");

A que if pertence o else?

Da forma como está escrito o código, parece ser dado a entender que o else representa a alternativa à condição
numeroAluno > 1200....
Mas na realidade o código tem um erro de indentação e o else representa uma alternativa à condição
numeroAluno < 2000.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 63


Sebenta da Disciplina de Introdução à Programação

Não podem existir ambiguidades quanto ao caminho a seguir na execução de instruções. Se não tivesse sido
estipulada à partida uma regra para o Java operar nestes casos, o interpretador não saberia o que fazer quando lhe
surgisse um conjunto de instruções deste género.
Em Java, a semântica da instrução if/else dita que um else "pertence" sempre ao if que foi deixado em aberto
em último lugar. Ou seja, ao último if sem else.

Na situação anterior, para forçar a que o else estivesse associado ao primeiro if, teríamos de usar delimitadores:

if ( numeroAluno > 1200) {


if (numeroAluno < 2000)
System.out.println("O aluno tem um numero entre 1201 e
1999");
}
else
System.out.println("O aluno tem um numero inferior ou igual a
1200");

Neste caso, dizemos que o segundo if e a mensagem que este envia para o canal de saída (caso a condição seja
verdadeira), fazem parte do bloco de instruções a executar quando numeroAluno > 1200 tem o valor true.
Tornámo-las numa instrução composta.

Nota: Pode haver if’s sem else’s, mas o contrário não se aplica.

Exemplo 6:

// Se tem menos que 70 pontos, visualizar “Deve melhorar“


// Se tem mais que 95 pontos, visualizar “Trabalho
// excelente!“
// Se tem entre 70 e 95, não visualizar mensagem
// O código seguinte está certo ou errado?

public class Pontos


{
public static void main(String args[])
{
Scanner scanTeclado = new Scanner(System.in);
int pontos = scanTeclado.nextInt();
/* Sem as {} sabemos a que if pertence o
else? E é esse o resultado desejado? */
if (pontos >= 70)
if (pontos > 95)
System.out.println(" Trabalho excelente!");
else
System.out.println(" Deve melhorar ");
}
}

Aplicando a regra de que um else pertence ao último if deixado em aberto, o else pertence ao if onde se
verifica se pontos > 95!

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 64


Sebenta da Disciplina de Introdução à Programação

Em termos sintácticos seria assim que a máquina virtual Java iria interpretar, pois não há margem para ambiguidades.
A máquina tem de saber sempre qual é a próxima instrução a executar.
Em termos semânticos, claramente teríamos aqui um erro de interpretação do problema e os resultados não seriam os
pedidos pelo enunciado.

4.1.3 - Selecção Múltipla: switch - case


Nos tipos de instruções de selecção descritos anteriormente verificámos que é possível utilizar diferentes formas da
instrução if para seleccionar a alternativa que mais nos convém.
No entanto, se a decisão a tomar tiver que ser feita com base num valor inteiro ou numa letra ao invés de um valor
lógico, então a estrutura de selecção múltipla que vamos apresentar torna-se mais eficaz.

Em termos de fluxograma pode ser representada da seguinte forma:

V1 V2 ... Vn outro
Expressão

I1 I2 In Id

Figura 31. Fluxograma de uma instrução de selecção múltipla

Começa por calcular o valor da expressão que tem de ter um resultado de tipo inteiro ou caracter. Depois, compara o
valor da expressão com os valores v1 a vn. Se for igual ao de algum deles, executa o bloco de instruções
correspondente.

Se o valor da expressão a executar não for igual a nenhum dos valores v1... vn, pode suceder uma de duas situações:
não há mais nenhuma alternativa a considerar e portanto nenhum bloco de instruções a executar;
há uma alternativa pronta a ser executada quando mais nenhuma serve e é essa a escolhida (no fluxograma está
representada pelo valor outro).

Em Java, a instrução que se usa para representar situações de selecção múltipla é a instrução switch. A instrução
switch é também uma instrução de selecção que, com base na avaliação de uma variável ou expressão de valor
inteiro (ou caracter) escolhe, entre várias alternativas possíveis, uma instrução ou conjunto de instruções a executar.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 65


Sebenta da Disciplina de Introdução à Programação

switch (expressão) {

case

constante

instrução break ; default }

Figura 32. Instrução de selecção múltipla switch-case

A instrução break após cada case serve para evitar que os próximos cases sejam executados. Se há um case
que tem o mesmo valor da expressão o seu bloco de instruções deve ser executado e o break faz com que a
instrução switch seja terminada.

O default é o caso que deve ser executado quando mais nenhum serve (segundo o fluxograma é a opção outro).
Os cases que não sejam explicitamente programados num switch sem default são ignorados. A existência do
default foca o programador na necessidade de processar condições excepcionais. Há, no entanto, situações em
que a utilização do default não é necessária.

Nota:
Esquecer um break onde ele deve ser usado, conduz a erros lógicos ou semânticos.
Embora a ordem dos cases e do default não esteja estipulada à partida, é considerada boa prática colocar o
default em último lugar.
O break após a última instrução case (ou default, se esta for a última), não é necessário. Muitos
programadores colocam-no apenas por uma questão de coerência e simetria para com as anteriores.

Exemplo 1:
public class Pontos
{
public static void main(String args[])
{
int pontos;
Scanner scanTeclado = new Scanner(System.in);
System.out.print (“Digite um inteiro entre 1 e 100:> “);
pontos = scanTeclado.nextInt();
switch (pontos/10)
{
case 10:
case 9: System.out.println("A - Excelente!");
break; // por exemplo, se o break nao estivesse aqui
// e pontos/10 = 9, o bloco seguinte (do case 8)
// era executado na mesma, conduzindo a um erro!

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 66


Sebenta da Disciplina de Introdução à Programação

case 8: System.out.println(“B - Bom trabalho!");


break;
case 7: System.out.println("C - Pode fazer melhor!");
break;
case 6: System.out.println("D - Falamos depois da
aula.");
break;
default: System.out.println("F – Vai trabalhar!");
}
}
}

Exemplo 2:

public class TestaCaracter


{
public static void main(String args[])
{
Scanner scanTeclado = new Scanner(System.in);
char ch = scanTeclado.nextChar();

switch (ch)
{
case ‘0’: case ’1’: case ’2’: case ’3’: case ’4’:
case ’5’: case ’6’: case ’7’: case ’8’: case ’9’:
return (ch – ‘0’);

case ‘a’: case ‘b’: case ‘c’: case ‘d’: case ‘e’:
case ‘f’:
return (ch – ‘a’) + 10;

case ‘A’: case ‘B’: case ‘C’: case ‘D’: case ‘E’:
case ‘F’:
return (ch – ‘A’) + 10;

default:
System.out.print(“Adeus.”);
}
}
}
// Não há breaks porque cada expressão tem um return que
// sai do bloco antes que se tente sequer avançar para o próximo!

If Versus Switch

O if é apropriado para testes em expressões que representem valores lógicos


O switch faz selecções com base expressões cujos valores sejam inteiros
Utiliza-se o if quando
O número de alternativas é pequeno
Queremos impor uma ordem na avaliação da expressão
A escolha é baseada em gamas de valores (tipo x>1, ou y>100 && y>200... )

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 67


Sebenta da Disciplina de Introdução à Programação

Utiliza-se o switch quando


Se testam expressões cujos resultados são valores de tipos enumeráveis (inteiros, caracteres)

4.2 - Repetição
É fundamental que uma linguagem de programação dê suporte à repetição de tarefas, não só por uma questão de
eficiência mas também de produtividade.
Se há uma tarefa que deve ser executada 500 vezes, não vamos escrever 500 vezes o mesmo bloco de código. Não
só deixa de ser produtivo, é cansativo e desmotivante, mas ainda por cima torna o código mais susceptível a erros
que para serem corrigidos nos obrigam a percorrer cada um dos blocos de instruções que programámos
repetidamente.

As instruções que nos permitem resolver este tipo de problemas de uma forma mais eficaz são as instruções de
repetição, também conhecidas por ciclos.

Um ciclo é uma sequência de instruções executada de forma repetitiva e sujeita a uma condição de término. É
normalmente composto por:
Corpo: conjunto de instruções a repetir
Uma condição ou outra estrutura que controla a execução do corpo, especificando de alguma forma a quantidade de
vezes que este deve ser executado (número de iterações).

Quando um ciclo não tem fim, ou seja, repete as instruções do corpo indefinidamente, diz-se que se trata de um Ciclo
Infinito.
Este tipo de situações é absolutamente indesejável pois se um ciclo não termina o programa não avança e,
consequentemente, a sua execução também não terá fim nem produzirá resultados. Para além disso, corremos o
risco de esgotar os recursos do computador rapidamente se durante esse ciclo interminável houver operações
exigentes em termos de requisitos de memória, por exemplo.

Em Java ( e na maioria das linguagens de programação de alto nível), há três tipos de instruções de repetição:

while
do-while
for

4.2.1 - Instrução de Repetição while


Esta instrução de repetição baseia-se na avaliação de uma condição lógica para determinar a continuação (ou não) da
execução do corpo do ciclo.

De acordo com o que nos mostra o fluxograma seguinte, o que vemos é que enquanto a condição tiver o valor
verdadeiro (true), o corpo continua a ser executado.

Expressão Instruções
Verdadeiro
Falso

Figura 33. Fluxograma de uma instrução de repetição while

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 68


Sebenta da Disciplina de Introdução à Programação

while ( expressão-lógica ) instrução

Figura 34. Instrução de repetição while

Código exemplo de uma instrução while:

// as chavetas aparecem se houver mais do que uma instrução


// a executar no corpo do ciclo

while(condição){
instruções;
}

Após uma pequena análise dos diagramas e sintaxes apresentados acima, há algumas pequenas notas a fazer:
A avaliação da expressão ou condição tem que ter obrigatoriamente como resultado um valor lógico (true ou
false).
O corpo do ciclo pode ser uma instrução simples ou composta. Isto é, pode haver uma ou mais instruções a repetir.
Essas instruções são repetidas enquanto a condição a avaliar em cada passagem for verdadeira.
Se a condição a verificar tiver à partida o valor false, o ciclo não chegará a ser executado.
Para que o ciclo não se torne infinito, temos de garantir de alguma forma que a expressão avaliada a cada passagem
chegará a ter o valor false. Isso consegue-se fazendo com que uma das instruções do corpo do ciclo se encarregue
de mudar o valor da condição no momento apropriado.

Exemplo 1:

public class CicloWhile


{
public static void main(String args[])
{
int a=30, b=15, i=3;

while (i>0)
{
a-=10;
b-=5;
i--;
System.out.println(“A é “ + a + “B é “ + b);
}
}
} // qual é o resultado produzido?

Exemplo 2:

/* Programa que gera um número entre 1 e 100 é verifica se o


número é primo (primo é um número maior que 2 e que é divisível
somente por si próprio e por 1) */
import java.util.Random;

public class NumeroPrimo {


public static void main(String[] args) {

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 69


Sebenta da Disciplina de Introdução à Programação

int d = 2;
Random random = new Random();
int x = random.nextInt(100)+1;
boolean primo = (x > 1);

while (primo && d <= x)


primo = (x % d++ != 0);

if (primo)
System.out.println(x + " e primo.");
else
System.out.println(x + " não é primo.");
}
}

Exemplo 3:

public class CicloInfinito


{
public static void main(String args[])
{
int a=0, i=0;
do
{
++a;
++i;
System.out.println(“A é “ + a);
}
while (i > 0);
}
} // Este é um exemplo a não seguir!

4.2.2 - Instrução de Repetição do-while


A instrução de repetição do-while é semelhante à anterior (while), no sentido em que executa o corpo do ciclo
enquanto a condição a avaliar for verdadeira.
Devem respeitar-se as mesmas regras para evitar a geração de ciclos infinitos, ou seja, há que garantir que no corpo
do ciclo existe alguma instrução que no momento certo muda a o valor da condição por forma a quebrar o ciclo.
Apesar de o modo de funcionamento ser aparentemente o mesmo, o do-while comporta-se de maneira
ligeiramente diferente: primeiro executa o corpo do ciclo e só depois avalia o valor da condição de paragem. Isto faz
com que se gere uma nuance que marca toda a diferença:

Por avaliar primeiro a condição, um while pode nunca chegar a executar o corpo, se a condição for falsa logo à
partida. Diz-se que o while executa 0 ou mais vezes.
Por avaliar a condição no fim, um do-while executa sempre o corpo pelo menos uma vez. O do-while
executa 1 ou mais vezes.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 70


Sebenta da Disciplina de Introdução à Programação

Em termos de fluxograma, um do-while pode representar-se da seguinte forma:

Instruções

Expressão
Verdadeiro
Falso

Figura 35. Fluxograma da instrução de repetição do-while

do instrução while ( )

expressão-lógica
Figura 36. Instrução de repetição do-while

Código exemplo para uma instrução do-while:

do { // as chavetas aparecem quando o corpo do ciclo tem


// mais do que uma instrução a executar!
instruções;
} while(condição);

Exemplo 1:

public class CicloDoWhile


{
public static void main(String args[])
{
int a=0, i=0;

do
{
++a;
++i;
System.out.println(“A é “ + a);
}
while (i<3);
}
} // qual é o resultado produzido?

Exemplo 2:

Programa que gera um número entre 1 e 100 e verifica se o número é primo.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 71


Sebenta da Disciplina de Introdução à Programação

import java.util.Random;

public class Primo


{
public static void main(String[] args)
{
boolean primo;
int d = 2;
Random random = new Random();
int n = random.nextInt(100)+1;

do
primo = (n % d++ != 0);
while (primo && d < n);

if (primo)
System.out.println(n + " é primo.");
else
System.out.println(n + " não é primo.");
}
}

Recapitulando:

A instrução de repetição while começa por avaliar a expressão :


Se for verdadeira entra no ciclo
Executa instrução ou bloco de instruções internas ao ciclo
A cada nova iteração re-avalia a expressão lógica
Se a expressão se tornou falsa o ciclo termina
A instrução do-while:
Executa o bloco de instruções internas ao ciclo
Avalia a expressão
Se for verdadeira continua o ciclo, senão termina
Conclusão:
A instrução do-while executa o bloco de instruções uma ou mais vezes
A instrução while executa o bloco de instruções zero ou mais vezes

4.2.3 - Instrução de Repetição for


A instrução for é outra instrução de repetição muito útil, particularmente quando se conhece de antemão a
quantidade de iterações necessárias (ou seja, o número de vezes que se pretende repetir o corpo do ciclo).
A execução do corpo do ciclo for está, regra geral, dependente da avaliação do valor de uma variável de controlo.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 72


Sebenta da Disciplina de Introdução à Programação

for ( expressão ; expressão ; expressão )


lógica

instrução

Figura 37. Instrução de repetição for

Código exemplo para a instrução de repetição for:

for(expressão1;expressão2;expressão3){
instruções
}

O modo de funcionamento é o seguinte:


Parte de expressão1, é a expressão que inicializa o ciclo atribuindo um valor inicial à variável de controlo.
Avalia expressão2 (o teste que é efectuado em cada ciclo).
Se é verdadeira:
executa instrução
executa incremento (instrução que altera o valor da variável de controlo) determinado por expressão3 para a
variável de controlo de expressão1
regressa ao passo 2
Se é falsa:
Termina o ciclo

Em termos de fluxograma, um for poder-se-ia representar da seguinte forma (seguindo literalmente a especificação
do ciclo):

Verdadeiro
Expressão Instruções

Falso
Aplica Experssão 3 a Experssão 1

Figura 38. Fluxograma da instrução de repetição for

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 73


Sebenta da Disciplina de Introdução à Programação

Notas:

Num ciclo for, devemos ter em atenção que, a variável de controlo, ao ser declarada no cabeçalho do ciclo, só é
conhecida dentro do seu corpo. Se tentarmos usá-la fora do ciclo obtemos um erro de sintaxe. Para conseguir esse
efeito devemos declará-la antes do cabeçalho do ciclo (a inicialização pode, ou não, ser feita nesse cabeçalho).
Um erro comum de programação consiste em usar virgulas, ao invés de pontos e virgula, para separar as expressões
do cabeçalho do for.
Normalmente geram-se erros semânticos/lógicos se colocarmos um ; imediatamente a seguir ao ) do cabeçalho do
for, isto porque assim o ciclo não tem corpo e passa a executar uma sucessão de instruções vazias.

Exemplo 1:

public class CicloFor


{
public static void main(String args[])
{
int a=0, b=0;
for (int i=0; i<3; i++)
{
a+=10;
b+=5;
System.out.println(“A é “ + a + “B é “ + b);
}
}
}
Exemplo 2:

// Programa que gera aleatoriamente um número entre 1 e 100


// e verifica se o número é primo.

import java.util.Random;

public class Primo


{
public static void main(String[] args)
{

Random random = new Random();


int n = random.nextInt(100)+1;

for (int d = 2; d < n; d++)


if (n%d == 0) {
System.out.println(n + " não é primo.");
return;
}

System.out.println(n + " é primo.");


}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 74


Sebenta da Disciplina de Introdução à Programação

Todas as 3 expressões do cabeçalho do for são opcionais:

Se omitirmos a expressão2, o Java assume que a condição de continuação do ciclo é true, gerando portanto
um ciclo infinito.
Podemos omitir a expressão1 se inicializarmos a variável de controlo antes do ciclo.
Podemos omitir a expressão3 se o programa calcular o incremento ou decremento com instruções dentro do
corpo do ciclo.

Ciclos Encadeados

Tal como podemos ter instruções de selecção encadeadas, também podemos ter ciclos encadeados, ou seja, ter
ciclos dentro de ciclos.
A regra dita apenas que o ciclo mais interior é o último a ser executado. Desde que o exterior reúna as condições para
prosseguir, o interior também terá a sua chance de realizar trabalho.

Exemplo 3:

public class CiclosEncadeados


{
public static void main(String[] args)
{
final int SIZE = 5;
for (int x = 1; x <= SIZE; x++)
{
for (int y = 1; y <= SIZE; y++)
{
int z = x*y;
if (z < 10) System.out.print(" ");
System.out.print(" " + z);
}
System.out.println();
}
}
}
Nota:

Não é aconselhável encadear muitos ciclos uns nos outros. Torna muito mais difícil a manutenção do código e a
resolução de problemas, ou seja, aumentamos toda a complexidade da solução.
Uma métrica razoável seria nunca utilizar mais do que três ciclos encadeados.

while versus do-while, versus for

Após sabermos como funciona cada tipo de instrução de repetição reside ainda uma questão por resolver: qual delas
deve ser usada em cada situação?

Um ciclo for, usa-se essencialmente quando o número de repetições é conhecido antes do início da sua execução.
Em Java, o for é flexível o suficiente para que possa ser utilizado em situações onde o número de repetições seja
também controlado por uma condição lógica e em que o número de repetições não seja conhecido de antemão. No
entanto, apesar de tal ser possível e de produzir um código mais compacto, por norma também é mais difícil de ler e
compreender caso tenhamos de corrigir erros.

Quando o número de repetições não é conhecido à partida, estando a execução do bloco de instruções dependente
apenas de uma condição lógica, devemos então utilizar o while.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 75


Sebenta da Disciplina de Introdução à Programação

Devemos usar um ciclo do-while em situações em que o bloco de instruções a repetir, para além de estar
dependente da avaliação de uma condição lógica, deva ser executado pelo menos uma vez. Aliás, é esse o ponto que
marca a diferença entre um do-while e os outros dois tipos de instruções de repetição.

4.3 - Exercícios Práticos


Grupo I

1. Que tipos de instruções de controlo conhece?


2. Na sua opinião, para que servem as instruções de controlo?
3. Qual é o objectivo da instrução if? E do switch? Quais as diferenças entre estas duas instruções de selecção?
Em que tipo de situações se deve usar uma ou a outra? Justifique todos os passos da resposta.
4. Ao utilizar o if tem de utilizar sempre e obrigatoriamente um else? Se não for o caso indique a que situações se
aplicam a utilização do else.
5. É possível ter instruções if encadeadas ou paralelas. Verdadeiro ou falso?
6. Para que serve a utilização da instrução break no código de um switch?
7. O que representa a opção de default?
8. O que é um ciclo? Qual é a motivação que encontra na utilização de instruções de repetição?
9. Quais são as instruções de repetição que conhece? Quais as diferenças entre elas? Quando acha que deve
utilizar cada uma? Justifique cada passo da resposta.
10. É possível codificar ciclos encadeados? Quais são as limitações que encontra neste tipo de solução?
11. O que são ciclos infinitos?

Grupo II

Exerc. 1: Para os exercícios seguintes indique o output que espera como resultado, tendo em conta a declaração e
inicialização das seguintes variáveis:

final int MAX = 25, LIMIT = 100;


int num1 = 12, num2 = 25, num3 = 87;

Alínea A
if (num3 >= LIMIT)
System.out.println ("maçã");
System.out.println ("laranja");
System.out.println ("pera");
Alínea B
if (num2 == MAX)
{
System.out.println ("maçã");
System.out.println ("laranja");
}
System.out.println ("pera");
Alínea C
if (LIMIT+num3 <= 150)
{
System.out.println ("maçã");
System.out.println ("laranja");
}
else
System.out.println ("pera");

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 76


Sebenta da Disciplina de Introdução à Programação

Alínea D
if (num1 < MAX)
if (LIMIT >= num2)
System.out.println ("maçã");
System.out.println ("laranja");
Alínea E
if (LIMIT%num1 + 4 == num1 + (MAX-num2))
{
System.out.println ("maçã");
System.out.println ("laranja");
}
else
{
System.out.println ("pera");
System.out.println ("banana");
}
Alínea F
if (num2 > 18)
if (num1 < 0)
System.out.println ("maçã");
else
System.out.println ("laranja");
System.out.println ("pera");

Alínea G
if (num3 >= MAX)
{
if (MAX/num2 == 1)
System.out.println ("maçã");
System.out.println ("laranja");
if (LIMIT-num3 > num1+2)
System.out.println ("pera");
else
{
System.out.println ("banana");
System.out.println ("kiwi");
}
}
else
if (num2*2 == MAX*2)
System.out.println ("uva");
Alínea H
if (LIMIT >= 4*num2)
if (MAX == 25)
System.out.println ("maçã");
else
System.out.println ("laranja");
else
System.out.println ("pera");.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 77


Sebenta da Disciplina de Introdução à Programação

Exerc. 2: Para os exercícios seguintes escreva segmentos de código que sirvam para executar as acções indicadas:

Alínea A
Imprimir “Hurra!” se a variável sum for divisível por count

Alínea B
Imprimir “Num é zero”, “Num é positivo”, “Num é negativo”, consoante o valor de num.

Alínea C
Atribuir o valor mais pequeno de dois inteiros à variável smallest utilizando:
If-else
Operador condicional

Alínea D
Imprimir “Igual” se dois valores do tipo float guardados em val1 e val2 forem exactamente iguais e
“Essencialmente igual” se esses dois valores estiverem a uma distância inferior ou igual a 0.0001 um do outro.
Imprimir “Diferente” se não forem de todo iguais ou semelhantes.:

Exerc. 3: Nos seguintes exercícios indicar o output que irá ser produzido tendo em conta o valor de base das
seguintes variáveis:
final int MIN = 10, MAX = 20;
int num = 15;
Alínea A
while (num < MAX)
{
System.out.println (num);
num = num + 1;
}
Alínea B
do
{
num = num + 1;
System.out.println (num);
}
while (num <= MAX);
Alínea C
for (int count1=1; count1 <= 5; count1++)
{
for (int count2=1; count2 <= 5; count2++)
System.out.print (count1*count2 + " ");
System.out.println();
}
Alínea D
while (num > MIN)
{
System.out.println (num);
num = num - 1;
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 78


Sebenta da Disciplina de Introdução à Programação

Alínea E
while (num < MAX)
{
if (num%2 == 0)
System.out.println (num);
num++;
}
Alínea F
for (int value=7; value < 0; value--)
System.out.println (value);
Alínea G
do
{
num = num + 1;
if (num*2 > MAX+num)
System.out.println (num);
}
while (num <= MAX);
Alínea H
for (int value=num; value <= MAX; value++)
if (value%4 != 0)
System.out.println(value);
Grupo III

Exerc. 1: Implemente um método que receba um número e indique se o número é par ou ímpar.

Exerc. 2: Implemente um método que receba um caracter e determinar se este corresponde a um dígito.

Exerc. 3: Implemente um método que receba um determinado número e informe o utilizador se o mesmo é divisível
por 5.

Exerc. 4: Implemente um método que receba um número inteiro e verifique se é divisível por 2, 3, 5, 6, 10, 15 ou 30.

Exerc. 5: Implemente um método chamado, calcIRS, que receba o ordenado de um trabalhador e devolva o
imposto a pagar de acordo com a tabela 2:
Ordenado Taxa
<100.000 5%
>= 100 000 e < 300 000 15%
> 300 000 25%
Tabela 1
Exerc. 6: Observe o código da figura seguinte e indique, caso existam, os erros existentes:

switch(n)
{
case 1:
a=11;
b=22;
break;
case 2:
c=33;
break;
d=44;
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 79


Sebenta da Disciplina de Introdução à Programação

Exerc. 7: Crie uma classe, chamada Utilitaria, constituída pelos seguintes métodos:
a) gerar um número aleatório;
b) receber dois números obtidos aleatoriamente e retornar o resultado da operação matemática entre ambos,
dependendo do operador escolhido (+, -, *,/)
Crie outra classe, chamada Principal, que permita testar os métodos desenvolvidos na classe Utilitaria.

Exerc. 8: Implemente um método que receba três valores reais, que correspondem a três lados de um triângulo e que
classifique o triângulo como equilátero, isósceles ou escaleno.

Exerc. 9: Crie uma classe, chamada Utilitaria, constituída pelos seguintes métodos:
a) ler um número inteiro;
b) Calcular a soma de um conjunto de números. A quantidade de números é desconhecida à partida. A sequência de
entrada só termina quando for introduzido um número negativo.
Crie outra classe, chamada Principal, que permita testar os métodos desenvolvidos na classe Utilitaria.

Exerc. 10: Implemente um método que recebe um valor n e calcule a soma de n primeiros números positivos.

Exerc. 11: Escreva, utilizando um ciclo “for”, um conjunto de instruções equivalente a:

while (i<100)
System.out.println(i,“ao quadrado é igual a ”,Math.sqr(i));

Exerc. 12: Observe o código da figura seguinte e indique, caso existam, os erros existentes:

public class Exercicio {


public static void main(String [ ] args){
System.out.print(0);
int fib0 = 0;
int fib1 = 1;
int fib2 = 1;
while (fib2<1000);
{
fib0=fib1;
fib1=fib2;
fib2=fib0 + fib1;
System.out.print(“ , “ + fib1);
}
}

Exerc. 13: Um banco venda moeda estrangeira (Dólares, Francos, Libras, etc.) e leva uma comissão de 2% do valor
transaccionado mais 1 Euro. Escreva um programa para indicar qual o valor a pagar por uma certa venda de moeda.
O programa recebe a quantia e tipo de moeda a adquirir. As taxas de câmbio existem no programa como constantes.

Exerc. 14: Uma certa empresa fabrica motores com potências compreendidas entre 1 e 99cv. Ao processar
informação sobre um destes motores, um programa usa um de três procedimentos, de acordo com a potência do
motor. Partindo do princípio que o programa está escrito em Java e de que a variável inteira Pot representa a potência
do motor a ser fabricado, escreva uma instrução if que execute o procedimento correspondente de acordo com a
tabela seguinte:

Potência do motor Acção a executar


Pot < 1 Mensagem de erro
1 <= Pot < 5 PW1
5 <= Pot < 20 PW2
20<= Pot < 100 PW3
Pot >= 100 Mensagem de erro

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 80


Sebenta da Disciplina de Introdução à Programação

As condições das instruções if não devem ter conjunções.

Exerc. 15: Escreva um programa em Java que converta notas quantitativas de 0 a 20 em notas qualitativas de mau a
excelente, utilizando uma estrutura de if’s encadeados e que verifique o limite superior das gamas de cada uma das
notas qualitativas.
Considere que:
0-4 : Mau
5-9 : Medíocre
10-13 : Suficiente
14-17 : Bom
18-20 : Muito Bom

Exerc. 16: Escreva um programa em Java para calcular os juros e o novo saldo de uma conta bancária, tendo em
atenção que se o saldo for inferior a 1.000 a conta não recebe juros e paga uma taxa ao banco (multa). Caso a conta
atinja um saldo negativo é cancelada. O programa deverá ter a multa representada por uma constante. Deverá ler o
saldo anterior, o número de meses ao fim do qual queremos calcular o saldo, e a taxa de juros anual. Parta do
princípio de que não há movimentos na conta e de que os juros só são calculados no fim do número de meses
especificado.

Exerc. 17: Relativamente à classe Aluno, criada no capítulo 3, implemente os seguintes métodos:
retornar falso se a nota da prova específica de matemática foi inferior a 12 valores;
verificar se a nota da prova específica foi inferior a 12 valores (invoque o método que calcula a média e o
implementado na alínea anterior).
imprimir um menu que permita ter as seguintes opções: inserir; listar; apagar e procurar aluno e sair do programa.
tratar as opções do menu anterior.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 81


Sebenta da Disciplina de Introdução à Programação

5- Tópicos Avançados de Classes

Como referido no livro “Fundamentos de Programação em Java2, FCA”, numa linguagem orientada a objectos os
programas funcionam através da criação de objectos, dos comportamentos que estes são capazes de apresentar e da
comunicação entre eles. Um objecto pode solicitar a outro um determinado comportamento, de entre os que estão
definidos. Antes de criar um objecto é necessário ter um “molde” que defina os seus atributos e comportamentos, o
qual se denomina por classe. Antes de se criar um objecto é necessário criar a respectiva classe. Podem ser criados
diversos objectos a partir de uma classe, cada um com atributos próprios mas com os mesmos comportamentos.
As linguagens de programação orientadas a objecto incluem diversas classes predefinidas a partir das quais se
podem criar objectos. Contudo, para a maioria dos programas é necessário definir novas classes de forma a poder
criar objectos que satisfaçam as necessidades dos programadores.
No JAVA, a definição de classes segue a seguinte sintaxe:

public class nomeDaClasse


{
//Declarações de atributos

// Construtores

// Métodos
}

As variáveis ou atributos, os construtores e os métodos de uma classe são genericamente denominados membros da
classe.

5.1 - Variáveis de Instância e variáveis de Classe


Numa classe podem ser declaradas variáveis de dois tipos: variáveis de instância e/ou variáveis de classe.

As variáveis de instância são as variáveis definidas para armazenar os atributos específicos de cada objecto, por
exemplo a cor, o peso, etc. Cada objecto da classe definida tem a cor e o peso como atributo embora os seus valores
possam ser diferentes para cada objecto.

As variáveis de classe não existem nos objectos. A declaração de uma variável de classe provoca a criação de uma
variável em memória, a qual será partilhada por todos os objectos que forem criados a partir da classe. Assim, as
alterações efectuadas por um objecto ao valor de uma variável de classe manifestam-se quando a mesma variável é
acedida por qualquer objecto da mesma classe. Este tipo de variáveis utiliza-se quando é necessário partilhar
informação entre objectos de uma classe ou aglutinar informação produzida pelos mesmos.

Como exemplo de uma variável de classe, podemos considerar uma situação em que se tenha interesse em saber
quantos alunos existem. A solução passa pela criação de uma variável de classe da classe Aluno que seja
incrementada quando for criado um novo objecto:

public static int numeroDeAlunos = 0;

A palavra reservada static indica ao compilador que deve criar uma variável que é partilhada por todos os
objectos da classe e como tal não deve criar uma cópia da variável sempre que for criado um novo objecto.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 82


Sebenta da Disciplina de Introdução à Programação

Da mesma forma que existem variáveis estáticas também existem métodos estáticos. Os métodos estáticos podem
ser invocados sobre a classe, não é necessário criar nenhuma instância da classe (i.e. um objecto) em que foram
declarados para os podermos utilizar (um bom exemplo disto são os métodos definidos na classe Math).
Os métodos estáticos apenas podem manipular variáveis locais ou então atributos estáticos pois as variáveis de
instância só são criadas quando são criadas instâncias da classe.
A figura seguinte apresenta um exemplo de utilização de atributos e métodos estáticos.

// Demonstração de utilização de atributos e métodos estáticos


// Utilizando uma versão simplificada da classe Aluno

// versão simplificada da classe Aluno


public class Aluno {

// VARIÁVEIS DE CLASSE
static private int numeroDeAlunos = 0;

// VARIÁVEIS DE INSTÂNCIA
private String nome;
private int numero;

//CONSTRUTORES
public Aluno( String nom)
{
nome = nom;
numero = this.numeroDeAlunos++ +1;
}

// método estático – pode ser invocado sem ser criado


// nenhum objecto
public static int getNumeroDeAlunos()
{
return numeroDeAlunos;
}

// selectores
public int getNumero()
{
return numero;
}
public String getNome()
{
return nome;
}
}

// Exemplo de utilização de atributos e métodos estáticos


public class ExemploVariaveis {

public static void main(String[] args) {


// Declaração de 3 variáveis do tipo aluno
Aluno aluno1, aluno2, aluno3;

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 83


Sebenta da Disciplina de Introdução à Programação

System.out.println();
System.out.print("Número de Alunos existentes :");

//Chamada do método estático da classe Aluno


System.out.println( Aluno.getNumeroDeAlunos());

// criar 1º aluno com o nome "António"


aluno1 = new Aluno("António");

//Imprimir o número de alunos criados


//utilizando um método da classe
System.out.print("Número de Alunos (via classe): " +
Aluno.getNumeroDeAlunos());

//Imprimir o número de alunos criados utilizando o objecto aluno1


System.out.print("Número de Alunos (via aluno1): " +
aluno1.getNumeroDeAlunos());

// criar 2º aluno com o nome "Maria"


aluno1 = new Aluno("Maria");

// Obter o nome e número do 1º aluno criado


System.out.println("Nome: " + aluno1.getNome());
System.out.println("Número: " + aluno1.getNumero());

// Obter o nome e número do 2º aluno criado


System.out.println("Nome: " + aluno1.getNome());
System.out.println("Número: " + aluno1.getNumero());

//Imprimir o valor da variável de classe


//que representa o nº de alunos

//Imprimir o número de alunos criados


//utilizando um método da classe
System.out.print("Número de Alunos (via classe): ");
System.out.println(Aluno.getNumeroDeAlunos());

//Imprimir o número de alunos criados utilizando o objecto aluno1


System.out.print("Número de Alunos (via aluno1): ");
System.out.println(aluno1.getNumeroDeAlunos());

//Imprimir o número de alunos criados utilizando o objecto aluno2


System.out.print("Número de Alunos (via aluno2): ");
System.out.println(aluno2.getNumeroDeAlunos());

}
}

Figura 39. Demonstração de utilização de atributos e métodos estáticos utilizando uma versão simplificada da classe
Aluno

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 84


Sebenta da Disciplina de Introdução à Programação

5.2 - Modificadores de visibilidade


Na linguagem Java existem três modificadores de visibilidade que permitem controlar as permissões de acesso a um
membro da classe: public, private e protected.
O modificador de visibilidade protected tem a ver com o conceito de herança o qual não é abordado no âmbito desta
disciplina.
Quando um membro de uma classe é declarado com o modificador public, ele é público e pode ser acedido a
partir de qualquer ponto do programa, mesmo por objectos de outras classes. Os membros declarados como
private são privados e como tal só são visíveis e dentro da classe onde estão declarados, pelo que não podem
ser directamente utilizados a partir de outros objectos.
Como regra geral, as variáveis de instância dos objectos devem ser declaradas com visibilidade private. Os
métodos que implementam os serviços fornecidos pelo objecto devem ser declarados public para que possam ser
chamados a partir de outros objectos.
Denomina-se por interface do objecto o conjunto de serviços (o conjunto de métodos) disponibilizados pelo objecto.
Os métodos que não pertencem à interface são métodos utilizados para auxiliar a implementação dos serviços e
devem ser declarados como privados.

5.3 - Encapsulamento
O conceito de encapsulamento representa o princípio que cada objecto deve ser responsável pelos seus próprios
dados e deve controlar o seu funcionamento. Um objecto deve funcionar como uma caixa negra que é capaz de
apresentar um conjunto de comportamentos se for solicitado. Para o exterior basta dar a conhecer os comportamentos
possíveis e os seus efeitos, mas não a forma como são implementados
Um objecto pode ser considerado sob duas perspectivas: a interna e a externa. A perspectiva interna tem a ver com a
estrutura dos seus dados e com os algoritmos utilizados para implementar os seus comportamentos. Esta perspectiva
apenas interessa ao programador que criou a classe, pois só este necessita de conhecer os seus detalhes internos.
Numa perspectiva externa, um objecto é visto como uma entidade encapsulada, que apenas responde a um
determinado conjunto de pedidos que lhe podem ser feitos por outros objectos. Estes pedidos correspondem ao
conjunto de comportamentos definidos como públicos na classe do objecto, i.e., acessíveis do exterior.
Esta perspectiva permite a reutilização do código do objecto uma vez que os detalhes internos de um objecto são
independentes do contexto da sua utilização.
Para obter este nível de independência, um objecto deve ser auto-contido, ou seja, qualquer alteração do seu estado
(das suas variáveis) deve ser provocada apenas pelos seus métodos e não deve permitir que outro objecto altere o
seu estado.

5.4 - O Operador de Auto-Referenciação this


A palavra reservada this pode ser utilizada, dentro de um bloco de um método, para referir o objecto actual.
this é um “apontador” ou uma referência para o objecto em questão. Usando este apontador, um método pode
aceder a todas os atributos da classe a que pertence.
this é criado automaticamente quando um objecto chama um método e “aponta” para o próprio objecto que chamou
o método.

// exemplo de utilização de this com a classe Aluno



//ATRIBUTOS

private String nome;


private int numero;
private int ano;
private String curso;
private char turma;

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 85


Sebenta da Disciplina de Introdução à Programação

private double valorPropina;


private double valorPago;

//CONSTRUTORES

public Aluno(String nome, int numero, String curso, int ano,


char turma)
{
this.nome = nome;
this.numero =numero;
this.ano=ano;
this.curso=curso;
this.turma=turma;
valorPropina=0;
valorPago=0;
}
Figura 40. Exemplo de utilização de this com a classe aluno

Neste caso o operador this ajuda ainda a resolver ambiguidades. Caso contrário como saberíamos de que nome,
numero, ano, curso ou turma se estava a falar? Quando se utiliza this.nome estamos a referenciar a
variável de instância nome pertencente ao objecto que está a ser criado, evitando deste modo a confusão com o
parâmetro nome do método construtor Aluno.

5.5 - Passagem por Parâmetros Referenciados


Como foi referido anteriormente, em Java, a passagem de parâmetros é sempre feita por valor. Contudo, quando se
passa um objecto como parâmetro, na realidade o que é passado é o valor da referência do objecto e não o objecto
propriamente dito. Deste modo, as alterações efectuadas sobre um objecto recebido como parâmetro de um método
reflectem-se fora do mesmo.
Todos os tipos de dados em Java que não sejam primitivos são objectos. As variáveis que representam objectos são
na realidade referências (apontadores) para zonas de memória onde estes estão armazenados.
Ao passar como parâmetro para um subprograma uma variável que representa um destes tipos, estamos a passar
uma cópia da referência para o mesmo. Isto significa que, se dentro do subprograma fizermos alguma operação sobre
essa variável, estamos na realidade a alterar o objecto e quem chamou o subprograma vê essa alteração. Isto
provoca um comportamento idêntico ao da passagem por referência.

// exemplo de passagem por parâmetros referenciados

public class Referencia {

public static void main(String[] args) {

Aluno aluno = new Aluno("João", 2133,"EI", 1, 'A');


// escreve o nome do aluno – "João"
System.out.println( aluno.getNome());
// passagem “por referencia” de aluno
mudaNomeAluno(aluno);
// escreve o nome do aluno após alteração no subprograma – "José"

System.out.println( aluno.getNome());

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 86


Sebenta da Disciplina de Introdução à Programação

public static void mudaNomeAluno( Aluno aluno1) {


aluno1.setNome("José");
}

}
Figura 41. Exemplo de passagem por parâmetros referenciados

5.6 - Sobrecarga de Métodos


O Java permite a sobrecarga de métodos.
Diz-se que existe sobrecarga de métodos sempre que numa classe existem vários métodos com o mesmo nome, mas
diferentes assinaturas. Por exemplo, na classe String existem diversos métodos valueOf, por
exemplo:

static String valueOf(boolean b)


static String valueOf(char c)
static String valueOf(char[] data)
static String valueOf(boolean b)

A sobrecarga de métodos é bastante utilizada no caso dos construtores. Como exemplo podemos ver a figura
seguinte onde são definidos dois construtores para aluno, os quais podem ser utilizados conforme a informação
disponível na altura da criação do objecto da classe Aluno.

public Aluno(String nome, int numero, String curso)


{
this.nome = nome;
this.numero =numero;
this.ano=1;
this.curso=curso;
this.turma=' ';
valorPropina=1000;
valorPago=0;
}

public Aluno(String nome, int numero, String curso, int ano,


char turma)
{
this.nome = nome;
this.numero =numero;
this.ano=ano;
this.curso=curso;
this.turma=turma;
valorPropina=1000;
valorPago=0;
}
Figura 42. Exemplo de sobrecarga do construtor

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 87


Sebenta da Disciplina de Introdução à Programação

5.7 - Exercícios Práticos

Objectivos da Série:

Com esta série de problemas pretende-se que o aluno:


• Saiba diferenciar e utilizar variáveis de instância e variáveis de classe;
• Compreenda os modificadores de visibilidade apresentados e as situações em que cada um deve ser
utilizado
• Utilize o operador de Auto-referenciação this

Parte I – Questões Teóricas

1. Diga o que entende por variável de classe e variável de instância. Mencione as diferenças entre ambas e
justifique a resposta.
2. Como pode criar e utilizar variáveis de classe? Isto é, quais são os passos a dar? Justifique e dê exemplos.
3. Para utilizar uma variável e/ou um método estático de uma classe necessita de instanciar a classe?
Justifique.
4. Métodos estáticos podem referenciar atributos que não sejam estáticos? Justifique.
5. O que é e para que serve o operador this?

Parte II – Aplicação de Conceitos Usando Pequenos Programas

Exerc. 1: Indique qual o resultado visualizado no ecrã após a execução do seguinte programa:

public class VariavelDeClasse {


static int n = 2;
String descricao;
public static void main(String[] args)
{
VariavelDeClasse v1 = new VariavelDeClasse();
v1.n = 1;
VariavelDeClasse.n--;
v1.descricao = "Ola";
VariavelDeClasse v2 = new VariavelDeClasse();
v2.n = 2;
VariavelDeClasse.n++;
v2.descricao = "isto e um teste";
System.out.print(v1.descricao + " ");
System.out.print(v1.n);
System.out.print(" ** ");
System.out.print(v2.descricao + " ");
System.out.print(v2.n);
}
}

a) Ola 1 ** isto e um teste 2


b) Ola 2 ** isto e um teste 3
c) Ola 3 ** isto e um teste 3
d) Ola 0 ** isto e um teste 3

Exerc. 2: No exercício anterior, indique onde se encontra uma variável de classe e uma variável de instância.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 88


Sebenta da Disciplina de Introdução à Programação

Exerc. 3: Crie um programa que determine a partir das coordenadas de 3 pontos, fornecidas pelo utilizador, o tipo de
triângulo que estas representam (equilátero, isósceles ou escaleno). Deve também mostrar se se trata ou não de um
triângulo rectângulo.

Nota:
1. Triângulo equilátero tem os 3 lados iguais.
2. Triângulo isóscele tem 2 lados iguais.
3. Triângulo escaleno tem os 3 lados diferentes.
4. Um triângulo é rectângulo quando verifica a propriedade dada pelo teorema de Pitágoras: o quadrado da
hipotenusa é igual à soma dos quadrados dos catetos.

Deve implementar:
1. A classe ponto para representar as coordenadas e
2. A classe triângulo para representar triângulos.
3. Em separado terá a classe que contém o programa principal e faz uso das outras duas para cumprir os
objectivos pretendidos.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 89


Sebenta da Disciplina de Introdução à Programação

6- Tabelas

6.1 - Motivação
Um programa que manipule vários valores, armazena estes valores em algumas variávei, faz o respectivo
processamento e envia o resultado para o exterior (fig.-1).

Programa

Valor 1 Variável 1

Valor 2 Variável 2 Saída

Valor 3 Variável 3

Figura 43. Armazenamento, processamento de valores e saída.

Nem sempre os programas manipulam tão poucos valores, podendo necessitar de manipular vários valores. Estes
podem ser lidos e processados um de cada vez(fig.-2).

Valor 1 Programa

Valor 2

Valor 3 variavel Saída

Valor 4

Valor n

...

Figura 44. Manipulação de vários valores

Imaginemos agora um programa que irá ler vários valores e imprimi-los pela ordem inversa. O programa deve
processá-los “quase todos ao mesmo tempo” para produzir a saída desejada (fig. 3).

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 90


Sebenta da Disciplina de Introdução à Programação

Programa

Valor 1 Variável 1

Valor 2 Variável 2

Valor 3 Variável 3

Saída
Valor 4 Variável 4

Valor 5 Variável 5

... ...

Valor n Variável n

Figura 45. Leitura de vários valores e sua visualização pela ordem inversa

A alternativa para este tipo de situações é o uso de Tabelas, que não são mais do que uma lista de valores. Assim,
para o exemplo da fig. 3 poderiamos armazenar os valores numa variável do tipo tabela e aceder aos valores pela
ordem desejada (fig.4).

Valor 1
Programa

Valor 2

Valor 3
Saída
Variável
Valor 4 Tabela

Valor 5

...

Valor n

Figura 46. Armazenamento de vários valores numa tabela.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 91


Sebenta da Disciplina de Introdução à Programação

6.2 - Tabela Unidimensional


6.2.1 - Introdução

Existem duas formas de declarar uma tabela em Java:

(1) <tipo> <variável> [ ]

(2) <tipo> [ ] <variável>

Exemplos :

(1) int tab [ ] ;


(2) int [ ] tab ;

Fazendo uma pequena revisão sobre as variáveis simples, estas :

• armazenam um só valor.
• são criadas quando da sua declaração.
• armazenam tipos primitivos, que são manipulados por valor.

As tabelas:

• são um agregado de valores, todos do mesmo tipo.


• estão indexadas a partir de 0.
• uma vez criadas possuem um tamanho fixo.
• são criadas em java dinamicamente, ou seja, em tempo de execução.
• o seu espaço é automaticamente reaproveitado quando deixam de estar referenciados.

6.2.2 - Passos para utilizar uma tabela

Os passos para utilizar uma tabela são três, declaração, instanciação e referenciação:

1) Declaração :

Na declaração de uma tabela cria-se uma referência para um determinado tipo de dados. No exemplo que
se segue cria-se uma referência para uma tabela de inteiros com qualquer dimensão, sendo a mesma
iniciada com null.

int [] tab;

tab null

2) Instanciação :

Na instanciação de uma tabela é definida a capacidade da mesma. No exemplo seguinte cria-se uma tabela
com o nome tab, com uma capacidade para cinco inteiros.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 92


Sebenta da Disciplina de Introdução à Programação

tab = new int[5] ;

tab

tab[0] tab[1] tab[2] tab[3] tab[4]

• Uma tabela em java é sempre criada dinamicamente com o operador new


• O índice dos elementos começa em 0 e termina em tamanho –1, ou seja, uma tabela de tamanho
N é indexada de 0 a N-1. Caso se exceda a dimensão da tabela é gerada uma excepção.
• Depois de instanciado podemos saber a sua dimensão consultando o atributo só de leitura
length ( exp: tab.length).
• As tabelas de valores numéricos são inicializadas a zero.

A instanciação (criação) de uma tabela pode ser feita no momento de declaração, se se indicar o conteúdo.

int tab [ ] = {1,1,2,3,5,8,13,34}; // é criada uma tabela com


// 8 elementos

tab 1 1 2 3 5 8 13 34

tab[0] tab[3] ….. tab[7]


tab[1]
tab[2]

3) Referenciação :

tab[1] = 12; // o elemento com o índice 1 da tabela


// passa a armazenar o valor 123

tab 1 12 2 3 5 8 13 34

tab[0] tab[3] ….. tab[7]


tab[1]
tab[2]

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 93


Sebenta da Disciplina de Introdução à Programação

Exemplo do uso de tabela e variáveis simples

Uso Variável Simples Tabela


Atribuição valor = 10.6; tab[3] = 10.6;
Entrada valor = tab[3]=
scanTeclado.nextDouble(); scanTeclado.nextDouble();
Saída System.out.println(valor); System.out.println(tab[3]);
Expressão x = valor / 2; x = tab[3] / 2;
Comparação if (valor > 5.0); if (tab[3] > 5.0);
Parâmetros Testa(valor); Testa(tab[3]);

Exemplos de acesso aos elementos de uma tabela:

Exemplo 1

Neste exemplo pretende-se calcular o valor médio da pluvisiosidade em 18 anos. Para tal, cria-se uma tabela que
guarde 18 valores e preenchesse a tabela com os valores da pluvisiosidade:

double [ ] pluv = new double [18];

pluv [0] = 30.55;


pluv [1] = 23.94;
…….
//restante valores

Depois efectua-se a soma dos valores, que pode ser feita por duas formas :

double total = pluv[0] + pluv[1] + pluv[2] + pluv[3]


+ pluv[4] + pluv[5] + pluv[6] + pluv[7]
+ pluv[8] + pluv[9] + pluv[10] + pluv[11]
+ pluv[12] + pluv[13] + pluv[14] + pluv[15]
+ pluv[16] + pluv[17];

ou

double total = 0.0;


for ( int ano = 0; ano < pluv.length; ano ++)
total = total + pluv[ano];

Nota :
relembre-se que o índice do vector começa em 0 e pode ir até length-1

Com o valor da soma efectuado, podemos calcular a média e imprimir para o ecran o valor:

System.out.println(“O valor média de pluviosidade é”+(total/pluv.length));

Exemplo 2

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 94


Sebenta da Disciplina de Introdução à Programação

O exemplo seguinte tem como objectivo pedir ao utilizador o valor de cinco inteiros, imprimir no ecran os valores
introduzidos, calcular a soma, a média e o valor máximo destes valores.

import Le;

public class MaxTotal{

public static void main(String[] args)


{
int n1[] = new int[5];
int soma=0;
int max=0;

//Ler array

for(int i=0;i<5; i++) {


n1[i]= scanTeclado.nextInt();
System.out.println(“Introduza um valor: “);
}

//Mostrar array
for(int i=0;i<5; i++)
System.out.println("i["+i+"]="+n1[i]);

//Calcular máximo, total


for(int i=0;i<5; i++){
soma+=n1[i];
if (max<n1[i])
max=n1[i];
}

//Mostrar resultados
System.out.println("Total:"+soma);
System.out.println("Media:"+(float)soma/n1.length);
System.out.println("Maximo:"+max);

//Nota: na media é necessário fazer uma divisao de floats.


}

Tabela criada com 5 Depois de uma Depois de duas Depois das


elementos indexados iteração iterações cinco iterações
de 0 a 4 do ciclo do ciclo do ciclo

0 1 1 1

1 3 3

2 10

11
3

4 2

índices

Figura 47. Criação e preenchimento da tabela do exemplo 2.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 95


Sebenta da Disciplina de Introdução à Programação

Atenção : acesso a elementos não existentes da tabela

Considere o exemplo 2, do ponto 1.2.4, no qual é criado e preenchido um array de cinco elementos. Caso se tentasse
aceder a um elemento inexistente, durante a execução do programa seria detectado um erro:

n1 [5] = 4; //acesso a um índice que não existe

O erro detectado seria:

Java.lang.ArrayIndexOutOfBoundsException:19
At Teste.main(Test.java)

6.3 - Tabelas de Objectos


As tabelas de objectos não são mais do que tabelas em que cada elemento é uma referência a um objecto de uma
determinada classe. Todas as tabelas de objectos são inicializadas a null.

Na sequência da classe Aluno, imaginemos que se pretendia gerir uma turma de alunos, com funcionalidades como
inserir, listar, procurar e apagar alunos. A solução seria criar uma tabela do tipo Aluno.

Aluno [] tabelaAlunos ;

Uma vez que se pretende gerir uma turma de alunos, deve-se criar uma classe Turma, que como atributo terá a tabela
de alunos:

public class Turma


{
private Aluno [ ] tabelaAlunos ;

private int numAlunos; // número de alunos inscritos na turma

private final static int MAXIMO_ALUNOS=20; //Lotação máxima


}

Quando se define uma classe, deve-se implementar os construtores da mesma. No caso da classe Turma serão
definidos dois construtores.

public Turma()
{
tabelaAlunos = new Aluno[MAXIMO_ALUNOS];
numAlunos=0;
}

public Turma(int max)


{
tabelaAlunos = new Aluno[max];
numAlunos=0;
}

No primeiro construtor, define-se que a tabela de alunos terá como dimensão o valor da constante
MAXIMO_ALUNOS. No segundo construtor a dimensão da tabela de alunos será passada por argumento. Em ambos
os construtores a variável numAlunos é inicializada a zero por não existirem alunos inscritos no início.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 96


Sebenta da Disciplina de Introdução à Programação

A funcionalidade inserir aluno na turma pode ser implementada da seguinte forma:

public boolean insereAluno(Aluno a1)


{
if(tabelaAlunos.length>numAlunos) // testa se a tabela não
está cheia
{
tabelaAlunos[numAlunos]=a1; // insere na tabela
numAlunos++; // incrementa a variável num
return true;
}
return false;

Outra forma de implementar este método sem a passagem de um objecto do tipo Aluno seria:

public boolean insereAluno(String nome, int num, String curso,


int ano, char turma)

{
if(tabelaAlunos.length>numAlunos)
{
Aluno aluno = new Aluno(nome, num,curso, ano, turma);
//inserir na tabela
tabelaAlunos[numAlunos++]=aluno;
return true;
}
return false;
}

Outra das funcionalidades requeridas é listar a informação contida na tabela, ou seja, lista os alunos inscritos na
turma:

public String listar( )


{
String str="";
for(inti=0;i<tabelaAlunos.length && tabelaAlunos[i]!=null;i++)
str= str+ i + " "+ tabelaAlunos[i].toString();
return str;
}

É de notar que quando se está a correr uma tabela de objectos, é necessário verificar se a posição corrente tem ou
não conteúdo. tabelaAlunos[i]!=null é a expressão que verifica se a posição i da tabela de alunos é
diferente de null.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 97


Sebenta da Disciplina de Introdução à Programação

Outra alternativa a este método:

public String listar( )


{
String str="";
for(inti=0;i<numAlunos;i++)
str= str+ i + " "+ tabelaAlunos[i].toString();
return str;
}

Procurar um aluno na tabela, poderá ter duas implementações:


• Procura pelo numero de aluno
• Procura por nome de aluno

public Aluno procuraAluno(int num )


{
for(int i=0;i<tabelaAlunos.length && tabelaAlunos[i]!=null;i++)
// verifica se o aluno na posição i tem o numero igual a num

if(this.tabelaAlunos[i].getNumero()==num)
return tabelaAlunos[i];
return null;
}

Na procura por número de aluno tem que se percorrer a tabela e para cada posição da mesma verificar se o número
do aluno é igual ao num passado no argumento do método. Como num é do tipo primitivo inteiro usa-se o operador
==.

public Aluno procuraAluno(String nome )


{

for(int i=0;i<tabelaAlunos.length && tabelaAlunos[i]!=null;i++)

// verifica se o aluno na posição i tem o nome igual a nome


if(this.tabelaAlunos[i].getNome().equals(nome))
return tabelaAlunos[i];
return null;
}

Na procura por nome de aluno tem que se percorrer a tabela e para cada posição da mesma verificar se o nomedo
aluno é igual ao nome passado no argumento do método. Como estamos perante variáveis do tipo String usa-se o
método equals.
str1.equals(str2) verifica se a str1 1 é igual à str2.

A funcionalidade de apagar aluno é mais complexa de implementar. O algoritmo deste método é dividido em duas
partes:

• Procura o índice da tabela onde se encontra o objecto a apagar.


• Reconstrói a tabela a partir do índice encontrado.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 98


Sebenta da Disciplina de Introdução à Programação

public boolean apagarAluno(int num )


{

boolean flag=true;
int i,j;
for(i=0;i<numAlunos && flag;i++)
if(tabelaAlunos[i].getNumero()==num)
{
flag =false;
}
if( flag)
return false;
else
{
for(j=i-1; j<numAlunos-1;j++)
tabelaAlunos[j]=tabelaAlunos[j+1];
tabelaAlunos[j]=null;
}
return true;
}

Para testar o funcionamento dos métodos pode-se utilizar a seguinte classe com o método main:

public class Principal {


public static void main(String[] args) {

Turma tEIA= new Turma(15);


Aluno aluno2 = new Aluno("João", 2133,"EI", 1, 'A');

System.out.println(tEIA.listar());
tEIA.insereAluno(aluno2);
System.out.println(tEIA.listar());

tEIA.insereAluno("Ana", 2131,"EI", 1, 'A');


tEIA.insereAluno("Pedro", 2137,"EI", 1, 'A');
tEIA.insereAluno("Vitor", 2138,"EI", 1, 'A');
System.out.println(tEIA.listar());

Aluno a1= tEIA.procuraAluno(2133);


System.out.println(a1);

tEIA.apagarAluno(2133);
System.out.println(tEIA.listar());
tEIA.apagarAluno(2131);
System.out.println(tEIA.listar());
tEIA.apagarAluno(2138);
System.out.println(tEIA.listar());
}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 99


Sebenta da Disciplina de Introdução à Programação

O Output seria:

tabelaAlunos [0]= Nome:João Numero :2133 curso : EI Ano1

tabelaAlunos [0]= Nome:João Numero :2133 curso : EI Ano1


tabelaAlunos [1]= Nome:Ana Numero :2131 curso : EI Ano1
tabelaAlunos [2]= Nome:Pedro Numero :2137 curso : EI Ano1
tabelaAlunos [3]= Nome:Vitor Numero :2138 curso : EI Ano1

Nome:João Numero :2133 curso : EI Ano1

tabelaAlunos [0]= Nome:Ana Numero :2131 curso : EI Ano1


tabelaAlunos [1]= Nome:Pedro Numero :2137 curso : EI Ano1
tabelaAlunos [2]= Nome:Vitor Numero :2138 curso : EI Ano1

tabelaAlunos [0]= Nome:Pedro Numero :2137 curso : EI Ano1


tabelaAlunos [1]= Nome:Vitor Numero :2138 curso : EI Ano1

tabelaAlunos [0]= Nome:Pedro Numero :2137 curso : EI Ano1

Em seguida serão apresentados mais exemplos sobre tabelas de objectos.

Exemplos:

Tabela de Strings

No exemplo em seguida apresentado é declarada uma tabela de Strings que não é mais do que uma tabela em que
cada elemento da tabela é uma referência a uma String.

final int NUM_NOMES = 5;

// Declaração e instanciação
String[] nome = new String [NUM_NOMES ] ;

// Inicialização ou Atribuição
nome[0] = "Smith";
nome[1] = "Jones";
nome[2] = "Miller";
nome[3] = "Luis";
nome[4] = "Gonzales";

// Saída
System.out.println ("Resultado:");
for (int indice = 0; indice < nome.length; indice ++)
System.out.println (“nome[“ + indice + "]: " + nome[indice]);

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 100


Sebenta da Disciplina de Introdução à Programação

Tabela de Objectos da classe pessoa

O código da classe pessoa, apresenta-se em seguida:

class Pessoa
{
String nome;
int idade;
String BI;

public Pessoa (String pfN, String pfC, int pfI)


{
nome = pfN;
BI = pfC;
idade = pfI;
}

public void apresentar()


{
System.out.println(“Meu nome é ” + nome);
System.out.println(“Tenho ”+ idade + “anos”);
}

public String getBI()


{
return BI;
}

public String toString()


{
return (“nome=“+nome+”com “+idade+”anos”);
}
}

A classe seguinte testa a utilização da classe pessoa.

public class Teste


{
public static void main (String args[])
{
Pessoa Pedro;
Pessoa Nuno;
Pedro = new Pessoa(“Pedro Martins”,“403.234.567”, 34);
Nuno = Pedro;
Pedro.apresentar();
Nuno.apresentar();
System.out.println(“O BI de Pedro e “+Pedro.getBI());
}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 101


Sebenta da Disciplina de Introdução à Programação

Em seguida apresenta-se o código onde se cria uma tabela de objectos da classe pessoa, que é uma tabela em que
cada elemento é uma referência a um objecto da classe pessoa.

public class TabelaDeObjectos


{
public static void main(String[] args)
{
//Declaração e Instanciação da tabela
Pessoa[ ] grupo = new Pessoa [4];

//Inicialização dos elementos da tabela (Atribuição)


grupo[0] = new Pessoa("Pedro Sousa", "403234567",34);
grupo[1] = new Pessoa("António Pereira", "233544325",37);
grupo[2] = new Pessoa("João Silva", "763234567",40);
grupo[3] = new Pessoa("Joaquim Feliz", "213456567",20);

//Saída
System.out.println("Conteúdos de cada elemento da tabela:");
for (int pessoa = 0; pessoa < 4; pessoa ++)
System.out.println((pessoa + 1) + "ª Pessoa do Grupo: " +
grupo[pessoa].toString );
}
}

grupo[0] grupo[1] grupo[2] grupo[3]

Pedro António João Silva Joaquim


Sousa Pereira Feliz

Figura 48. Exemplo gráfico dos resultados obtidos com o código anterior

Tabela dinâmica

No exemplo apresentado em seguida será criada uma tabela dinâmica, lida uma lista de números inteiros terminada
por 0 e depois com os valores lildos calculada a média e o valor máximo.

import Le;

public static void main(String args[])


{
//Declaração de uma tabela de inteiros com
// dimensão ainda indefinida

int tab[ ]={};

int soma=0;
int max=0;
int i=1;

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 102


Sebenta da Disciplina de Introdução à Programação

//Ler 1º valor
System.out.print(“Insira o 1º inteiro:> ”);
int n = scanTeclado.nextInt();
while (n!=0)
{
//criar tabela temporária
int tabTemp[]=new int[tab.length+1];

//copiar valores
for(int j=0;j<tab.length;j++)
tabTemp[j]=tab[j];

//inserir novo valor


tabTemp[tabTemp.length-1]=n;

//colocar a tabela temporária na definitiva


tab = tabTemp;

System.out.print(“Insira o ” + j + ”º inteiro:> ”);


n = scanTeclado.nextInt();
}

//Mostrar tabela
for(i=0; i<tab.length; i++)
System.out.println(“tab[“ + i + "]="+ tab[i]);

//Calcular o valor máximo e a soma total


for(i=0; i<tab.length; i++)
{
soma+ = tab[i];
if (max < tab[i])
max = tab[i];
}

//Mostrar resultados
System.out.println("Total:"+soma);

//Nota: na media é necessário fazer uma divisao de floats.

System.out.println("Media:"+(float)soma/n1.length);
System.out.println("Maximo:"+max);

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 103


Sebenta da Disciplina de Introdução à Programação

Lista Telefónica

No exemplo seguinte pretende-se criar uma lista telefónica. Para tal, cria-se a classe Contacto, cujos atributos são o
nome e o telefone da pessoa:

public class Contacto {

//Atributos
String nome;
int telefone;

//Construtores
public Contacto(String nomeContacto, int telefoneContacto)
{
nome=nomeContacto;
telefone=telefoneContacto;
}

//Métodos
public String mostrarContacto()
{
return nome + " - " + telefone;
}

public int obterTelefone()


{
return telefone;
}

public String obterNome()


{
return nome;
}

Em seguida veremos a classe Lista telefónica na qual é manipulado uma tabela de objectos do tipo Contacto:

public class ListaTelefonica {

//Atributos
private static final int MAXCONTACTOS= 20;
private Contacto contactos [];
private int nContactos=0;

//Construtores

public ListaTelefonica(){
contactos = new Contacto[MAXCONTACTOS];
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 104


Sebenta da Disciplina de Introdução à Programação

//Métodos
public void adicionar()
{
String nome;
int telefone;
System.out.println("Introduza o nome:");
nome= scanTeclado.next();
System.out.println("Introduza o telefone:");
telefone= scanTeclado.nextInt();
Contacto c = new Contacto(nome,telefone);
contactos[nContactos]=c;
nContactos++;
}

public void mostrar(){


for ( int i=0; i<nContactos; i++)
System.out.println(contactos[i].mostrarContacto());
}

public void procurar(){


System.out.println("Qual o telefone:");
int telefone= scanTeclado.nextInt();
int i=0;
while(i<nContactos && contactos[i].obterTelefone()!=telefone)
i++;
if (i!=nContactos)
System.out.println(contactos[i].mostrarContacto());
else
System.out.println("O número não se encontra na lista.");
}

public void ordenar(){


quickSort(0, nContactos-1);
}

private void quickSort( int pri, int ult)


{
int i = pri;
int j = ult;
if (pri > ult)
return;
String pivot = contactos[(pri + ult)/2].obterNome();
do
{
while
(contactos[i].obterNome().compareToIgnoreCase(pivot) < 0)
i++;
while
(contactos[j].obterNome().compareToIgnoreCase(pivot) > 0)
j--;

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 105


Sebenta da Disciplina de Introdução à Programação

if (i <= j)
trocaContactos(i++, j--);
}
while (i <= j) ;
quickSort(pri, j);
quickSort(i, ult);
}

private void trocaContactos(int i, int j){


Contacto tmp = contactos[i];
contactos[i] = contactos[j];
contactos[j] = tmp;
}
}

public class ExemploListaTelefonica {

public static void main(String[] args)


{
ListaTelefonica listaTel = new ListaTelefonica();

int seleccao;
do
{
System.out.println("Organizer");
System.out.println("");
System.out.println("1 - Adicionar");
System.out.println("2 - Mostrar");
System.out.println("3 - Procurar");
System.out.println("4 - Ordenar");
System.out.println("5 - Sair");
System.out.println("_______________________");
System.out.println("Qual a sua escolha?");
seleccao = scanTeclado.nextInt();

switch(seleccao){
case 1:
listaTel.adicionar();
break;
case 2:
listaTel.mostrar();
break;
case 3:
listaTel.procurar();
break;
case 4:
listaTel.ordenar();
break;
case 5:

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 106


Sebenta da Disciplina de Introdução à Programação

System.out.println("Adeus.");
break;
default:
System.out.println("Opção errada. Tente de Novo.");
break;
}
}
while(seleccao != 5);
}
}

6.4 - Passagem de tabelas como parâmetros de métodos


Uma tabela pode ser passada como parâmetro a um método. O que é passado como parâmetro (por valor) é a
referência da tabela, o que significa a alteraração de um elemento da tabela dentro do método, altera a tabela original.

Também é possível passar como parâmetro um elemento de uma tabela, desde que se sigam as regras referentes ao
seu tipo.

É possível passar como parâmetro um elemento de uma tabela, desde que se sigam as regras referentes ao seu tipo.

Exemplo:

public class programa {

public static void main(String args[]) {


int [] array = new int[2];

array[0]=12;
array[1]=10;

for(int i=0;i<array.length;i++)
System.out.println(array[i]);

metodo_1(array);

for(int i=0;i<array.length;i++)
System.out.println(array[i]);

metodo_2(array[1]);

for(int i=0;i<array.length;i++)
System.out.println(array[i]);
}

public static void metodo_1(int [] varray) {


for(int i=0;i<array.length;i++)
array[i]=array[i]+1;
}

public static void metodo_2(int var) {

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 107


Sebenta da Disciplina de Introdução à Programação

System.out.println(“O valor recebido é :”+var);


}
}

O output do código atrás apresentado, à luz dos conceitos introduzidos é:


12
10
13
11
O valor recebido é 11.
13
11

6.5 - Tabela Multidimensional


Uma tabela uni-dimensional representa uma lista de valores enquanto que uma tabela multidimensional representa
uma matriz, com linhas e colunas.

Cada elemento de uma tabela multidimensional é referenciado usando dois índices.


Em Java, uma tabela multidimensional é uma tabela de tabelas, ou seja é uma tabela uni-dimensional em que cada
elemento é uma referência para um objecto do tipo tabela.

Declaração:

<tipo> [ ] [ ] <variável>

Exemplo

int [ ] [ ] tab;

O código acima declara tab como uma tabela bidimensional de inteiros ou como uma tabela de tabelas, em que
apenas se cria uma referência.

A inicialização é que cria a tabela com os comprimentos respectivos:

1) tab = new int [2] [3];


ou
2) tab [][]={1,2,3} {4,5,6};

tab tab[0][0] tab[0][2]

tab[0] 1 2 3

tab[1] 4 5 6

tab[1][2]

Para percorrer a tabela usam-se ciclos for encadeados.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 108


Sebenta da Disciplina de Introdução à Programação

Exemplo

public class Matriz {

public static void main(string args[]) {

int tab[][] = {{ 1, 2, 3 }, { 4, 5, 6 }};

for(int i = 0; i < tab.length; i++)


for(int j = 0; j < tab[i].length; j++)
System.out.print("tab[" + i + "][" + j + "] = " +
tab[i][j]);
}
}

O Java é uma linguagem fortemente tipada, sendo portanto o número de dimensões da matriz e o tipo dos elementos
são definidos. O número de elementos em cada dimensão pode variar e o conteúdo dos elementos de uma tabela
pode ser de quaisquer objectos ou tipos primitivos.

Exemplo

O exemplo seguinte mostra uma matriz 3D de vectores de comprimento variado.

public class Ex {

public static void main(string args[]) {

Random gerador = new Random();


Integer a3[][][] = new Integer[gerador.nextInt(7)][][];

for(int i = 0; i < a3.length; i++)


{
a3[i] = new Integer[gerador.nextInt(7)][];

for(int j = 0; j < a3[i].length; j++)


{
a3[i][j] = new Integer[gerador.nextInt(5)];
for(int k = 0; k < a3[i][j].length; k++)
a3[i][j][k] = new Integer(i*j+k);
}
}

for(int i = 0; i < a3.length; i++)


for(int j = 0; j < a3[i].length; j++)
for(int k = 0; k < a3[i][j].length; k++)
System.out.print("a3["+i+"]["+j+"]["+k+"] = " + a3[i][j][k]);
}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 109


Sebenta da Disciplina de Introdução à Programação

6.6 - Classe Vector


6.6.1 - Introdução
A classe Vector faz parte do package java.util e funciona de forma idêntica a uma tabela, permitindo a
armazenamento de valores e a referência a estes através de um índice. A grande diferença entre uma tabela e um
objecto do tipo Vector é que este pode crescer e diminuir dinamicamente em tamanho, enquanto que uma tabela
tem sempre um tamanho fixo.

Outra diferença consiste no facto de um objecto do tipo vector não ser declarado para guardar um tipo de valor. Um
objecto do tipo Vector gere uma lista de referências para a classe Object, permitindo assim guardar qualquer
tipo de valor.

6.6.2 - Alguns métodos da classe Vector


Método Descrição
Vector ( ) Cria um vector vazio
void addElement (Object obj) Adiciona o objecto especificado ao fim
do vector
void insertelementAt (Object obj, int index) Adiciona o elemento no índice
especificado
Object remove ( int index) Remove um objecto do índice
especificado e retorna-o
boolean removeElement (Object obj) Remove a primeira ocorrência do
objecto especificado.
void removeElementAt(int index) Remove um objecto do índice
especificado
void clear ( ) Remove todos os elementos do vector
boolean contains (Object obj) Retorna true se o objecto está no vector
int indexOf (Object obj) Retorna o índice do objecto
especificado. Retorna -1 caso o objecto
não exista.
Object elementAt (int index) Retorna o Objecto no indice
especificado
boolean isEmpty ( ) Retorna true se o vector estiver vazio
int size ( ) Retorna o número de elementos do
vector

Nota:
Para mais informações sobre os métodos disponibilizados por esta classe, consultar a documentação do Java.

Exemplo

Neste exemplo será criado um objecto da classe Vector que armazenará nomes. Serão depois aplicadas algumas
operações ao vector, como inserir, remover, verificar que elemento está num determinado índice.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 110


Sebenta da Disciplina de Introdução à Programação

public class Nomes {

public static void main ( String [] args)


{
Vector nomes = new Vector( );

nomes.addElement(“Ricardo”);
nomes.addElement(“João”);
nomes.addElement(“Nuno”);
nomes.addElement(“Daniel”);

System.out.println(nomes);

nomes.removeElement(“João”);

System.out.println(nomes);
System.out.println(“No índice 1: “ + nomes.elementAt(1));

nomes.insertAt(“Carlos”,2);

System.out.println(“Tamanho do vector “ + nomes.size());


}
}
Resultado de saída do exemplo

Ricardo, João, Nuno, Daniel


Ricardo, Nuno, Daniel
No índice 1: Nuno
Tamanho do vector 4

6.7 - Exercícios Práticos


Exerc.1 – Escreva um programa que preencha uma tabela com os valores inteiros gerados aleatoriamente e imprima
todos os valores da tabela. Acrescente depois as seguintes funcionalidades ao seu programa:
• Indicar quantos valores negativos estão guardados na tabela
• Imprimir os valores positivos da tabela
• Indicar o maior valor da tabela
• Substituir todos os valores divisíveis por 3 pelo valor zero
• Indicar a posição do menor valor da tabela

Exerc.2 - Implemente um método que retorna o produto dos elementos de uma tabela.
A assinatura do método é a que se segue:

static double produto(int [ ] x)

Exerc.3 - Implemente um método que retorna o menor valor de uma tabela.


A assinatura do método é a que se segue:

static double menorValor(double [ ] x)

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 111


Sebenta da Disciplina de Introdução à Programação

Exerc.4 - Escrever um método que, dada uma sequência de n valores inteiros, retorne a diferença entre os valores
máximo e mínimo da sequência.

Exerc.5 - Escrever um método que retire todas ocorrências de um caracter carC de uma string. A assinatura do
método é a que se segue:

static String remove(String s, char carC )

Exerc.6 - Escrever um programa que converta uma string numa tabela de caracteres.

Exerc.7 - Escrever um método que receba um número e uma tabela e devolva a posição na tabela onde este número
ocorra ou o valor -1 no caso do número não existir na tabela. A assinatura do método é a que se segue:

static int indiceValor(int [ ] tabela, int valor)

Exerc.8 - Escrever um método que inverta a ordem dos elementos de uma tabela de inteiros, passada como
parâmetro.

Exerc.9 - Escrever um método que devolva a posição da última ocorrência do valor máximo de uma tabela de valores
do tipo double.

Exerc.10 - Escrever um método que receba duas tabelas e retorne true se as tabelas são iguais.

Exerc.11 - Escrever um programa que, para um dada tabela de inteiros A, construa uma tabela P formada pelos
índices dos elementos pares de A. Exemplo: Para A = ( 1 3 6 7 8 ), o programa deve construir P = ( 3 5 ).

Exerc.12- Escrever um método (e um programa que exercite tal método) que determine se os elementos de uma
tabela encontram-se em ordem decrescente ou não.

Exerc.13 - Escrever um programa que, dada uma sequência de n valores inteiros (gerados aleatoriamente) que
representam o resultado de n lançamentos de um dado, determine o número de ocorrências de cada face na
sequência analisada.

Exerc.14 - Dada uma sequência de n números reais, fazer um programa que determine os números que compõem a
sequência e a frequência de tais números na sequência dada.

Exemplo:

n = 10
Sequência: 3.2 8.1 2.5 3.2 7.4 8.1 3.2 6.3 7.4 3.2

Saída:
Num Freq
3.2 4
8.1 2
2.5 1
7.4 2
6.3 1

Exerc.15 - Escrever um programa que determine o maior valor em uma matriz de valores inteiros com n>0 linhas e
m>0 colunas. Em seguida altere o programa anterior para indicar todas as posições da matriz em que se encontra tal
valor máximo.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 112


Sebenta da Disciplina de Introdução à Programação

Exerc.16 - Implemente um método que retorne o cálculo do produto externo entre duas matrizes. A matriz resultante
calcula-se da seguinte forma p[i][j]=x[i]*y[j], onde x e y são as tabelas de entrada.
A assinatura do método é:

static double[][] productoExterno(double[] x, double[] y)

Exerc.17 - Escrever um programa que inicialmente lê um número inteiro N. Se o valor introduzido for menor que 2
(dois) finalizar o programa. Caso contrário, cria dinamicamente uma matriz de inteiros NxN. Em seguida lê um valor
para cada posição da matriz e, no final, mostrar se a matriz possui algum valor repetido.

Exerc. 18 - Defina uma classe WebSite caracterizada pelo nome, endereço e lista de temas que se podem encontrar
no mesmo. Implemente as seguintes funcionalidades a esta classe:
• Determinação de quantos temas possui o website
• Verificar se um determinado tema existe no website
• Adicionar um tema
• Remover um tema

Elabore uma classe CatalogoWeb que implementa um arquivo sobre webSites e cujas funcionalidades são:
• Determinação do número total de websites do catálogo
• Listar os Websites que tratam um determinado tema T
• Remover um website

Exerc. 20 – Construa uma classe estática que tem como objectivo conter métodos utilitários para a manipulação de
tabelas. Esses métodos são os já criados nos exercícios 2,3,8 e 10.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 113


Sebenta da Disciplina de Introdução à Programação

7- Algoritmos de Procura/Pesquisa

7.1 - Introdução
A procura de informação é uma actividade quotidiana: procuramos números em listas telefónicas, palavras em
dicionários, etc.

Estudaremos em seguida dois métodos para procurar um elemento numa tabela:


• A procura sequencial.
• A procura binária.

A procura de informação é frequentemente executada em tabelas. Ao longo deste capítulo vamos utilizar uma tabela
preenchida. Vamos para tal fazer uso de uma classe (Tabela) que possui um método (preenche) que preenche uma
tabela, passada como parâmetro, com valores inteiros gerados aleatoriamente entre 0 e 100. O código da classe é
em seguida apresentado:

import java.util.Random;

class Tabela {

public static void preenche(int tabela[]){


Random random = new Random();

for (int i=0; i < tabela.length; i++)


tabela[i] = random.nextInt(100);

public static void imprime(int tabela[]){

for (int i=0; i < tabela.length; i++)


System.out.println(" "+i+":"+ tabela[i]+"; ");
System.out.println();
}
}

7.2 - Procura Sequencial


7.2.1 - Simples
Uma forma simples de procurar consiste em:
• Começar no inicio da tabela.
• Comparar sucessivamente o elemento procurado com o elemento da tabela.
• Repetir o processo até encontrar o elemento ou atingir o fim da tabela.
Como a tabela é percorrida sequencialmente, o algoritmo é denominado por procura sequencial.

No exemplo seguinte pretende-se saber qual a posição que o valor 75 (se existir) ocupa na tabela de números.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 114


Sebenta da Disciplina de Introdução à Programação

0 1 2 3 4 5 Índice

10 20 75 9 4 3

Posição 0
Compara-se 75 com 10 → São diferentes
Incremento a posição
Posição 1
Compara-se 75 com 20 → São diferentes
Incremento a posição
Posição 2
Compara-se 75 com 75 → São iguais
Parar a procura

O valor procurado é achado e ocupa a terceira posição da tabela.

O próximo exemplo utiliza um programa que preenche uma tabela com números gerados aleatoriamente (entre 0 e
100) e permite, em seguida, procurar números que foram inseridos.

public class ProcuraSequencial{

public static int procura (int tab[], int valor) {


int i = 0;

while (i < tab.length && tab[i] != valor )


i++;

if ( i != tab.length)
return(i); // retorna indice;
else
return(-1);
}

public static void main(String[] args){

int tabela[] = new int[100];

Tabela.preenche(tabela);

System.out.println("Resultado:"+procura(tabela,67);
System.out.println("Resultado:"+procura(tabela,33));
System.out.println("Resultado:"+procura(tabela,1));
System.out.println("Resultado:"+procura(tabela,101));
}
}

O método procura retorna o índice do valor na tabela se encontrar o valor, caso contrário retorna -1. Note-se que no
ciclo correspondente à procura propriamente dita,

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 115


Sebenta da Disciplina de Introdução à Programação

while (i < tab.length && tab[ i ] != valor ) {

tem de se efectuar continuamente dois testes:


• verificar se o valor desejado foi encontrado e
• verificar se o fim da tabela foi atingido.

Embora a primeira verificação seja essencial a segunda seria desnecessária se pudesse garantir que o valor a
procurar se encontrava na tabela.

7.2.2 - Com Sentinela


Uma técnica utilizada para prescindir do segundo teste consiste em utilizar um denominado valor sentinela. Um valor
sentinela é um valor especial que inserimos na tabela para garantir que a procura tem sucesso. Neste caso trata-se de
inserir o valor procurado a seguir ao último elemento da tabela.

A utilização de um valor sentinela exige a existência de uma posição adicional na tabela para armazenar o valor
sentinela. A primeira operação a efectuar, ainda antes da procura, é a inserção do valor sentinela no final da tabela.
Se no fim da procura o valor encontrado for o sentinela, então o valor procurado não existe na tabela.

No exemplo seguinte procede-se a implementação da procura sequencial com sentinela, utilizando um programa que
preenche uma tabela com números gerados aleatoriamente (entre 0 e 100) e permite, em seguida, procurar números
que foram inseridos.

public class ProcuraSequencialSentinela {

public static int procura(int tab[], int valor){


int i = 0;

tab[tab.length-1] = valor; //SENTINELA

while (tab[ i ] != valor )


i++;

if ( i != tab.length-1)
return(i);
else
return(-1);
}

public static void main(String[] args){

int tab[] = new int[101];

Tabela.preenche(tabela);

System.out.println("Resultado:"+procura(tab,67));
System.out.println("Resultado:"+procura(tab,33));
System.out.println("Resultado:"+procura(tab,1));
System.out.println("Resultado:"+procura(tab,102);
}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 116


Sebenta da Disciplina de Introdução à Programação

7.3 - Procura Binária


A procura sequencial é muito simples, mas pode exigir a inspecção de todos os elementos da tabela. Isto acontece
sempre que o elemento que estamos a procurar não se encontra na tabela.

A procura binária é uma alternativa mais eficaz, mas exige que os elementos sobre os quais a procura está a ser
efectuada se encontrem ordenados.

O algoritmo é o seguinte:

1. Encontramos o meio da tabela.


2. Consideramos último o elemento da 1ª metade da tabela.
3. Se o elemento procurado é menor do que o último o elemento da 1ª metade da tabela, podemos garantir
que o procurado não se encontra na 2ª metade da tabela.
4. Repetimos então processo para a 1ª metade da tabela.
5. Se o elemento procurado é maior do que o último o elemento da 1ª metade da tabela, podemos garantir que
o procurado não se encontra na 1ª metade da tabela.
6. Repetimos então o processo para a 2ª metade da tabela.
7. Se o elemento no meio da tabela for igual ao procurado a procura termina.
8. Note-se que em cada passo a procura binária reduz o número de elementos a considerar para metade

O próximo exemplo utiliza um programa que lê 100 números e permite, em seguida, procurar os números que foram
inseridos.

public class ProcuraBinaria {

public static int procuraBinaria(int tab[], int valor) {


boolean achou = false;

int alto = tab.length - 1;


int baixo = 0;
int meio = alto/2;

while (!achou && alto >= baixo )


{
if (valor == tab[meio ])
achou = true;
else if (valor < tab[meio ])
alto = meio - 1;
else
baixo = meio + 1;

meio = (alto + baixo )/2;


}

return((achou ) ? meio : -1);

public static void main(String[] args) {


int tabela[] = new int[100

for (int i=0; i < tabela.length; i++)


tabela[i] = i;

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 117


Sebenta da Disciplina de Introdução à Programação

System.out.println("Resultado:"+procuraBinaria (tabela,67));
System.out.println("Resultado:"+procuraBinaria (tabela,33));
System.out.println("Resultado:"+procuraBinaria (tabela,1));
System.out.println("Resultado:"+procuraBinaria (tabela,101));
}
}

Exemplo (Pesquisa de um valor inexistente na tabela)

baixo
x: 2
1ª iteração v: 1 3 3 5 7 8 9
(>x)
baixo meio alto
Valor a Procurar

2ª iteração 1 3 3 5 7 8 9
(>x)
baixo meio alto

3ª iteração 1 3 3 5 7 8 9
(<x)
baixo alto

4ª iteração 1 3 3 5 7 8 9

O valor 2 não existe na tabela

Figura 49. Pesquisa binária de um valor inexistente na tabela.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 118


Sebenta da Disciplina de Introdução à Programação

public static int procuraBinaria (int tab[], int valor)


{
boolean achou = false;
int alto = tab.length - 1;
int baixo = 0;
int meio = alto/2;

while (!achou && alto >= baixo ){


if (valor == tab[meio ])
achou = true;
else if (valor < tab[meio ])
alto = meio - 1;
else
baixo = meio + 1;

meio = (alto + baixo )/2;


}
return((achou ) ? meio : -1);

Exemplo (Pesquisa de um valor existente na tabela)

baixo meio alto


x: 1
1ª iteração v: 1 3 3 5 7 8 9
(>x)
baixo meio alto
Valor a Procurar

2ª iteração 1 3 3 5 7 8 9
(>x)

baixo meio alto

3ª iteração 1 3 3 5 7 8 9
(<x)
O valor 1 existe na tabela

Figura 50. Pesquisa binária de um valor existente na tabela

7.4 - Exercícios práticos


Exerc.1 - Implemente o método máximo que retorna o maior valor dos elementos da tabela x. Utilize o algoritmo de
procura sequencial.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 119


Sebenta da Disciplina de Introdução à Programação

Exerc.2 - Implemente o método mínimo que retorna o índice do elemento de menor valor da tabela tabF. A assinatura
do método é

public static int minimo(float[ ] tabF).

Exerc.3 - Implemente o método procuraCar que retorna o índice da primeira ocorrência do caracter c1 na tabela
tabCar. Utilize o método de procura binária. A assinatura do método é:

public static int procuraCar(car[ ] tabCar, car c1)

Exerc.4 - Temos uma tabela com as temperaturas médias ao longo dos dias de mês. Queremos saber para um
determinado mês:
1. Qual foi a temperatura mais baixa
2. Em que dia ocorreu a temperatura mais elevada
3. Qual foi a diferença entre a temperatura mais baixa e a temperatura mais alta.

Exerc.5 - Implemente o método procuraFloat que procura na tabela v, que tem como critério de paragem o valor de s,
se esta contem o elemento x. Caso a procura seja realizada com sucesso retorna o índice do elemento, senão retorna
–1. assinatura do método é

public static int procuraInteiro(int[] v, int x, int s)

Exerc.6 - Um sistema de controlo de presenças ligado ao sistema de marcação de ponto, mantém uma lista de todos
os trabalhadores que num determinado momento se encontram dentro da empresa. É necessário implementar um
método que dado o nome de uma pessoa, ele nos valide se esta pessoa se encontra dentro da empresa ou não.
Utilize a procura binária na implementação desta função.

Nota: a lista é terminada com a palavra “ * ‘”


A assinatura do método é:

public static boolean procuraPessoa(String[ ] v)

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 120


Sebenta da Disciplina de Introdução à Programação

8- Algoritmos de Ordenação

8.1 - Introdução
Um conjunto de elementos é normalmente ordenado para facilitar a procura. Ordenamos as coisas para facilitar a
procura e não por sermos naturalmente arrumados. Imagine que teria de procurar o número de telefone de um amigo
numa lista telefónica que não estivesse ordenada alfabeticamente. Seria caótico certamente.

Em programação, a utilização de tabelas ordenadas permite escrever algoritmos de procura mais eficientes.

Nos algoritmos de ordenação que serão em seguida introduzidos, vamos supor que pretendemos ordenar uma
sequência de inteiros com um máximo de 100 elementos.

Com o objectivo de separar algumas operações que se repetem ao longo dos exemplos de ordenação, vamos
apresentar de seguida uma classe (Tabela) que permite realizar as seguintes funções, sobre uma tabela:

• Preenchimento de uma tabela com valores inteiros, não ordenados, gerados aleatoriamente.
• Troca de elementos de uma tabela.
• Impressão dos elementos de uma tabela.

import java.util.Random;

class Tabela {

//(1) preenche uma tabela

public static void preenche(int tabela[]) {


Random random = new Random();
for (int i=0; i < tabela.length; i++)
tabela[i] = random.nextInt(100);
}

//(2) troca as posições de dois elementos da tabela

public static void troca(int tabela[], int x, int y){


int tmp;
tmp = tabela[x];
tabela[x] = tabela[y];
tabela[y] = tmp;
}

//(3) Imprime a tabela

public static void imprime(int tabela[]) {


for (int i=0; i < tabela.length; i++)
System.out.println(" "+i+": "+ tabela[i]+" ; ");
System.out.println();
}
// O método main vai variar para cada implementação
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 121


Sebenta da Disciplina de Introdução à Programação

8.2 - BubbleSort
Este algoritmo consiste em:
• Percorrer os elementos a ordenar, comparando elementos adjacentes e trocando os pares de
elementos que se encontram fora de ordem.
• Até que se tenha efectuado uma passagem completa em que não haja nenhuma troca de posições.

Note que a tabela encontra-se ordenada quando se efectua uma passagem completa em que nenhum par de
elementos trocou de posição.

De um modo geral uma única passagem pelo conjunto de elementos não ordena a tabela.

O tempo de execução é proporcional a n2, onde n é o numero de elementos a serem ordenados.

Consideremos a seguinte tabela, onde se aplicará o algoritmo BubbleSort:

0 1 2 3 4 5 Índice

4 8 17 3 11 2

Veremos a evolução da posição dos elementos ao longo das passagens e da variável trocou que permite saber se ao
longo da passagem houve trocas de posição.

Primeira passagem
trocou = false
4 8 17 3 11 2
4 8 17 3 11 2
4 8 3 17 11 2 (trocou=true)
4 8 3 11 17 2 (trocou=true)
4 8 3 11 2 17 (trocou=true)

Segunda passagem
trocou = false
4 8 3 11 2 17
4 3 8 11 2 17 (trocou=true)
4 3 8 11 2 17
4 3 8 2 11 17 (trocou=true)
4 3 8 2 11 17

Terceira passagem
trocou = false
3 4 8 2 11 17 (trocou=true)
3 4 8 2 11 17
3 4 2 8 11 17 (trocou=true)
3 4 2 8 11 17
3 4 2 8 11 17

Quarta passagem
trocou = false
3 4 2 8 11 17

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 122


Sebenta da Disciplina de Introdução à Programação

3 2 4 8 11 17 (trocou=true)
3 2 4 8 11 17
3 2 4 8 11 17
3 2 4 8 11 17

Quinta passagem
trocou = false
2 3 4 8 11 17 (trocou=true)
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17

Sexta passagem
trocou = false
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17
trocou == false – Termina!

O código da implementação do algoritmos BubbleSort é apresentado em seguida:

public class OrdenacaoBubbleSort {


public static void bubbleSort(int tabela[ ] ) {
boolean houveTroca;

do
{
houveTroca = false;
for (int j = 0; j < tabela.length-1; j++)
if (tabela[j] > tabela[j+1]){
Tabela.troca(tabela, j, j+1);
houveTroca = true;
}
}while (houveTroca);
}

public static void main(String[] args) {


int tabela[] = new int[100];

Tabela.preenche(tabela); //preenche tabela


Tabela.imprime(tabela); //imprime tabela antes da ordenação

bubbleSort(tabela); //ordena tabela

Tabela.imprime(tabela); //imprime tabela depois de ordenada


}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 123


Sebenta da Disciplina de Introdução à Programação

8.3 - ShellSort
A ordenação ShellSort é uma variante da ordenação BubbleSort e consiste em comparar e trocar, não elementos
adjacentes, mas sim elementos separados por um certo intervalo.

Como intervalo inicial considera-se metade do número de elementos a ordenar.


Após uma ordenação completa, do tipo BubbleSort, com o intervalo inicial, esse intervalo é dividido ao meio e o
processo repete-se para o novo intervalo.

Este processo repete-se até que o intervalo seja 1 (correspondente a uma ordenação por BubbleSort).

Note que a ordenação ShellSort é mais eficiente (mais rápida) do que a ordenação BubbleSort porque as primeiras
passagens consideram apenas um subconjunto dos elementos a ordenar e as últimas passagens já os encontram
parcialmente ordenados.

Consideremos a tabela que foi usada no exemplo do Bubblesort:


0 1 2 3 4 5 Índice

4 8 17 3 11 2

Vejamos a evolução da posição dos elementos ao longo das passagens, da variável trocou que permite saber se ao
longo da passagem houve trocas de posição e da variável intervalo que define a distância entre elementos
comparados.

Passagem 1
Intervalo=3
trocou=False
3 8 17 4 11 2 (trocou=true)
3 8 17 4 11 2
3 8 2 4 11 17 (trocou=true)

Passagem 2
Intervalo=3
trocou=False
3 8 2 4 11 17
3 8 2 4 11 17
3 8 2 4 11 17

Passagem 3
Intervalo=1
trocou=False
3 8 2 4 11 17
3 2 8 4 11 17 (trocou=true)
3 2 4 8 11 17 (trocou=true)
3 2 4 8 11 17
3 2 4 8 11 17

Passagem 4

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 124


Sebenta da Disciplina de Introdução à Programação

Intervalo=1
trocou=False
2 3 4 8 11 17 (trocou=true)
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17

Passagem 5
Intervalo=1
trocou=False
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17
2 3 4 8 11 17

O código da implementação do algoritmo ShellSort é apresentado em seguida:

public class OrdenacaoShell {

public static void shell (int tabela[ ] ) {


boolean nenhumaTroca;
int intervalo;
intervalo = tabela.length / 2;

do
{
do
{
nenhumaTroca = true;

for (int j = 0; j < tabela.length-intervalo; j++)


if (tabela[j] > tabela[j+intervalo]) {
Tabela.troca(tabela, j, j+intervalo);
nenhumaTroca = false;
}

}while (!nenhumaTroca);

intervalo = intervalo / 2;

}while ( intervalo > 0);


}

public static void main(String[] args){


int tabela[] = new int[100];

Tabela.preenche(tabela); //preenche tabela


Tabela.imprime(tabela); //imprime tabela antes da ordenação

shell(tabela); //ordena tabela

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 125


Sebenta da Disciplina de Introdução à Programação

Tabela.imprime(tabela); //imprime tabela depois de ordenada


}
}

8.4 - Ordenação por selecção


A ordenação por selecção consiste em percorrer os elementos a ordenar e, em cada passagem, colocar um elemento
na sua posição correcta:

o Na 1ª passagem coloca-se o menor elemento na sua posição correcta.


o Na 2ª passagem coloca-se o segundo menor.
o E assim sucessivamente.

Consideremos novamente a mesma tabela:


0 1 2 3 4 5 Índice

4 8 17 3 11 2

Vejamos a evolução da posição dos elementos ao longo das passagens:

Primeira passagem (4 8 17 3 11 2)
2 8 17 3 11 4

Segunda passagem (2 8 17 3 11 4)
2 3 17 8 11 4

Terceira passagem (2 3 17 8 11 4)
2 3 4 8 11 17

Quarta passagem (2 3 4 8 11 17)


2 3 4 8 11 17

O código da implementação do algoritmo é apresentado em seguida:

public class OrdenacaoSeleccao {

void selectionSort(int numbers[])


{
int i, j;
int min, temp;

for (i = 0; i < numbers.length-1; i++)


{
min = i;
for (j = i+1; j < numbers.length; j++)
{
if (numbers[j] < numbers[min])
min = j;
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 126


Sebenta da Disciplina de Introdução à Programação

Tabela.troca(numbers, i, min);
}
}

public static void main(String[] args) {


int tabela[] = new int[100];

Tabela.preenche(tabela); //preenche tabela


Tabela.imprime(tabela); //imprime tabela antes da ordenação

selectionSort(tabela); //ordena tabela

Tabela.imprime(tabela); //imprime tabela depois de ordenada


}
}

8.5 - Algoritmo QuickSort


É um algoritmo recursivo baseado na técnica divide and conquer!

o Escolher um elemento arbitrário (x) da tabela (chamado pivot)


o Passo de Divisão
ƒ Dividir os restantes em dois grupos (esquerdo e direito).
ƒ O grupo esquerdo é composto pelos elementos menores ou iguais que o elemento pivot.
ƒ O grupo direito é composto pelos elementos maiores que o elemento pivot.
ƒ O elemento pivot é colocado entre os dois grupos.

o Passo Recursivo
ƒ Ordenar os dois grupos esquerdo e direito, usando o mesmo método recursivamente

Relativamente ao passo da divisão:

• Seja a Tabela v com n elementos.


• Seja x o elemento pivot contido no meio da tabela (x = v[n/2]).

Poderá ser introduzido o seguinte refinamento:

• Inicializar i = 0 (índice da 1º posição da tabela).


• Inicializar j = n-1 (índice da última posição da tabela).
• Enquanto i ≤ j, fazer:
ƒ Enquanto v[i] < x (é sempre i≤ n-1), incrementar i
ƒ Enquanto v[j] > x (é sempre j≥ 0), decrementar j
ƒ Se i ≤ j, trocar v[i] com v[j], incrementar i e decrementar j

• O grupo esquerdo (com valores ≤ x) é v[0], ..., v[j]


(vazio se j<0)
• O grupo direito (com valores ≥ x) é v[i], ..., v[n-1]
(vazio se i>n-1)

O tempo de execução é proporcional a

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 127


Sebenta da Disciplina de Introdução à Programação

n * log n

onde n é o numero de elementos a serem ordenados.

A ideia “de aceleração” por trás do algoritmo QuickSort é que é mais rápido ordenar duas sequências de n/2
elementos do que uma sequência de n elementos.

Veremos em seguida um exemplo do passo da divisão.

i x=4 j
v: 8 9 2 5 4 6 1 3 7
(3.1+3.2)
i j
8 9 2 5 4 6 1 3 7

(3.3) i j
3 9 2 5 4 6 1 8 7

(3.3) j
i
3 1 2 5 4 6 9 8 7

(3.1+3.2) i j
3 1 2 5 4 6 9 8 7

(3.3) j i
3 1 2 4 5 6< 9 8 7
≤x ≥x
Figura 51. Passo da divisão

O código da implementação do algoritmo é apresentado em seguida:

public static void main(String[] args) {


int tabela[] = new int[100];

Tabela.preenche(tabela); //preenche tabela

Tabela.imprime(tabela); //imprime tabela antes da ordenação

quickSort(tabela, 0, tabela.length-1); //ordena tabela

Tabela.imprime(tabela); //imprime tabela depois de ordenada


}

static void quickSort (int tabela[], int pri, int ult)


{
int i = pri;
int j = ult;

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 128


Sebenta da Disciplina de Introdução à Programação

int pivot = tabela[(pri + ult)/2];


do
{
while (tabela[i] < pivot)
i++;
while (tabela[j] > pivot)
j--;
if (i<= j) Tabela.troca(tabela,i++,j--);

}while(i <= j);

if (pri < j) quickSort(tabela, pri, j);


if (i < ult) quickSort(tabela, i, ult);
}

8.6 - Exercícios práticos


Exerc.1 - Implemente um método que receba como parâmetro uma tabela de inteiros e retorne a tabela ordenada
usando o algoritmo Bubble Sort

Exerc.2 - Implemente um método que receba como parâmetro uma tabela de inteiros e retorne uma outra tabela
ordenada. Use o algoritmo Selection Sort.

Exerc.3 - Faça um método que receba como parâmetro uma tabela de objectos do tipo funcionário (nome e número
fiscal) e retorne uma tabela ordenada. Use o algoritmo Shell Sort

Exerc.4 - Implemente um programa que dado uma tabela de caracteres a ordene o algoritmo Selection Sort.

Exerc.5 - Implemente um programa que:


1. receba o registo de automóveis (Marca e n.º registo)
2. guarde estes registos numa tabela
3. Ordene a tabela por marca, segundo o método quick Sort.
4. Apresente em seguida o resultado no ecran.

Exerc.6 - Uma loja pretende dispor os seus artigos de vestuário segundo cores. Para isso precisa de fazer uma
pequena alteração à aplicação de suporte à gestão da loja, de modo a acrescentar a funcionalidade de listagem de
artigos por ordem de cor, sendo a ordem de cores desejada (amarelo, laranja, castanho, beje, verde, azul, vermelho,
cinzento e preto).
Implemente o método que permite reordenar a tabela de objectos ArtigoVestuario segundo a ordem de cores desejada

public class ArtigoVestuario {


public int cod;
public String artigo, cor;

}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 129


Sebenta da Disciplina de Introdução à Programação

9- Recursividade

9.1 - Definições
A repetição de execução de um grupo de instruções para diferentes valores de dados pode ser implementada de duas
formas:
• Iterativa (ou explícita).
• Recursiva (ou implícita). Quando um método está definido em termos dele próprio.

Por exemplo, vejamos o cálculo do factorial de um número natural. Este pode ser feito de duas formas:

• Forma iterativa
n! = n*(n-1)*(n-2)*…*1

• Forma recursiva (definindo-se uma forma recursiva da função)


1!=1
n! = n*(n-1)!

Um método recursivo é um método que directa ou indirectamente faz uma chamada a si mesmo (recorre a si próprio
para resolver o problema).
Como um método F resolve um problema chamando a si mesmo? O F chama a si em diferentes instâncias, com os
valores diferentes.
Exemplos:
• Examinar todos os arquivos de um directório D, incluindo todos os sub-directórios;
• Procurar o significado de uma palavra num dicionário;
• Definição de uma expressão aritmética numa linguagem de programação.

O uso da recursão é útil na resolução de problemas que podem ser decompostos em subprogramas mais simples e
onde a solução final obtém-se pela composição das soluções desses subproblemas.

Um método recursivo é definido em termos de uma instância menor de si mesmo.


Devem existir duas condições fundamentais para implementar a recursividade:

• Um caso elementar (ou critério de paragem). No mínimo, sempre tem que haver um caso que pode ser
resolvido sem recursividade.
No exemplo do cálculo do factorial este critério é dado por 1!=1.

• O caso geral, ou parte recursiva. Qualquer chamada recursiva tem que progredir em direcção ao caso
elementar.
No exemplo do cálculo do factorial este caso é n!=n*(n-1)!

A recursividade é muito usada, por exemplo, no cálculo de problemas matemáticos, contudo a recursividade pode
causar problemas de memória em virtude da duplicação de variáveis locais, incluindo os parâmetros.
Também devemos ter cuidado para não criar uma lógica circular que resulte em laços infinitos.

Recursividade é uma poderosa ferramenta de programação que pode levar a algoritmos pequenos e eficientes.
Recursividade, sempre leva a um código mais compacto.

Exemplos:

No exemplo seguinte será apresentado o cálculo do factorial de um número natural através da forma iteractiva e
recursiva.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 130


Sebenta da Disciplina de Introdução à Programação

Iterativa

public class FacInt {

public static void main(String[] args)


{
for (int i = 0; i < 9; i++)
System.out.println("f(" + i + ") = " + factorial(i));
}

static long factorial(int n)


{
long f = 1;
while (n > 1)
f *= n--;
return f;
}
}

/*
Output:

f(0) = 1
f(1) = 1
f(2) = 2
f(3) = 6
f(4) = 24
f(5) = 120
f(6) = 720
f(7) = 5040
f(8) = 40320
*/

Recursiva

public class TestFactorialRec

{ public static void main(String[] args)


{
for (int i = 0; i < 9; i++)
System.out.println("f(" + i + ") = " + fact(i));
}

static long fact(int n)


{
if (n < 2) return 1;
return n*fact(n-1);
}
}

/*

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 131


Sebenta da Disciplina de Introdução à Programação

Output:

f(0) = 1
f(1) = 1
f(2) = 2
f(3) = 6
f(4) = 24
f(5) = 120
f(6) = 720
f(7) = 5040
f(8) = 40320
*/

Veja-se para este último caso o rasto do cálculo do factorial

f(3) = 3 * f(2) = 6
|
2 * f(1) = 2
|
1*1=1

Para finalizar, repare-se que:


• Numa implementação iterativa o ciclo está presente explicitamente como estrutura de repetição.
• Numa implementação recursiva o ciclo está presente, mas mascarado por uma estrutura de selecção.

9.2 - Exercícios práticos


Exerc.1 – Escreva um algoritmo recursivo e respectivo método, que permita obter o resultado de A*B sendo A e B
inteiros não negativos.
Nota:
a*b = a if b=1
a*b =a*(b-1)+a

Exerc.2 – Escreva um algoritmo recursivo e respectivo método, que permita obter o resultado de A+B sendo A e B
inteiros não negativos.
Nota:
a+b = a if b=0
a+b =(a+1) + (b-1)

Exerc.3 – A sequência de Fibonacci é definida como: 1, 1, 2, 3, 5, 8, 13, 21, 34, ... Em que cada elemento desta
sequência é a soma dos dois elementos precedentes:
Nota:
Se n <= 2 então Fib(n) := 1;
Se n > 2 então Fib(n) : = Fib(n-2)+ Fib(n-1);
Em que Fib(n) retorna o n-ésimo termo da sequência.

Faça um programa que calcule o número da sequência de Fibonacci:


ƒ Iterativamente
ƒ Recursivamente

Exerc.4 - Faça um método recursivo que calcule o valor de S, onde S = 1 + ½ + 1/3 + ¼ + 1/5 + 1/N.

Exerc.5 - Escreva um método recursivo que calcula e retorna o valor de S(n), onde

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 132


Sebenta da Disciplina de Introdução à Programação

S = 1 + 1/1! + ½! + 1/3! + 1 /N!.

Exerc.6 - Escreva um método recursivo que calcula e retorna o valor de S(n), onde
S = 2/4 + 5/5 + 10/6 + 17/7 + 26/8 + ... +(n*2+1)/(n+3)

Exerc.7 - Escreva um método recursivo que calcula e retorna a função potência Xⁿ.

Exerc.8 - Faça um método recursivo que recebe um inteiro e retorna o seu número de dígitos.

Exerc.9 – Escreva um método para calcular o valor da função de Ackmann, dada pela seguinte relação:
Nota:
1 se m = 0
A(m,n) = A(m-1,1) se m>0 e n=0
A(m-1,A(m,n-1)) se m>0 e n>0

Exerc.10 – Escreva um programa contendo o seguinte método recursivo que retorna o n-ésimo número Catalão:
static long c( int n)

A sequência dos números Catalão é dada por :


1 1 2 5 14 42 132 429 ...
Em termos matemáticos a sua relação é dada por :

n −1
c (n) = ∑ c(i ) . c(n − 1 − i ) = c(0) . c(n − 1) + c(1).c(n − 2) + .... + c(n − 2).c(1) + c(n − 1) . c(0)
i =0

Para efeitos comprovativos, em seguida, utilize a seguinte expressão e compare os resultados da sequência
obtida:

(2n)!
c ( n) =
n!. (n + 1)!

Exerc.11 - Faça um método recursivo que ordene por ordem crescente os n elementos de um vector de inteiros de n
posições.

Exerc.12 - Faça uma função recursiva que calcule o mdc entre dois números:
mdc(n1,n2) = n1 , se n2 = 0
mdc(n1,n2) = mdc( n2, n1 mod n2), se n2 != 0

Exerc.13 - Dada a função X definida abaixo:

Algoritmo X(n,m: inteiro): inteiro;

inicio
se (n=m) ou (m=0)
entao
X = 1
senao
X = X(n-1,m) + X(n-1,m-1)
fim
Qual o valor de X(5,3) ?
Quantas chamadas serão feitas na avaliação acima ?

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 133


Sebenta da Disciplina de Introdução à Programação

10 - Anexo I – Exemplo Introdutório em Java

Neste anexo apresenta-se a título de exemplo introdutório ao Java a classe Aluno que foi teoricamente explicada no
capitulo 2.

public class Aluno


{
//ATRIBUTOS
private String nome;
private int numero;
private int ano;
private String curso;
private char turma;
private double valorPropina;
private double valorPago;

//CONSTRUTORES
public Aluno(String nom, int num, String curs, int an, char turm)
{
nome = nom;
numero =num;
ano=an;
curso=curs;
turma=turm;
valorPropina=0;
valorPago=0;
}

// metodos selectores
public int getNumero()
{
return numero;
}
public String getNome()
{
return nome;
}
public String getCurso()
{
return curso;
}
public int getAno()
{
return ano;
}
public char getTurma()
{
return turma;
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 134


Sebenta da Disciplina de Introdução à Programação

public double getPropina()


{
return valorPropina;
}
public double getValorPago()
{
return valorPago;
}

// metodos modificadores
public void setCurso(String curs)
{
curso=curs;
}
public int setAno()
{
return ano;
}
public void setTurma(char turm)
{
turma=turm;
}
public void setPropina(double valor)
{
valorPropina=valor;
}

// outros métodos
public String toString()
{
String str= "Nome:" + nome + "Numero :" + numero + " curso : " +
curso + " ano" + ano;
return str;
};

// metodo que calcula valor da propina ja pago


public void pagarPropina(double valor)
{
valorPago=valorPago+valor;
}

// metodo que calcula a divida


public double calculaDivida()
{
return valorPropina-valorPago;
}

// metodo que verifica se a propina já foi paga


public boolean verificaPropinaPaga()
{
boolean resultado=calculaDivida()==0;
return resultado;
}
}

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 135


Sebenta da Disciplina de Introdução à Programação

11 - Anexo II – Glossário

Nota:

Os significados apresentados para as palavras colocadas neste glossário são apenas os que se consideraram
necessários no âmbito da cadeira de Introdução à Programação.
As palavras encontram-se descritas por ordem alfabética.

Abordagem: conjunto de acções tomadas para definir a forma de atingir a solução de um determinado problema.

Algoritmo: Conjunto de instruções que resolvem um problema.

Ambiguidade: Expressão cujo significado não pode ser determinado a partir do contexto em que está inserida (ou
seja, que a partir de determinado ponto oferece mais do que um caminho a seguir, podendo levar a resultados
diferentes).

Bottom-Up: Construção de uma solução partindo dos elementos mais pequenos.

Código fonte: Código escrito pelo programador.

Código executável: Resultado da compilação do código fonte.

Conceber: Criar.

Compilador: Programa que sabe interpretar o código escrito numa determinada linguagem de programação. Recebe
código fonte como elemento de entrada e produz código executável.

Compilação: Processo de gerar código executável a partir de código fonte recorrendo a um compilador.

Divide-And-Conquer: Metodologia ou forma de resolução de problemas que envolve partir um problema em


subproblemas mais pequenos, cujas soluções combinadas representam a solução do problema original.

Estado: Situação em que se encontra uma variável em termos de valor actual. O estado de um objecto é o conjunto
de valores dos seus atributos. No que diz respeito a um problema, tem um estado inicial que corresponde ao valor do
resultado que ainda não existe, e um estado final que é o valor de resultado após passar pela fase de transformação.

Hardware: Componentes físicos de um computador (discos, monitores, colunas, etc.)

Implementação: Código produzido por um programador e que representa uma solução possível para um determinado
problema.

Linguagem de Programação: Linguagem artificial utilizada para levar a cabo a implementação de programas de
computador.

Máquina Virtual: Na prática é um computador simulado dentro do próprio computador através de software próprio
criado para esse efeito. Comporta-se como se fosse um computador independente. A máquina virtual Java actua
como um ambiente de execução de programas Java auto-contido.

Notação: Mecanismo que serve para definir o formato de determinado tipo de informação. Por exemplo: a BNF serve
para definir gramáticas para variados tipos de linguagens, tal como o XML serve para definir formato de dados, os
símbolos musicais servem para definir músicas nas partituras, etc, etc.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 136


Sebenta da Disciplina de Introdução à Programação

Operandos: elementos envolvidos numa determinada operação.

Quotidiano: algo relativo ao dia-a-dia.

Pseudocódigo: forma simplificada de descrever um algoritmo recorrendo a palavras chave semelhantes às da


linguagem natural, mas que são estruturadas à semelhança de um programa de computador.

Sistema de Numeração: Esquema de representação de magnitudes ou quantidades através de um grupo de dígitos.


Basicamente, é uma notação de representação de números.

Sistema Operativo: Programa de computador de grandes dimensões e complexidade que é responsável não só por
esconder os detalhes do hardware aos utilizadores e programadores, como também tem de gerir a memória
disponível para cada aplicação(programa em execução, também chamado de processo) e gerir a execução dessas
mesmas aplicações, gerir o sistema de comunicação com outras máquinas, etc.

Software: Programa de computador. Representa a parte lógica, ao contrário do hardware que representa a parte
física de um computador.

Subprograma: Também chamados de rotinas (ou métodos no caso de linguagens orientadas a objectos como é o
caso do Java), são pequenos programas que podem ser chamados e chamar outros programas para que em conjunto
colaborem na obtenção de uma solução para determinado problema.

Top-Down: Cosntrução de uma solução em que a partir do problema maior se tenta ir descendo de nível e
especificando a cada passo os níveis intermédios, ou seja, os problemas mais pequenos.

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 137


Sebenta da Disciplina de Introdução à Programação

12 - Anexo III - Bibliografia

ƒ Fundamentos de Programação em Java2 – António Mendes, Maria José Marcelino, FCA


ƒ Java Software Solutions, John Lewis, Addison Wesley
ƒ Programação em Java2 – Pedro Coelho, FCA
ƒ Introdução à Programação Utilizando Pascal, Pavão Martins, McGraw-Hill
ƒ The Java Programming Language – Ken Arnold, James Gosling . Addison Wesley
ƒ Acetatos de IP dos anos lectivos 2000/2001 até 2003/2004

© Escola Superior de Tecnologia de Setúbal 2005-2006 Página 138

Potrebbero piacerti anche