A primeira coisa que deverá fazer é garantir que tem um
compilador e um interpretador de Java instalado na sua
máquina. Tente seguir as seguintes ligações:
// Uma classe muito simples que usa um ciclo para imprimir numeros entre 1 e n
// O ficheiro tem de ter o mesmo nome da classe + a extensão '.java'
public class Numbers {
public static void main(String[] args) {
int n = 10; // limite dos numeros
System.out.println("Numeros de 1 a " + n + ":"); // + é o operador de concatenação de strings
for (int i=1; i<=n; i++)
System.out.println(i);
}
}
public class Square {
// Desenha uma linha de n caracteres onde:
// - o primeiro e o último caracteres são o caracter da variável 'a'
// - todos os outros caracteres são o caracter da variável 'b'
static void line(char a, char b, int n) {
System.out.print(a);
for (int i=1; i<=n-2; i++)
System.out.print(b);
System.out.println(a);
}
// O procedimento executado inicialmente é sempre o main
public static void main(String[] args) {
line('*','-',5);
}
}
Exercício 4) Funções e instruções condicionais
public class Primes {
// Verifica se o número n é primo (apenas divisível por 1 e por si próprio)
// [função ainda por completar]
static boolean isPrime(int n) {
return true;
}
public static void main(String[] args) {
int n=1000; // Limite dos números
for (int i=2; i<=n; i++)
if (isPrime(i))
System.out.println(i);
}
}
- Testando o código base.
Compile e execute este código. Qual o resultado?
- Função isPrime.
Preencha agora o conteúdo da função isPrimepara o código ficar correcto.
- Um número é primo se apenas for divisível por 1 e por si próprio
- A função deve retornar true se o número for primo e false caso contrário.
- Faça um ciclo entre 2 e n e se algum outro número dividir n, então indique que ele não é primo, saindo logo da função.
(sim, é possivel fazer melhor que testar todos os números, e nos próximos exercícios vamos fazer evoluir o código para algo mais eficiente).
- Como saber se um número divide outro? Que tipo de operador é necessário? (ver secção de operadores da introdução)
- Se o programa estiver correcto, para n=1000 deverá encontrar 168 números primos (use o comando wc como atrás descrito para verificar).
- Medindo o tempo.
Neste exercício vamos querer ver quanto tempo o seu programa demora. Para isso vamos usar o comando time de Linux.
- Comece por usar time com o seu programa para verificar quanto tempo demora. Deverá ver algo como:
$ time java Primes | wc -l
168
real 0m0.079s
user 0m0.076s
sys 0m0.008s
$
- Experimente agora mudar n para cem mil e veja quanto tempo demora (nao se esqueça de recompilar antes de voltar a executar).
- Se n for um milhão quanto tempo demora?
(se ficar cansado de esperar pode parar a execução fazendo Control+C)
- Melhorando a eficiência.
Vamos agora melhorar a eficiência da função isPrime para melhorar o tempo de execução.
Em vez de testar com os divisores todos números entre 2 e n, basta testar entre 2 e
√n. (Porquê?)
Modifique o seu programa para fazer isso (não precisa de saber como calcular raízes quadradas em Java, pois não?) e meça o tempo de execução para verificar se melhorou.
Exercício 5) Strings, e alguns erros de execução e compilação
// Exemplos de uso de Strings
public class Strings {
public static void main(String[] args) {
String a = 1007; // A tentar atribuir um número inteiro a uma String
String b = "1007"; // Colocar "1007" na variável b
String c = "CC"; // Colocar "CC" na variável c
String d = c + b; // Concatenar "CC" com "1007" e colocar resultado na variável d
String e = c + 1007; // Concatenar "CC" com número 1007 e colocar resultado na variável e
// Escrever conteúdo das duas strings criadas
System.out.println("d = " + d);
System.out.println("e = " + e);
// Como comparar duas strings
System.out.println("d==e? " + (d==e)); // Não está correcto (compara referências)
System.out.println("d.equals(e)? " + d.equals(e)); // Maneira correcta de comparar o conteúdo de duas strings
// Como calcular o tamanho de uma string
int size = d.length();
System.out.println("tamanho de d = " + size);
// Como ir buscar o caracter numa dada posição da string
System.out.println("d.charAt(0) = " + d.charAt(0));
System.out.println("d.charAt(2) = " + d.charAt(2));
//System.out.println("d.charAt(10) = " + d.charAt(10));
// Como ir buscar parte de uma string entre duas dadas posições
String sub = d.substring(1,4);
System.out.println("d.substring(1,4) = " + sub);
// Procurando a primeira ocorrência de um dado caracter
char ch = '7';
int pos = d.indexOf(ch);
System.out.println("d.indexOf(" + ch +") = " + pos);
}
}
- Um erro de compilação.
Compile o programa. Que tipo de erro dá? Consegue "ler" e interpretar o que o compilador de Java escreve?
- Verificando o programa.
Comente a linha que deu erro, compile e execute, procurando perceber todas as suas linhas e o output obtido.
- Ao contrário do C, em Java uma String é um tipo específico (uma classe) e não um mero array de caracteres.
- Note como o operador concatenação funciona conforme os operandos: se tiver dois números, soma, se tiver pelo menos uma string, interpreta ambos como strings e concatena;
- Uma simples comparação com == compara as referências e não o conteúdo dos objectos string e por isso devolve que são diferentes (vamos falar sobre objectos e referências noutras aulas)
- Para podermos operar sobre objectos do
tipo String, o Java disponibiliza
toda uma biblioteca. Espreite a documentação
oficial da classe String para ver quais os métodos
existentes (as funções que operam sobre objectos do
tipo String). Na ligação poderá
encontrar uma explicação detalhada do funcionamento dos vários
métodos aqui usados.
- Erro durante a execução.
Descomente a linha que tenta escrever d.charAt(10). Que erro é dado? O Java comunica os erros de execução através de excepções com nomes que indicam o tipo de erro.
- Procurando um método.
Use a documentação para descobrir um método para converter uma String em minúsculas. Teste o método no código, compilando e executando para ver o resultado obtido.
- Criando uma função.
Crie um método que recebe uma String e devolve se esta é ou não um palíndromo (ou seja, se a string é igual à sua versão invertida). Por exemplo:
- isPalindrome("hello") deve devolver false porque "hello" não é igual a "olleh"
- isPalindrome("bob") deve devolver true
Qual deve ser o tipo do argumento da função? E do seu valor de retorno?
Exercícios adicionais para consolidação de conhecimentos
- Mais sobre ciclos e procedimentos.
Crie um procedimento que, dado um n ímpar, escreva um losango de tamanho n no ecrã. Por exemplo, se n=5, o output deve ser:
#
###
#####
###
#
- Mais sobre números primos.
Crie um procedimento que, dado um inteiro n, escreva a sua decomposição em factores primos. Por exemplo, se n=20, o output deve ser:
20 = 2 * 2 * 5
- Mais sobre strings I.
Crie um procedimento count que receba uma string s e um caracter c e devolva o número de ocorrências da letra c na string c (por exemplo, count("algoritmo", 'o') deve devolver 2, o número de vezes que a letra 'o' aparece)
- Mais sobre strings II.
Crie um procedimento que receba um inteiro n e escreva as primeiras n linhas do L-system original de Lindenmayer, que usa as seguintes regras:
- A primeira linha é "A"
- Para se obter uma nova linha pega-se na linha anterior e substitui-se todos os "A" por "AB" e todos os "B" por "A".
Por exemplo, se o procedimento for chamado com n=7 o output deverá ser:
A
AB
ABA
ABAAB
ABAABABA
ABAABABAABAAB
ABAABABAABAABABAABABA