SlideShare ist ein Scribd-Unternehmen logo
1 von 50
Downloaden Sie, um offline zu lesen
INSTITUTO FEDERAL DE MATO GROSSO DO SUL
Tecnologia em Sistemas para Internet
Disciplina: Linguagem de Programação I
Prof.º Msc. Sidney Roberto de Sousa
Apostila – Linguagem de Programação I
1 - Conteúdo da apostila
• Criando um programa em Java
• Compilando e executando programas em Java
• Imprimindo texto na tela
• Trabalhando com números inteiros
• Trabalhando com números reais
• Operações matemáticas
◦ Operações binárias
◦ Operações unárias
• Trabalhando com booleanos e operações lógicas
• Trabalhando com strings
• Lendo valores do usuário
• Controlando o fluxo do programa
• Utilizando laços de repetição
• Matrizes
2 - Criando um programa em Java
Um programa Java básico precisa ser escrito dentro de uma classe. Em um futuro
próximo, aprenderemos mais a respeito sobre classes e objetos. Por enquanto, tudo o que
precisamos saber é que todo o algoritmo do nosso programa Java precisa ser escrito dentro de
uma definição de classe, conforme o exemplo abaixo.
public class MeuPrograma {
public static void main(String[] args) {
// O seu algoritmo vai aqui!
}
}
No exemplo, a nossa classe chama-se MeuPrograma. O nome de uma classe Java deve
obrigatoriamente começar com uma letra e não pode conter caracteres especiais (como por
exemplo $%”&#-+=/(){}[]*@!.?`'ªº). É uma convenção que o nome de classes Java sejam
escritas no formato Camel Case, ou seja, com cada palavra do nome iniciada por uma letra
maiúscula e todos os caracteres restantes em minúsculo. Todas as classes que escreveremos
nesta disciplina conterá o método main, exatamente da forma como foi escrito no exemplo
acima.
Dentro do método main, na única linha de código do método, existe um comentário
explicando que o código do algoritmo do programa deve ser escrito a partir daquele ponto.
Comentários não são códigos de programa. Eles servem somente para se comentar algo sobre
o código que está sendo escrito. Por exemplo, você pode querer inserir comentários que
expliquem o raciocínio por trás do algoritmo que você desenvolveu, ou mesmo um lembrete
para você mesmo a respeito de um trecho de código mais complexo. Abaixo, alguns exemplos
de comentários.
// Eu sou um comentário de uma linha
// Eu sou um comentário de
// duas linhas
/*
* Eu também sou um comentário de
* duas linhas!
*/
Outra coisa a ser notada é que tanto o corpo de código da classe MeuPrograma
quanto o corpo de código do método main são delimitados por chaves. Esta delimitação é
obrigatória e nos ajuda a organizar o nosso código.
Uma vez que você escreveu o seu programa dentro de uma classe e de um método
main, você deve salvar o arquivo de texto que contém o código que você escreveu. A
nomenclatura deste arquivo deve seguir obrigatoriamente o padrão abaixo:
NOME_DA_CLASSE.java
Por exemplo, a classe MeuPrograma do nosso exemplo deve ser salva no arquivo
MeuPrograma.java. Tome muito cuidado para não se esquecer deste procedimento!
Exercício
a) Crie a classe MeuPrograma conforme o exemplo anterior e salve a classe em um
arquivo apropriado (conforme ensinado nesta seção).
3 - Compilando e executando programas em Java
Um programa Java precisa ser compilado para bytecodes antes que a máquina virtual
Java possa executá-lo. Para tanto, a plataforma Java oferece um compilador Java, presente no
script javac.
Antes que você possa utilizar o script javac, talvez você deseje adicioná-lo às suas
variáveis de ambiente, para que você possa executá-lo em qualquer pasta. No Windows,
primeiramente você deve informar ao sistema operacional onde os arquivos da máquina virtual
Java estão localizados, criando a variável de ambiente JAVA_HOME:
Nome da variável: JAVA_HOME
Valor da variável: PASTA_ONDE_O_JAVA_FOI_INSTALADO
Por exemplo, se você instalou a última versão do Java1
em uma instalação padrão, sem
definir um outro diretório, provavelmente você fará a seguinte configuração:
Nome da variável: JAVA_HOME
Valor da variável: C:Program FilesJavajdk1.7.0_17
Após criar a variável de ambiente JAVA_HOME, você precisa informar ao Windows onde
estão localizados os programas da máquina virtual Java. Para tanto, basta você adicionar o
caminho dos programas na variável de ambiente PATH (ATENÇÃO: Esta variável provavelmente
já existe na sua instalação do Windows. Assim, coloque o caminho dos executáveis Java no
final da string do valor da variável PATH. NÃO APAGUE o conteúdo já existente da variável!).
Caso você tenha instalado a última versão do Java em uma instalação padrão como
citado anteriormente, você deve colocar o valor abaixo no final da string do valor da variável
de ambiente PATH (lembrando que quando uma variável de ambiente possui vários valores,
cada valor deve ser separado pelo caractere ';'):
C:Program FilesJavajdk1.7.0_17bin
Uma vez que você tenha realizado todas estas configurações (caso tenha sido
1 Data de 08/04/2013.
necessário realizá-las), o seu computador está pronto para compilar e executar os seus
programas Java. Para compilar um programa Java, entre no PROMPT do DOS, use o comando cd
para entrar na pasta onde o seu arquivo .java está localizado e utilize o comando javac para
compilar o seu programa.
Por exemplo, considere o nosso programa escrito na classe MeuPrograma, a qual está
dentro do arquivo MeuPrograma.java. Assim, para compilar o seu programa você precisa
digitar o comando abaixo:
javac MeuPrograma.java
Ao fazer isto, caso o seu programa não contenha nenhum erro, o compilador Java cria
um arquivo chamado MeuPrograma.class na mesma pasta onde o seu programa está
situado. Este arquivo contém os bytecodes do seu programa para que a máquina virtual Java
possa executá-lo. Assim, para executar o seu programa, você precisa digitar o comando abaixo:
java MeuPrograma
E pronto! Agora é só testar o seu programa!
Exercícios
a) Abra o terminal de linha de comando, encontre a pasta onde o arquivo da classe
MeuPrograma se encontra e compile e execute a classe MeuPrograma.
4 – Imprimindo texto na tela
Uma das primeiras coisas úteis que podemos aprender é imprimir texto em linha de
comando por meio de um programa Java. No Windows, o shell de linha de comando mais
utilizado é o PROMPT do MS-DOS. No Linux, temos vários tipos de shells, como o bash e o
dash. O programa abaixo imprime a mensagem “Olá! Eu sou um programa escrito em Java!”
na tela.
public class MeuPrograma {
public static void main(String[] args) {
System.out.print("Olá! Eu sou um programa escrito em Java!");
}
}
O método print, existente no atributo out da classe System do Java imprime
mensagens em linha de comando. Se você compilar e executar este programa, ele irá gerar a
seguinte saída no shell:
Note que o texto impresso pelo programa provocou uma má formatação no shell de
linha de comando, pois o texto impresso e a linha de comando atual ficaram na mesma linha!
Para evitar este tipo de problema, podemos utilizar o método println ao invés do método
print, conforme o exemplo abaixo:
public class MeuPrograma {
public static void main(String[] args) {
System.out.println("Olá! Eu sou um programa escrito em Java!");
}
}
suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$ javac MeuPrograma.java 
suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$ java MeuPrograma 
Olá! Eu sou um programa escrito em Java!suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$
O método println imprime a mensagem desejada na tela do shell, porém ele pula uma
linha do shell após a impressão. Abaixo, a saída do programa acima:
Existem basicamente duas formas de se imprimir múltiplas linhas na tela. A primeira
forma é utilizar um println por frase, conforme abaixo:
public class MeuPrograma {
public static void main(String[] args) {
System.out.println("Olá! Eu sou um programa escrito em Java!");
System.out.println("Estou imprimindo duas linhas na tela.");
}
}
A outra forma é utilizar o caractere especial 'n' dentro do método print. Este caractere
faz com que o texto seja quebrado em outra linha. O programa abaixo gera a mesma saída do
programa do exemplo acima:
public class MeuPrograma {
public static void main(String[] args) {
System.out.print("Olá! Eu sou um programa escrito em Java!nEstou imprimindo duas linhas na tela.n");
}
}
Opcionalmente, você pode inserir tabulações nas frases a serem impressas na tela, a
fim de se obter uma melhor formatação do texto. Para inserir uma tabulação, utilizamos o
caractere especial 't'. O programa abaixo imprime uma frase na tela, inserindo uma tabulação
no início da frase:
public class MeuPrograma {
public static void main(String[] args) {
System.out.println("tOlá! A tabulação no início desta frase simula o início de um parágrafo.");
}
}
Exercícios
a) Escreva um programa que imprima na tela o poema a seguir utilizando uma ou mais
chamadas ao método println, sabendo que cada frase possui uma tabulação em seu início.
BILHETE 
Se tu me amas, ama­me baixinho 
Não o grites de cima dos telhados 
Deixa em paz os passarinhos 
Deixa em paz a mim! 
Se me queres, 
enfim, 
tem de ser bem devagarinho, Amada, 
que a vida é breve, e o amor mais breve ainda... 
Mario Quintana
b) Escreva um programa que imprima na tela o mesmo poema acima, porém utilizando
somente uma chamada ao método print.
suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$ javac MeuPrograma.java 
suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$ java MeuPrograma 
Olá! Eu sou um programa escrito em Java!
suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$
5 - Trabalhando com números inteiros
Muitos dos problemas do mundo real que necessitam de um programa de computador
para serem resolvidos envolvem números. Considere o seguinte problema: uma pessoa possui
53 pacotes de biscoito salgado e 87 pacotes de biscoito doce em seu estoque e ela precisa
saber quantos pacotes de biscoito ela possui no total. Note que este problema envolve apenas
números inteiros, ou seja, número que não precisam de casas decimais para representá-los.
Vamos escrever um programa para resolver este problema:
public class SomaPacotesBiscoito {
public static void main(String[] args) {
int numeroPacotesBiscoitoSalgado = 53;
int numeroPacotesBiscoitoDoce = 87;
int totalPacotes = numeroPacotesBiscoitoSalgado + numeroPacotesBiscoitoDoce;
System.out.println("Você possui " + totalPacotes + " pacotes de biscoito.");
}
}
Para resolver este problema, precisamos utilizar três variáveis. Uma variável é um local
de armazenamento de dados. Você pode pensar em uma variável como uma gaveta capaz de
armazenar itens. Toda variável possui um nome, o qual deve começar com uma letra e não
pode conter caracteres especiais. É uma forte convenção que variáveis em Java iniciem com
letras minúsculas.
As três variáveis que utilizamos neste programa são do tipo int. Uma variável do tipo
int só pode armazenar números inteiros. Existem outros tipos em Java que podem armazenar
números inteiros. Para uma melhor explicação sobre tipos inteiros, veja os slides da aula 3.
A primeira variável utilizada no programa acima chama-se
numeroPacotesBiscoitoSalgado. Ela guarda o número de pacotes de biscoito salgado
contidos no estoque da pessoa do nosso problema. A segunda variável do nosso programa
chama-se numeroPacotesBiscoitoDoce. Por sua vez, ela guarda o número de pacotes de
biscoito doce existentes no estoque.
A soma total de pacotes resulta em um número inteiro, visto que ela é composta pela
soma de dois números inteiros. Assim, a última variável do nosso programa (totalPacotes)
armazena a soma do número de pacotes de biscoito salgado com o número de pacotes de
biscoito doce. Observe bem a linha de código que executa esta soma. O operador '=' simboliza
que algum valor será atribuído à variável totalPacotes. O operador '+' simboliza a soma entre
os valores de numeroPacotesBiscoitoSalgado e numeroPacotesBiscoitoDoce. Veremos
mais em frente nesta apostila outros tipos de operações matemáticas possíveis em Java.
O número total de pacotes é exibido na última linha do programa. A fim de facilitar o
entendimento do usuário a respeito do que foi realizado no programa, exibimos a ele uma frase
explicativa contendo o número total de pacotes calculado. Note que utilizamos o operador '+'
para concatenar a frase que queremos exibir para o usuário com o número total de pacotes.
Esta concatenação transforma o número inteiro em texto, podendo assim ser juntado à frase. O
programa exibe a seguinte saída na tela:
Você possui 140 pacotes de biscoito.
6 - Trabalhando com números reais
Agora, imagine que a pessoa do exemplo anterior deseje saber qual o peso total dos
biscoitos que ela possui em estoque. Ela sabe que cada pacote de biscoito salgado pesa 0,350
kg e cada pacote de biscoito doce pesa 0,414 kg. Note que agora alguns números do nosso
problema não são inteiros – no caso, os pesos dos pacotes. Assim, não podemos armazenar
tais valores em variáveis inteiras. A seguir, a solução para este problema:
public class CalculoPesoPacotesBiscoito {
public static void main(String[] args) {
int numeroPacotesBiscoitoSalgado = 53;
int numeroPacotesBiscoitoDoce = 87;
double pesoTotalBiscoitosSalgados = numeroPacotesBiscoitoSalgado * 0.350;
double pesoTotalBiscoitosDoces = numeroPacotesBiscoitoDoce * 0.414;
double pesoTotalPacotes = pesoTotalBiscoitosSalgados + pesoTotalBiscoitosDoces;
System.out.println("O seu estoque de biscoitos pesa " + pesoTotalPacotes + " kg.");
}
}
Além das duas variáveis inteiras para armazenar o número total de pacotes de cada
tipo de biscoito, o nosso programa possui mais três variáveis do tipo double para armazenar o
peso total de biscoitos salgados, o peso total de biscoitos doces e o peso total de biscoitos em
estoque. O tipo double é utilizado para definir que as três variáveis armazenam números reais.
Uma variável do tipo double pode armazenar tanto números reais quanto números inteiros. O
tipo float também é utilizado para se definir variáveis para armazenar números reais. Para
entender melhor as diferenças entre estes dois tipos, veja os slides da aula 3. O programa
acima imprime a seguinte mensagem na tela:
O seu estoque de biscoitos pesa 54.568 kg.
7 - Operações matemáticas
Na linguagem Java é possível compor desde operações matemáticas simples - como
somar ou subtrair dois valores - até operações mais complexas. No exemplo anterior, o nosso
código realizou duas operações matemáticas básicas: a soma entre dois valores, por meio do
operador '+' e a multiplicação entre dois valores, por meio do operador '*'. Podemos agrupar as
operações matemáticas em Java em dois tipos: operações binárias e operações unárias.
7.1 Operações binárias
Uma operação binária é uma operação matemática que envolve dois valores distintos.
Tais valores podem ser constantes ou oriundos de variáveis. A tabela abaixo mostra as
operações matemáticas binárias possíveis em Java.
Operação Operador Expressão
Adição + a = b + c;
Subtração - a = b – c;
Multiplicação * a = b * c;
Divisão / a = b / c;
Operações matemáticas do tipo a = a OPERADOR b; podem ser abreviadas. A tabela
abaixo mostra as abreviações possíveis.
Expressão Expressão abreviada
a = a + b; a += b;
a = a - b; a -= b;
a = a * b; a *= b;
a = a / b; a /= b;
O programa abaixo contém algumas operações matemáticas binárias simples:
public class ExemploOperacoesBinarias {
public static void main(String[] args) {
int valor1 = 45;
// Somando o valor de uma variável com um constante
int valor2 = valor1 + 76; // 121
// Somando o valor de duas variáveis
valor1 = valor1 + valor2; // 166
// Realizando a mesma operação, usando uma abreviação
valor1 += valor2; // 287
// Subtraindo o valor de duas constantes
double numeroReal = 687.35 - 790; // −102.65
numeroReal -= 100; // −202,65
numeroReal *= -1; // 202,65
double resultado = numeroReal / valor1; // 0.7060975609756097
resultado /= resultado; // 1
}
}
Podemos compor operações matemáticas mais complexas, como fórmulas
matemáticas. A seguir, alguns programas que contém fórmulas conhecidas:
public class Bhaskara {
public static void main(String[] args) {
double a = 5;
double b = 6;
double c = 4;
double delta = b * b - 4 * a * c; // -44
System.out.println("Delta = " + delta);
}
}
public class AreaCircunferencia {
public static void main(String[] args) {
/*
* Constantes em Java são definidas por meio do prefixo final.
* O valor da constante deve ser definido obrigatoriamente
* no momento de sua declaração.
* O valor de uma constante não é mutável. Isto significa que
* após a inicialização da constante, instruções como esta:
* PI = 456.87;
* Gerariam um erro.
*/
final double PI = 3.14159;
double raio = 5;
double areaCircunferencia = PI * raio * raio; // 78.53975
System.out.println("Área da circunferência = " + areaCircunferencia);
}
}
public class AreaQuadrado {
public static void main(String[] args) {
double lado = 4.5;
double areaQuadrado = lado * lado; // 20.25
System.out.println("Área do quadrado = " + areaQuadrado);
}
}
Vale a pena salientar que as operações de multiplicação e divisão possuem precedência
sobre as operações de adição e subtração. Caso a fórmula precise ser calculada utilizando uma
ordem de precedência diferente à ordem normal, é preciso utilizar parênteses para se definir os
trechos de precedência. Considere o exemplo abaixo:
public class ExemploPrecedencia {
public static void main(String[] args) {
int valor1 = 7;
int valor2 = 9;
int resultado = valor1 * (98 - valor2) * 4; // 2492
System.out.println(resultado);
}
}
Note que a fórmula do programa acima resultaria no valor 650 caso não houvessem os
parênteses, pois primeiramente seriam calculadas as multiplicações para depois ser calculada
a subtração. Porém, o uso dos parênteses faz com que a subtração seja calculada inicialmente,
fazendo com que a fórmula resulte no valor 2492.
Exercícios
Para cada problema abaixo, escreva um programa para resolvê-lo:
a) Uma pessoa viaja em seu veículo de passeio pelo estado de Mato Grosso do Sul. Em
um determinado momento, ela chega no município de Guia Lopes da Laguna. Porém, o seu
objetivo é chegar até o município de Bonito, o qual se situa a 45 km de distância do município
de Guia Lopes da Laguna. Dado que seu veículo viaja sob a velocidade média de 80 km/h,
quanto tempo (em minutos) a pessoa demorará para chegar até o município de Bonito?
(Recordando que segundo a física mecânica, a fórmula para se encontrar o intervalo de tempo
é tempo=distância/velocidade. Não se esqueça de realizar a conversão para minutos no
final!)
b) Um pedreiro utilizou 1000 tijolos para construir 30 metros de muro. Dado que ele
ainda necessita construir 6 metros de muro, quantos tijolos ele ainda necessitará utilizar? (Não
se preocupe se o número da resposta não for inteiro)
c) Um artesão deseja construir uma torre uniforme de 3,5 m de altura utilizando cartas
de baralho. Ele já conseguiu construir 1,75 m da torre, utilizando para tanto 557 baralhos.
Sabendo que um baralho tradicional possui 52 cartas, quantas cartas ele ainda necessitará
para finalizar a construção da sua torre? (Não se preocupe se o número da resposta não for
inteiro)
d) Em uma pesquisa eleitoral, identificou-se que 432 pessoas pretendem votar no
candidato José da Silva; 284 pessoas pretendem votar na candidata Ana Alencar; 698 pessoas
pretendem votar na candidata Carolina Bezerra; por fim, 173 pessoas se mostraram indecisas
quanto a que candidato votar. Qual o percentual de indecisos levantado nesta pesquisa
eleitoral?
7.2 Operações unárias
Uma operação unária envolve apenas uma variável. Em Java, existem duas operações
unárias matemáticas, o incremento e o decremento. O operador de incremento faz com que o
valor atual da variável seja incrementado em uma unidade, ou seja, a variável recebe o seu
valor atual somado em uma unidade. Por sua vez, o operador decremento faz com que o valor
da variável seja decrementado em uma unidade, ou seja, a variável recebe o seu valor atual
subtraído em uma unidade. A tabela abaixo exibe estas operações.
Operação Operador Expressão
Incremento ++ a++; ou ++a;
Decremento -- a--; ou --a;
Em alguns casos, o uso do operador unário antes ou depois da variável pode resultar
em valores distintos. O programa abaixo exibe alguns exemplos de incremento e decremento,
além dos resultados da operação unária com operadores antes e depois da variável:
public class ExemploOperacoesUnarias {
public static void main(String[] args) {
double valor = 2.7;
valor++; // 3.7
int numero = 58;
numero--; // 57
int outroNumero = 57;
int valorInteiro = ++numero; // valor recebe 58
valorInteiro = outroNumero++; // valor recebe 57!
}
}
8 – Trabalhando com booleanos e operações lógicas
Na linguagem Java, um valor booleano só pode ter um dentre dois valores: true e
false, respectivamente verdadeiro e falso. Saber trabalhar com valores booleanos é
essencial para a criação de programas complexos em Java, conforme veremos a partir desta
seção.
Em Java, um valor booleano pode ser armazenado em uma variável do tipo boolean.
Um operação realizada entre dois valores booleanos é chamada de operação lógica (ou
booleana) binária. O resultado de uma operação lógica só pode resultar em um valor
booleano, ou seja, true ou false. Existem basicamente duas operações lógicas binárias, as
operações AND e OR. Em Java, o operador && simboliza uma operação AND. Uma operação
AND só resulta o valor true se e somente se os dois valores da operação forem iguais a true;
caso contrário, o resultado da operação será false. A tabela abaixo exibe os resultados para
cada operação AND possível entre dois valores booleanos:
a b a && b
true true true
true false false
false true false
false false false
A operação OR em Java é simbolizada pelo operador ||. Uma operação OR só resulta o
valor false se e somente se os dois valores da operação forem iguais a false. A tabela abaixo
exibe os resultados para cada operação OR possível entre dois valores booleanos:
a b a || b
true true true
true false true
false true true
false false false
Existe apenas uma operação unária sobre valores booleanos, a operação de negação.
Em Java, esta operação é simbolizada pelo operador !. Quando um valor booleano é negado, o
seu valor é invertido. A tabela abaixo exibe os resultados possíveis para cada negação:
a !a
true false
false true
O programa abaixo mostra alguns exemplos de operações booleanas binárias e unárias:
public class ExemploOperacoesBooleanas {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
boolean resultado = a && b; // false
resultado = a || b; // true
resultado = !a; // false
resultado = !b; // true
/*
* Operações AND e OR não possuem precedência uma sobre a outra. As
* operações são calculadas par a par.
*/
resultado = false && true || false || true; // true
}
}
É possível criar operações lógicas envolvendo números inteiros ou reais. Existem muitas
situações em que precisamos comparar dois ou mais números. As operações AND e OR não se
aplicam a números diretamente. As operações lógicas possíveis entre dois valores numéricos
são exibidas na tabela abaixo:
Operação Operador Expressão
Igual == a == b
Diferente != a != b
Maior > a > b
Menor < a < b
Maior ou igual >= a >= b
Menor ou igual <= a <= b
O programa abaixo exemplifica as operações da tabela acima:
public class ExemploOperacoesLogicasNumericas {
public static void main(String[] args) {
int numero = 67;
double outroNumero = -178.54;
boolean saoIguais = numero == outroNumero; // false
boolean saoDiferentes = numero != outroNumero; // true
boolean primeiroEMaior = numero > outroNumero; // true
boolean primeiroEMenor = numero < outroNumero; // false
boolean menorOuIgual = 67 <= numero; // true
boolean maiorOuIgual = -177 >= outroNumero; // true
}
}
Operações lógicas unárias possuem precedência sobre as operações binárias.
Operações lógicas binárias de comparação entre números (==, !=, >, <, >=, <=) possuem
precedência sobre as operações AND e OR (&& e ||). Se você deseja forçar a precedência de
uma determinada operação lógica binária, tal operação deve ser escrita entre parênteses,
como no exemplo abaixo:
public class ExemploPrecedenciaOperacoesLogicas {
public static void main(String[] args) {
boolean resultado = (98 < 89) && (true && false) || true; // true
}
}
9 - Trabalhando com strings
Uma string é uma cadeia de caracteres. Nós já trabalhamos com strings nesta apostila,
quando criamos programas para imprimir texto na tela:
public class MeuPrograma {
public static void main(String[] args) {
System.out.print("Olá! Eu sou um programa escrito em Java!");
}
}
Neste exemplo, o programa imprime a string “Olá! Eu sou um programa escrito em
Java!” na tela. Em Java, uma string deve ser delimitada por aspas duplas (“”). A string deste
exemplo é dita constante, pois em seu ciclo de vida o seu valor não é alterado. Para guardar o
seu valor e opcionalmente alterá-lo, podemos armazenar esta string em uma variável. A
linguagem Java utiliza a classe String para armazenar strings. Abaixo, um exemplo simples de
uso da classe String:
public class ExemploStringSimples {
public static void main(String[] args) {
String umaString = "Olá! Eu sou um programa escrito em Java!";
System.out.println(umaString);
}
}
Uma propriedade importante de uma string é o seu tamanho. O tamanho de uma string
é o número de caracteres imprimíveis ou não imprimíveis (ex.: 'n' e 't') que ela possui.
Lembre-se sempre que o caractere de espaço em branco ' ' também é um caractere válido e
imprimível, influenciando assim no tamanho da string. Para se obter o tamanho de uma string,
basta utilizar o método length da classe String, conforme o exemplo abaixo:
public class ExemploTamanhoString {
public static void main(String[] args) {
String umaString = "Olá! Eu sou um programa escrito em Java!";
int tamanho = umaString.length(); // 40
System.out.println("A string '" + umaString + "' possui tamanho " + tamanho);
}
}
A menor string possível é a string vazia (“”), ou seja, uma string que não possui ao
menos um caractere. Existem duas formas básicas de se verificar se uma string é vazia ou não.
A primeira é verificar se o seu tamanho é igual a 0, utilizando o método length; a segunda é
verificar diretamente se a string é vazia por meio do método isEmpty da classe String. Este
método retorna true se a string for vazia ou false caso contrário. Abaixo, um programa que
exemplifica estas duas formas de verificação:
public class ExemploStringVazia {
public static void main(String[] args) {
String umaString = "";
int tamanho = umaString.length();
System.out.println("Tamanho: " + tamanho+ ". Se for zero, então a string é vazia.");
boolean estaVazia = umaString.isEmpty();
System.out.println("Está vazia? " + estaVazia);
}
}
É possível concatenar duas ou mais strings utilizando o operador '+'. De fato, nós já
fizemos isto algumas vezes nesta apostila, quando imprimimos texto na tela. Note que em
muitos exemplos, nós acabamos concatenando strings com números ou mesmo com valores
booleanos. Quando uma operação de concatenação é realizada entre uma string e um outro
valor não string, tal operação sempre resulta em uma string. Para entender melhor isto,
verifique o exemplo abaixo:
public class ExemploConcatenacaoStrings {
public static void main(String[] args) {
String primeiraParte = "Meu nome é ";
String segundaParte = " Sidney.";
String fraseCompleta = primeiraParte + segundaParte;
// Meu nome é Sidney.
System.out.println(fraseCompleta);
int numero = 567;
String umaString = "Eu escolhi o número " + numero;
// Eu escolhi o número 567
System.out.println(umaString);
double numeroReal = 45.67;
umaString = "Eu escolhi o número " + numeroReal;
// Eu escolhi o número 45.67
System.out.println(umaString);
/*
* É possível abreviar concatenações locais, i.e., concatenação entre
* uma string e ela mesma.
*/
umaString += ". Também escolhi o valor " + true + ".";
// Eu escolhi o número 45.67. Também escolhi o valor true.
System.out.println(umaString);
}
}
Existem duas formas de verificar se duas strings são iguais. A primeira forma é utilizar o
operador == entre as duas strings. Porém, existem alguns casos em que comparar strings
desta forma pode levar a resultados inesperados. A forma mais segura de se verificar se duas
strings são iguais é utilizando o método equals da classe String. O programa abaixo
exemplifica estas duas formas:
public class ExemploStringsIguais {
public static void main(String[] args) {
String primeiraString = "Copie-me se for capaz!";
String segundaString = "Copie-me se for capaz!";
boolean saoIguais = primeiraString == segundaString; // true
saoIguais = primeiraString.equals(segundaString); // true
saoIguais = segundaString.equals(primeiraString); // true
}
}
No exemplo acima, as duas strings foram consideradas iguais pois todos os caracteres
de cada posição de uma string é igual ao da outra string. Ambos os tipos de comparação são
sensíveis a casos, ou seja, consideram se as letras contidas nas strings são maiúsculas ou
minúsculas. Isto significa que, para ambos os tipos de comparação, os caracteres 'a' e 'A', por
exemplo, são distintos. Assim, se alterarmos o programa do exemplo anterior conforme abaixo,
os resultados serão diferentes:
public class ExemploStringsIguais {
public static void main(String[] args) {
String primeiraString = "Copie-me Se for Capaz!";
String segundaString = "Copie-me se for capaz!";
boolean saoIguais = primeiraString == segundaString; // false
saoIguais = primeiraString.equals(segundaString); // false
saoIguais = segundaString.equals(primeiraString); // false
}
}
A classe String oferece o método equalsIgnoreCase para se realizar comparações de
igualdade entre duas strings ignorando casos, ou seja, maiúsculas e minúsculas. Vamos
reescrever a classe ExemploStringsIguais para que ela possa realizar a comparação entre as
duas strings ignorando casos:
public class ExemploStringsIguais {
public static void main(String[] args) {
String primeiraString = "Copie-me Se for Capaz!";
String segundaString = "Copie-me se for capaz!";
boolean saoIguais = primeiraString.equalsIgnoreCase(segundaString); // true
}
}
Uma forma alternativa de se comparar duas strings ignorando casos é convertendo
ambas as strings para algum caso específico. Por exemplo, podemos converter os caracteres
de ambas as strings para minúsculo; assim, ao compararmos as strings com o método equals
ele retornará o valor true. A classe String oferece o método toLowerCase para transformar
todos os caracteres da string para minúsculo e o método toUpperCase para transformar todos
os caracteres da string para maiúsculo. O programa a seguir verifica a igualdade entre duas
strings utilizando duas abordagens distintas:
public class ComparacaoAlternativaStrings {
public static void main(String[] args) {
String primeiraString = "Copie-me Se for Capaz!";
String segundaString = "Copie-me se for capaz!";
// Converte as strings para minúsculo
primeiraString = primeiraString.toLowerCase();
segundaString = segundaString.toLowerCase();
boolean saoIguais = primeiraString.equals(segundaString); // true
primeiraString = "Crie outra String igual a MIM!";
segundaString = "crie outra string igual a mim!";
// Converte as strings para maiúsculo
primeiraString = primeiraString.toUpperCase();
segundaString = segundaString.toUpperCase();
saoIguais = primeiraString.equals(segundaString); // true
}
}
Como dito anteriormente, uma string é uma cadeia de caracteres. Um caractere pode
ser armazenado em uma variável do tipo char. Uma variável do tipo char só pode armazenar
um único caractere imprimível ou não imprimível. É possível pegar um determinado caractere
de uma string de acordo com a sua posição (índice) na string. O primeiro caractere de uma
string é localizado na posição 0; o último caractere de uma string é localizado na posição
length() - 1, ou seja, se uma string possui tamanho 10, o seu último caractere é localizado na
posição 9. A tabela abaixo ilustra a indexação de caracteres na string “Olá mundo!”. No
exemplo, a posição 4 da string guarda o caractere 'm', assim como a posição 3 da string
guarda o caractere ' ' (espaço em branco).
O l á m u n d o !
0 1 2 3 4 5 6 7 8 9
Para pegar um caractere de uma string situado em uma posição em específico,
utilizamos o método charAt da classe String. O programa a seguir mostra o uso do método
charAt. Note que cada caractere recuperado da string de exemplo é armazenado em uma
variável do tipo char:
public class PegaCaractereString {
public static void main(String[] args) {
String umaString = "Uma string é uma cadeia de caracteres.";
char caractere = umaString.charAt(5); // 't'
/*
* Caracteres constantes devem ser delimitados por aspas simples e não
* aspas duplas, como fazemos com strings.
*/
boolean igualT = caractere == 't'; // true
// Pega o primeiro caractere da string
caractere = umaString.charAt(0); // 'U'
System.out.println("Primeiro caractere: " + caractere);
// Pega o último caractere da string
caractere = umaString.charAt(umaString.length() - 1); // '.'
System.out.println("Último caractere: " + caractere);
}
}
Anteriormente nesta seção vimos como concatenar duas ou mais strings em uma única
string. Porém, em alguns casos precisamos quebrar uma string de tal forma a resultar uma
string menor ou mesmo quebrar a string original em duas ou mais strings, de acordo com
alguma necessidade. O método substring da classe String retorna uma parte da string
original, de acordo com as posições delimitadoras desejadas. O programa a seguir pega partes
de uma string utilizando o método substring de duas formas distintas:
public class ExemploSubstring {
public static void main(String[] args) {
String umaString = "Olá, mundo! Eu sou uma string!";
/*
* Pega a parte da string que inicia na posição 11 e termina na posição
* length() - 1: " Eu sou uma string!"
*/
String parteDaString = umaString.substring(11);
/*
* Pega a parte da string que inicia na posição 0 e termina na posição
* 10: "Olá, mundo!"
*/
parteDaString = umaString.substring(0, 11);
}
}
Agora, digamos que queremos verificar se uma string contém uma substring, ou seja,
uma string de tamanho menor ou igual à string original. Por exemplo, digamos que queremos
verificar se uma string contém a substring “animal”. Para resolver este problema, utilizaremos
o método contains da classe String:
public class ExemploContains {
public static void main(String[] args) {
String umaString = "Ontem foi visto um animal na praça central.";
/*
* O método contains da classe String verifica a existência de uma
* substring na string pesquisada.
*/
boolean temAnimalNaFrase = umaString.contains("animal"); // true
/*
* Agora, faremos uma verificação ignorando casos
*/
boolean temPracaNaFrase = umaString.toUpperCase().contains("CENTRAL"); // true
}
}
Uma operação também possível em strings é substituir uma determinada substring por
outra string. Para tanto, a classe String oferece dois métodos. O método replace substitui
todas as ocorrências de uma substring por uma outra string desejada. Por sua vez, o método
replaceAll substitui todas as substrings que correspondem a uma determinada expressão
regular por uma outra string desejada. A seguir, alguns exemplos de substituições de strings:
public class ExemploSubstituicoes {
public static void main(String[] args) {
String umaString = "A Ana comeu banana... mas que sacana!";
// A Ana comeu banana... mas que espertinha!
System.out.println(umaString.replace("sacana", "espertinha"));
// A Ana comeu bANAna... mas que sacANA!
System.out.println(umaString.replace("ana", "ANA"));
/*
* Substitui todas as vogais minúsculas pelo dígito 0:
* "A An0 c0m00 b0n0n0... m0s q00 s0c0n0!"
*/
System.out.println(umaString.replaceAll("[aeiou]", "0"));
/*
* Substitui todas as ocorrências da substring "ana" pela string "eno",
* ignorando casos: "A eno comeu benona... mas que saceno!"
*/
System.out.println(umaString.replaceAll("(?i)ana", "eno"));
/*
* Substitui todas as vogais pela vogal 'i':
* "i ini cimii binini... mis qii sicini!"
*/
System.out.println(umaString.replaceAll("(?i)[aeiou]", "i"));
}
}
Por fim, uma operação comum a se realizar em strings é remover espaços em branco no
início e no final. Muitas vezes usuários ao preencher formulários acabam deixando espaços em
branco indesejados nestas posições. Para resolver este problema, a classe String oferece o
método trim, cujo exemplo de uso é mostrado a seguir:
public class ExemploTrim {
public static void main(String[] args) {
String umaString = " por gentileza, remova estes espaços em branco ";
/*
* O metodo trim da classe String remove os caracteres em branco no
* início e no fim da string.
*/
umaString = umaString.trim();
// “por gentileza, remova estes espaços em branco”
System.out.println(umaString);
}
}
Exercícios:
a) Escreva um programa que imprima os caracteres inicial, final e o situado exatamente
no meio da frase “Eu sou um aspirante a programador de sucesso!”.
b) Escreva um programa que substitua todas as ocorrências da substring “alo” na string
“A Salomé escalonou os robalos que nadavam pelos ralos” pela string “ito”.
c) Escreva um programa que armazene cada metade da string “Um dia eu fui uma
string completa...” em uma variável distinta.
d) Escreva um programa que insira o caractere '[' no início e o caractere ']' no final da
string “Meu Deus, estou entre colchetes!”.
e) Escreva um programa que armazene cada palavra da string “Um dia eu fui uma
string completa...” em uma variável distinta, utilizando chamadas ao método substring.
10 - Lendo valores do usuário
Todos os programas dos exemplos vistos até então nesta apostila não são interativos.
Ou seja, eles não promovem a interação entre o usuário e computador. A partir de agora,
vamos aprender a ler números e strings do usuário a fim de alimentar os nossos programas.
10.1 – Lendo dados do usuário via linha de comando
Podemos ler números e strings do usuário via linha de comando em Java por meio da
classe Scanner do pacote java.util. Para utilizar a classe Scanner em nossos programas,
precisamos importar esta classe por meio da instrução import. O exemplo abaixo, lê um
número inteiro do usuário, utilizando o método nextInt da classe Scanner. Note que na
primeira linha de código nós realizamos a importação da classe Scanner:
import java.util.Scanner;
public class LeitorValorInteiroTeclado {
public static void main(String[] args) {
Scanner leitor = new Scanner(System.in);
// O código abaixo lê um valor inteiro do teclado
System.out.println("Digite a sua idade:");
int idade = leitor.nextInt();
System.out.println("Você tem " + idade + " anos de idade.");
}
}
Para realizar a leitura de números reais do usuário, utilizamos o método nextFloat da
classe Scanner. Lembre-se de utilizar vírgula ao invés de ponto quando for informar o número
real na leitura. A seguir, um exemplo de leitura de um número real com o método nextFloat:
import java.util.Scanner;
public class LeitorValorPontoFlutuanteTeclado {
public static void main(String[] args) {
Scanner leitor = new Scanner(System.in);
// O código abaixo lê um valor inteiro e um valor float do teclado
System.out.println("Digite a sua idade:");
int idade = leitor.nextInt();
System.out.println("Digite o seu peso em kg:");
float peso = leitor.nextFloat();
System.out.println("Você tem " + idade + " anos e pesa " + peso + " kg.");
}
}
Por fim, para realizar a leitura de strings do usuário via linha de comando, utilizamos o
método nextLine da classe Scanner. O programa a seguir lê do usuário a sua comida
preferida:
import java.util.Scanner;
public class LeitorStringTeclado {
public static void main(String[] args) {
Scanner leitor = new Scanner(System.in);
/*
* O código abaixo lê uma string do teclado.
* Ao terminar de digitar a string, o usuário
* deve teclar ENTER.
*/
System.out.println("Qual a sua comida favorita?");
String resposta = leitor.nextLine();
System.out.println("A sua comida favorita é " + resposta + ".");
}
}
10.2 – Lendo dados do usuário via janelas de Dialog
Opcionalmente, você pode realizar a leitura dos dados do usuário via janelas de Dialog,
a fim de deixar o seu programa mais amigável ao usuário. Você pode também exibir o
resultado do processamento do seu programa em uma janela de Dialog. Para realizar esta
tarefa, utilizaremos a classe JOptionPane do pacote javax.swing. O método
showInputDialog da classe JOptionPane exibe uma janela de Dialog com um campo de
texto para a leitura. Por exemplo, considere o exemplo contido na classe
LeitorValorInteiroTeclado da seção 10.1. Naquele exemplo, o programa lia a idade do
usuário via linha de comando. Utilizando o método showInputDialog podemos criar uma
janela de Dialog como a da figura abaixo:
Após lermos a idade do usuário, exibiremos uma frase informando a sua idade por meio
do método showMessageDialog da classe JOptionPane, o qual criará uma janela de Dialog
simples de mensagem. A janela de saída ficará como a janela da figura abaixo:
Abaixo, o programa correspondente:
import javax.swing.JOptionPane;
public class LeitorInteiroDialog {
public static void main(String[] args) {
/*
* Exibe uma janela para ler a resposta do usuário.
* Após, exibe outra janela para exibir a resposta
* digitada pelo usuário.
*/
String resposta = JOptionPane.showInputDialog("Qual a sua idade?");
int idade = Integer.parseInt(resposta); // Converte a string em inteiro
JOptionPane.showMessageDialog(null, "Você tem " + idade + " anos de idade.");
}
}
O método showInputDialog sempre retorna strings. Assim, para converter a idade
informada pelo usuário em um valor inteiro, utilizamos o método parseInt da classe Integer.
Na última linha utilizamos o método showMessageInputDialog para exibir a janela com a
mensagem ao usuário. Em um outro momento, veremos como customizar estas janelas de
entrada e saída de dados. O programa logo a seguir lê a idade e o peso do usuário,
convertendo a string com a informação do peso em um valor do tipo float. O segundo
programa a seguir exibe a simples leitura de strings do usuário:
import javax.swing.JOptionPane;
public class LeitorFloatDialog {
public static void main(String[] args) {
String resposta = JOptionPane.showInputDialog("Qual a sua idade?");
int idade = Integer.parseInt(resposta); // Converte a string em inteiro
resposta = JOptionPane.showInputDialog("Qual o seu peso em kg?");
float peso = Float.parseFloat(resposta); // Converte a string em float
JOptionPane.showMessageDialog(null, "Você tem " + idade + " anos de idade" +
"e pesa " + peso + " kg.");
}
}
import javax.swing.JOptionPane;
public class LeitorStringDialog {
public static void main(String[] args) {
/*
* Exibe uma janela para ler a resposta do usuário.
* Após, exibe outra janela para exibir a resposta
* digitada pelo usuário.
*/
String resposta = JOptionPane.showInputDialog("Qual a sua comida favorita?");
JOptionPane.showMessageDialog(null, "A sua comida favorita é " + resposta);
}
}
Exercícios
a) Escreva um programa que leia do usuário o seu nome completo e informa a ele
quantos caracteres o seu nome possui (lembre-se de não contar espaços em branco).
b) Escreva um programa que leia duas frases do usuário e exibe a na tela a segunda
frase concatenada com a primeira frase.
c) Escreva um programa que leia do usuário o valor do raio de uma circunferência e
exiba na tela o valor da área desta circunferência.
d) Escreva um programa que leia do usuário o tamanho dos lados de um retângulo e
imprima na tela o valor da área deste retângulo.
e) Escreva um programa que leia uma frase do usuário e imprima os caracteres inicial,
final e o situado exatamente no meio da frase.
11 - Controlando o fluxo do programa
Cada programa visto nos exemplos desta apostila até então possui um único fluxo
possível de execução. Isto significa que todas as linhas de código do programa serão
executadas, a menos que ocorra algum tipo de erro durante a execução do programa. Porém,
existem muitos problemas em que desejamos poder controlar o fluxo de execução do nosso
programa, ou seja, controlar quais linhas de código serão executadas de acordo com uma ou
mais condições. Neste caso, o programa terá mais de um fluxo de execução possível.
Por exemplo, considere o programa que lê a idade do usuário. Digamos que desejamos
customizar a mensagem ao usuário de acordo com a sua idade. Se o usuário tiver menos de 18
anos, informamos que ele é menor de idade; caso contrário, informamos que ele já é maior de
idade.
Para resolver este problema, utilizaremos as instruções if e else da linguagem Java. A
seguir, o programa correspondente:
import java.util.Scanner;
public class ExemploIfElse {
public static void main(String[] args) {
Scanner leitor = new Scanner(System.in);
System.out.println("Digite a sua idade:");
int idade = leitor.nextInt();
if (idade < 18) { // se idade maior que 18, então:
System.out.println("Você é menor de idade.");
} else { // senão
System.out.println("Você é maior de idade.");
}
}
}
A instrução if recebe como argumento um valor booleano. No nosso caso, passamos
como argumento uma expressão lógica, que por sua vez resultará em um valor booleano. Se
este valor for igual a true, então o código delimitado pelas chaves da instrução if será
executado; caso contrário, o código delimitado pelas chaves da instrução else será executado.
No exemplo acima, temos apenas duas situações que são mutuamente exclusivas.
Porém, existem vários problemas os quais necessitam de múltiplas condições para realizar o
roteamento de múltiplos fluxos de execução possíveis. O programa abaixo lê a idade do usuário
e informa em que faixa de idade o usuário se encontra:
import java.util.Scanner;
public class ExemploCondicoesMultiplas {
public static void main(String[] args) {
Scanner leitor = new Scanner(System.in);
System.out.println("Digite a sua idade:");
int idade = leitor.nextInt();
if (idade <= 10) {
System.out.println("Você tem menos de 11 anos.");
} else if (idade <= 20) {
System.out.println("Você tem entre 11 e 20 anos.");
} else if (idade <= 30) {
System.out.println("Você tem entre 21 e 30 anos.");
} else if (idade <= 50) {
System.out.println("Você tem entre 31 e 50 anos.");
} else {
System.out.println("Você tem mais de 50 anos.");
}
}
}
Agora, considere este problema. Após lermos a idade do usuário, devemos informar se
ele é menor ou maior de idade. Além disso, se a idade do usuário for ímpar, também
informaremos tal fato. O programa a seguir resolve este problema:
import java.util.Scanner;
public class ExemploIfsNaoExclusivos {
public static void main(String[] args) {
Scanner leitor = new Scanner(System.in);
System.out.println("Digite a sua idade:");
int idade = leitor.nextInt();
if (idade < 18) { // se idade maior que 18, então:
System.out.println("Você é menor de idade.");
} else { // senão
System.out.println("Você é maior de idade.");
}
/*
* Utilizamos o operador MOD (%) para verificar se o número abaixo é
* ímpar. O operador MOD retorna o resto da divisão inteira entre o
* primeiro número e o segundo.
*/
if (idade % 2 == 1) {
System.out.println("Você possui uma idade ímpar.");
}
}
}
Note que neste exemplo temos duas condições não exclusivas, pois a condição do
segundo if é executada de forma independente ao primeiro if. Como você já deve ter
observado, o código controlado por toda instrução if e else é delimitado por chaves. Quando o
código de uma instrução if ou else possui apenas uma linha, o uso de chaves é opcional, como
mostra o exemplo a seguir:
import java.util.Scanner;
public class ExemploIfSemChaves {
public static void main(String[] args) {
Scanner leitor = new Scanner(System.in);
System.out.println("Qual a sua cor preferida?");
String cor = leitor.nextLine();
if (cor.equalsIgnoreCase("amarelo"))
System.out.println("Legal! Amarelo é uma cor tranquila.");
else
System.out.println("Hmmm... prefiro amarelo.");
}
}
Agora, imagine que devemos escrever um programa que simule uma calculadora
simples, capaz de efetuar adições, subtrações, multiplicações e divisões. O nosso programa
funcionará da seguinte forma. Ele solicitará ao usuário dois números reais. Após isto, ele
exibirá ao usuário um menu de operações matemáticas a serem realizadas sobre os números
que ele informou, conforme abaixo:
Escolha a operação desejada:
1 – Soma
2 – Subtração
3 – Multiplicação
4 – Divisão
Por exemplo, se o usuário deseja multiplicar os dois números que ele informou, então
ele escolherá a opção 3, digitando assim este número no teclado para que o programa possa
enfim realizar a multiplicação dos dois valores. Vamos resolver este problema utilizando as
instruções if e else:
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner leitor = new Scanner(System.in);
System.out.println("Digite o primeiro valor:");
double primeiroValor = leitor.nextFloat();
System.out.println("Digite o segundo valor:");
double segundoValor = leitor.nextFloat();
System.out.println("Escolha a operação desejada:");
System.out.println("1 - Soma");
System.out.println("2 - Subtração");
System.out.println("3 - Multiplicação");
System.out.println("4 - Divisão");
int opcao = leitor.nextInt();
double resultado = 0;
if (opcao == 1) {
resultado = primeiroValor + segundoValor;
} else if (opcao == 2) {
resultado = primeiroValor - segundoValor;
} else if (opcao == 3) {
resultado = primeiroValor * segundoValor;
} else if (opcao == 4) {
// Evita a divisão por 0, pois isto causa um erro.
if (segundoValor != 0) {
resultado = primeiroValor / segundoValor;
} else {
System.out.println("Não é possível dividir por zero!");
}
} else {
System.out.println("Opção inválida.");
}
if (opcao <= 4) {
System.out.println("Resultado: " + resultado);
}
}
}
No programa acima, foi escrita uma instrução if para cada valor de escolha possível no
menu. Problemas de decisão deste tipo podem ser implementados utilizando a instrução
switch. Reescreveremos a classe Calculadora, utilizando uma instrução switch para realizar
o controle da opção escolhida:
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner leitor = new Scanner(System.in);
System.out.println("Digite o primeiro valor:");
double primeiroValor = leitor.nextFloat();
System.out.println("Digite o segundo valor:");
double segundoValor = leitor.nextFloat();
System.out.println("Escolha a operação desejada:");
System.out.println("1 - Soma");
System.out.println("2 - Subtração");
System.out.println("3 - Multiplicação");
System.out.println("4 - Divisão");
int opcao = leitor.nextInt();
double resultado = 0;
switch (opcao) {
case 1:
resultado = primeiroValor + segundoValor;
break;
case 2:
resultado = primeiroValor - segundoValor;
break;
case 3:
resultado = primeiroValor * segundoValor;
break;
case 4:
if (segundoValor != 0) {
resultado = primeiroValor / segundoValor;
} else {
System.out.println("Não é possível dividir por zero!");
}
break;
default:
System.out.println("Opção inválida.");
}
if (opcao <= 4) {
System.out.println("Resultado: " + resultado);
}
}
}
No exemplo acima, a instrução switch escolhe o fluxo correto de acordo com a opção
digitada pelo usuário. Caso a opção digitada seja 1, 2 3 ou 4, o cálculo correto é realizado com
os dois números reais informados pelo usuário. Note que ao final de cada instrução case existe
uma instrução break. A instrução break interrompe a execução da instrução switch. Ou seja, o
programa irá executar o código seguinte ao final da instrução switch. A instrução break é
opcional. No nosso caso, ela é necessária para garantir que, assim que o cálculo correto for
realizado, o programa sairá da instrução switch.
Note também que no final da instrução switch foi colocada uma instrução default. O
código de uma instrução default só é executado caso nenhum dos casos seja satisfeito. No
nosso exemplo, se o usuário digitar uma opção inválida, ou seja, diferente de 1, 2, 3 ou 4,
então o código da instrução default é executado, informando que a opção digitada pelo
usuário é inválida. A instrução break não foi escrita no final da instrução default, pois como a
instrução default simboliza o último caso possível dentro da instrução switch, não existe a
necessidade de se interromper a execução da instrução switch neste ponto. Apenas uma
instrução default pode ser escrita dentro de uma instrução switch.
Condições mutuamente exclusivas do tipo if-else que definem o valor de uma variável
podem ser escritas utilizando uma operação ternária. Considere o exemplo a seguir:
public class VerificaParidade {
public static void main(String[] args) {
// Sorteia um número entre [0..100]
// O tipo long armazena números inteiros de alta precisão
long numeroAleatorio = System.currentTimeMillis() % 101;
String resposta = numeroAleatorio + " é ";
if (numeroAleatorio % 2 == 0) {
resposta += "par";
} else {
resposta += "ímpar";
}
System.out.println(resposta);
}
}
Neste exemplo, um valor inteiro é sorteado e então o programa deve informar se o
número é par ou ímpar. As instrução if e else definem qual a resposta correta a ser
armazenada na variável resposta, cujo valor será impresso na tela. Vamos reescrever este
programa, utilizando uma operação ternária:
public class VerificaParidade {
public static void main(String[] args) {
// Sorteia um número entre [0..100]
// O tipo long armazena números inteiros de alta precisão
long numeroAleatorio = System.currentTimeMillis() % 101;
String resposta = numeroAleatorio + " é ";
resposta += numeroAleatorio % 2 == 0 ? "par" : "impar";
System.out.println(resposta);
}
}
Uma operação ternária é escrita da seguinte forma:
v = c ? a : b;
Na expressão acima, v representa a variável que irá receber o valor da expressão. O
símbolo c representa a condição lógica a ser testada na expressão. O símbolo a representa o
valor a ser atribuído a v caso a condição c seja satisfeita. Por fim, b representa o valor a ser
atribuído a v caso a condição c não seja satisfeita.
Exercícios:
a) Escreva um programa que leia um número inteiro do usuário e informe ao usuário se
este número é divisível por 7.
b) Escreva um programa leia do usuário sua altura e peso, calcule o seu índice de
massa corporal (IMC) e informe na tela o seu grau de obesidade. O IMC é dado pela fórmula
abaixo:
IMC = peso / altura²
Abaixo, os graus de obesidade referentes a cada faixa de IMC:
IMC < 18.5: Abaixo do peso
18.5 <= IMC <= 24.9: Peso normal
24.9 < IMC <= 29.9: Sobrepeso
29.9 < IMC <= 34.9: Obesidade de grau I
34.9 < IMC <= 39.9: Obesidade de grau
c) Escreva um programa que leia as notas de quatro provas do usuário, calcula a média
das notas. Se a média for maior ou igual a 7, então informe ao usuário que ele foi aprovado. Se
a média for maior que 5 e menor que 7, informe que ele está de recuperação. Por fim, se a
média for inferior a 5, informe que ele foi reprovado.
12 - Utilizando laços de repetição
Imagine que devemos escrever um programa para imprimir na tela a sequência de 1
até 4 em uma mesma linha. Este problema é extremamente simples e é resolvido pelo
programa abaixo:
public class ProblemaSimplesDemais {
public static void main(String[] args) {
System.out.println("1 2 3 4");
}
}
Agora, considere que o nosso problema seja criar um programa que leia do usuário um
valor inteiro positivo n e imprima na tela a sequência de 1 até n em uma mesma linha. Vamos
tentar resolver este problema utilizando a mesma estratégia da solução anterior:
public class SolucaoNaoMuitoInteligente {
public static void main(String[] args) {
System.out.println("Digite um numero inteiro positivo:");
Scanner leitor = new Scanner(System.in);
int n = leitor.nextInt();
// Garantindo que o valor de n seja positivo...
if (n < 0) {
n = n * -1;
} else if (n == 0) {
n = 1;
}
// E lá vamos nós...
if (n == 1) {
System.out.println("1");
} else if (n == 2) {
System.out.println("1 2");
} else if (n == 3) {
System.out.println("1 2 3");
} else if (n == 4) {
System.out.println("1 2 3 4");
} else if (n == 5) {
System.out.println("1 2 3 4 5");
} else if (n == 6) {
System.out.println("1 2 3 4 5 6");
}
// .. continua... até quando?
}
}
Obviamente, o programa acima não consegue resolver o problema de fato, uma vez que
ele só informa a resposta correta para valores de n entre [1..6]. O grande problema do
programa acima é que ele não é escalável aos valores de n, ou seja, ele não consegue resolver
o problema para qualquer valor de n. A questão é: como saberemos quais os possíveis valores
de n que o usuário poderá digitar? Não há como saber! Ele pode digitar qualquer valor superior
a 0. Assim, quantas condições lógicas necessitaríamos para resolver o problema de fato? Na
realidade, infinitas condições!
Desta forma, precisamos escrever um código que seja capaz de imprimir todos os
números da sequência, porém utilizando um número fixo e mínimo de linhas de código. Para
tanto, precisamos de alguma forma escrever um código que repita a impressão dos números
de forma categórica e estratégica.
Para realmente resolver este problema, precisamos utilizar um laço de repetição. A
linguagem Java oferece três laços de repetição distintos: o laço while, o laço do-while e o laço
for. O programa a seguir resolve o nosso problema utilizando um laço while:
import java.util.Scanner;
public class ExemploWhile {
public static void main(String[] args) {
System.out.println("Digite um numero inteiro positivo:");
Scanner leitor = new Scanner(System.in);
int n = leitor.nextInt();
// Garantindo que o valor de n seja positivo...
if (n < 0) {
n = n * -1;
} else if (n == 0) {
n = 1;
}
int contador = 1;
while (contador <= n) {
System.out.print(contador + " ");
contador++;
}
}
}
O laço while recebe como argumento uma condição lógica, chamada de condição de
manutenção do laço. No nosso exemplo, enquanto o valor da variável contador for menor
ou igual ao valor da variável n, o laço while repetirá a execução do código localizado entre as
chaves.
Note que agora para qualquer valor de n a mensagem correta será impressa. A variável
contador é inicializada com o valor 1, que é o primeiro valor que o nosso programa deve
imprimir. A cada iteração, o valor da variável contador é impresso. Logo em seguida, o valor
da variável é incrementado em uma unidade. Assim, na próxima iteração, o valor a ser
impresso é uma unidade maior que o valor atual.
O laço while só é executado se e somente se a sua condição lógica de manutenção for
satisfeita. Assim, para que um laço while execute ao menos uma iteração, a sua condição
lógica de manutenção deve ser satisfeita ao menos uma vez.
Agora, resolveremos o problema mais uma vez, porém utilizando o laço do-while:
import java.util.Scanner;
public class ExemploDoWhile {
public static void main(String[] args) {
System.out.println("Digite um numero inteiro positivo:");
Scanner leitor = new Scanner(System.in);
int n = leitor.nextInt();
// Garantindo que o valor de numero seja positivo...
if (n < 0) {
n = n * -1;
} else if (n == 0) {
n = 1;
}
int contador = 0;
do {
contador++;
System.out.print(contador + " ");
} while (contador < n);
}
}
Neste exemplo, o laço do-while repete a execução do trecho de código localizado entre
as chaves enquanto o valor da variável contador for menor que o valor da variável n. A
variável contador é inicializada com o valor 0. Este não é o valor correto do primeiro valor a
ser impresso, porém no início de cada iteração, o valor da variável contador é incrementado
em uma unidade. Logo em seguida, o valor correto é impresso na tela.
O laço é executado até que o valor da variável contador seja menor que o valor da
variável n. Isto parece um tanto anti-intuitivo no início mas, se você analisar o código acima,
você verá que esta condição se deve ao fato de que o incremento do valor da variável
contador é realizado antes de que este seja impresso na tela.
O laço do-while sempre executa ao menos uma iteração. Assim, para que um laço
do-while execute após a primeira iteração, a sua condição lógica de manutenção deve ser
satisfeita ao menos uma vez.
Por fim, resolveremos novamente o problema, agora utilizando o laço for:
import java.util.Scanner;
public class ExemploFor {
public static void main(String[] args) {
System.out.println("Digite um numero inteiro positivo:");
Scanner leitor = new Scanner(System.in);
int n = leitor.nextInt();
// Garantindo que o valor de numero seja positivo...
if (n < 0) {
n = n * -1;
} else if (n == 0) {
n = 1;
}
for(int contador = 1; contador <= n; contador++) {
System.out.print(contador + " ");
}
}
}
No exemplo acima, o laço for pode ser lido da seguinte forma: para o valor de contador
partindo de 1 até atingir o valor de n, incrementando o valor de contador em uma unidade a
cada iteração, repita o trecho de código entre as chaves. O primeiro argumento de um laço for
contém as inicializações desejadas para o laço. No caso, a variável contador é inicializada com
o valor 1. Esta inicialização é executada somente uma vez, antes mesmo da execução da
primeira iteração do laço.
O segundo argumento de um laço for é a condição lógica de manutenção do laço.
Ou seja, é o teste lógico realizado antes de cada iteração para avaliar se a iteração deve ser
executada ou se o laço deve parar de executar iterações. No caso, o laço executará enquanto o
valor da variável contador for menor ou igual ao valor da variável n.
O terceiro e último argumento de um laço for contém o código a ser executado no final
de cada iteração. No caso, após o valor da variável contador ser exibido, ele é incrementado
em uma unidade.
Desta forma, o código contido no primeiro argumento do laço for é executado apenas
uma vez e antes do laço começar a sua execução. A condição de manutenção do laço contida
no segundo argumento do laço for é executada sempre e antes da execução de cada iteração.
Por fim, o código contido no terceiro e último argumento do laço for é executado sempre e no
final da execução de cada iteração.
O uso de qualquer um dos argumentos do laço for é opcional. O programa abaixo ilustra
a omissão dos argumentos do laço for:
public class ExemploOmissaoArgumentosFor {
public static void main(String[] args) {
int i = 0;
// Omitimos o primeiro argumento, pois ele não é necessário neste caso
for (; i < 10; i++) {
System.out.println("Linha " + i);
}
// Omitimos o terceiro argumento, pois ele não é necessário neste caso
for (i = 0; i < 10;) {
System.out.println("Linha " + i);
i++;
}
// A omissão do segundo argumento pode fazer com que o laço execute
// infinitamente. Para terminar a execução do programa, digite CTRL + C
for (i = 0;; i++) {
System.out.println("Linha " + i);
}
}
}
Os três argumentos do laço for podem ser combinados para diversas finalidades. O
programa abaixo exibe na tela uma sequência numérica regressiva:
public class SequenciaRegressivaFor {
public static void main(String[] args) {
int numero = 10;
for (int i = numero; i > 0; i--) {
System.out.print(i + " ");
}
}
}
Abaixo, um exemplo mais complexo do uso do laço for:
import java.util.Scanner;
public class ExemploComplexoFor {
public static void main(String[] args) {
System.out.println("Digite um numero inteiro positivo:");
Scanner leitor = new Scanner(System.in);
int n = leitor.nextInt();
// Garantindo que o valor de numero seja positivo...
if (n < 0) {
n = n * -1;
} else if (n == 0) {
n = 1;
}
for (int contador = n, contador2 = n, contador3 = n;
contador >= 0 && contador2 >= 0 && contador3 >= 0;
contador--, contador2 -= 2, contador3 -= 3) {
System.out.print("[" + contador + ", ");
System.out.print(contador2 + ", ");
System.out.print(contador3 + "] ");
}
}
}
Exercícios:
a) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na
tela a sequência:
1 2 3 … n-1 n
Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa:
1 2 3 4 5
b) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na
tela a sequência:
n n-1 n-2 … 3 2 1
Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa:
5 4 3 2 1
c) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na
tela a sequência:
1, 2, 3, … n-1, n
Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa:
1, 2, 3, 4, 5
d) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na
tela a sequência:
n-1, n-2, n-3, … 3, 2, 1
Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa:
5, 4, 3, 2, 1
e) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na
tela a sequência:
[1|2|3|...|n-1|n]
Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa:
[1|2|3|4|5]
f) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na
tela a sequência:
1, 2, 3, … n, n-1, n-2,..., 3, 2, 1
Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa:
1, 2, 3, 4, 5, 4, 3, 2, 1
g) Escreva um algoritmo que leia do usuário um valor n entre [1..100] e então imprima
na tela a seguinte sequência:
1,
1, 2
1, 2, 3
...
1, 2, 3, …, n - 1, n
1, 2, 3, …, n – 1
…
1, 2, 3
1, 2
1
Por exemplo, caso o valor n seja 5, a seguinte sequência abaixo deve ser impressa:
1
1, 2
1, 2, 3
1, 2, 3, 4
1, 2, 3, 4, 5
1, 2, 3, 4
1, 2, 3
1, 2
1
Caso o valor de n seja 1, então a sequência abaixo deve ser impressa:
1
h) Escreva um programa leia do usuário valores inteiros entre [0..100] até que o usuário
digite o valor -1 e calcule a média aritmética destes valores (P.S.: o valor -1 não deve ser
incluído no cálculo).
i) Escreva um programa que leia do usuário 10 valores inteiros entre [0..100] e calcule o
produto destes valores.
j) Escreva um programa que leia do usuário um valor n entre [1..100] e imprima na tela
os primeiros n números da sequência de Fibonacci. Em uma sequência de Fibonacci, cada valor
é a soma dos dois últimos valores da sequência anteriores a ele. Como exemplo, a linha abaixo
contém os oito primeiros números da sequência de Fibonacci:
0, 1, 1, 2, 3, 5, 8, 13
13 – Matrizes
Todas as variáveis que criamos em nossos exemplos até então possuem a capacidade
de armazenamento de apenas um valor por vez. Por exemplo, considere o programa abaixo:
public class ValorNumero {
public static void main(String[] args) {
int numero = 1;
numero = 2;
numero = 4;
numero = -9;
System.out.println(numero);
}
}
Durante a sua execução, o programa atribui quatro valores distintos à variável numero,
porém apenas o valor -9 é impresso, pois este foi o último valor associado à variável. Ou seja,
não é possível armazenar mais de um valor simultaneamente na variável numero. O programa
abaixo exibe uma possível solução a este problema:
public class DiversosValores {
public static void main(String[] args) {
int numero1 = 1;
int numero2 = 2;
int numero3 = 4;
int numero4 = -9;
System.out.println(numero1);
System.out.println(numero2);
System.out.println(numero3);
System.out.println(numero4);
}
}
Neste exemplo, cada valor foi armazenado em uma variável distinta e o valor de cada
variável foi impresso separadamente no final do programa. Note que se tivéssemos que
armazenar mais valores, teríamos que criar mais variáveis, além de mais instruções para exibir
tais valores na tela. Desta forma, esta solução deixa de ser prática à medida que o número de
valores aumenta.
Uma solução mais elegante ao problema anterior é utilizar uma matriz para assim poder
armazenar vários valores em uma única variável. Matrizes são estruturas de dados que
representam uma coleção de elementos, onde cada elemento é representado por uma única
chave. O programa abaixo apresenta uma possível solução ao problema anterior, utilizando
uma matriz para armazenar os valores:
public class MatrizValores {
public static void main(String[] args) {
int[] numeros = new int[4];
numeros[0] = 1;
numeros[1] = 2;
numeros[2] = 4;
numeros[3] = -9;
for (int i = 0; i < numeros.length; i++) {
System.out.println(numeros[i]);
}
}
}
Vamos analisar este programa passo-a passo. Na primeira linha do algoritmo do
programa, foi criada uma matriz de inteiros de tamanho quatro, ou seja, capaz de armazenar
quatro valores inteiros. Preste atenção na sintaxe de declaração e instanciação desta matriz.
No código anterior ao símbolo de atribuição (=) foi declarada uma variável chamada numeros.
Note que diferentemente à sintaxe de declaração de uma variável comum do tipo int, foram
colocados colchetes de abertura e encerramento ([]) após a palavra reservada int. Isto denota
que a variável sendo criada é uma matriz e será capaz de armazenar um conjunto de valores
inteiros. Nós dizemos que o código anterior ao símbolo de atribuição representa a declaração
da variável numeros.
No código posterior ao símbolo de atribuição a variável numeros é instanciada, ou seja,
é alocado o espaço de memória a ser ocupado pela variável. Neste exemplo, a variável
numeros obtém espaço de memória suficiente para armazenar quatro valores do tipo int.
Como cada valor do tipo int utiliza 4 bytes de memória de armazenamento, a matriz numeros
ocupará 16 bytes de memória, ou seja, 4 bytes * 4 espaços. Assim, dizemos que o código
posterior ao símbolo de atribuição representa a instanciação da variável numeros. Este tipo
de instanciação é dito instanciação direta, pois o número de elementos da matriz é definido
explicitamente. Uma outra forma de instanciação é a indireta, como mostra a linha abaixo:
int[] numeros = { 1, 2, 4, -9 };
Neste exemplo, em uma única linha a matriz numeros foi declarada, instanciada
(indiretamente) e inicializada, ou seja, os seus valores já foram determinados. Este tipo de
instanciação é dito indireto pois o número de elementos da matriz é definido implicitamente.
No exemplo, ao passarmos quatro valores à matriz numeros, fica-se definido que esta matriz
terá capacidade de armazenamento de quatro valores inteiros.
Voltando ao exemplo da classe MatrizValores, da segunda à quinta linha do algoritmo
é realizada a inicialização da matriz numeros, ou seja, ela recebe os valores os quais deve
armazenar. Cada valor é atribuído separadamente e endereçado por meio de um índice
específico. Os índices de uma matriz vão de 0 até o tamanho da matriz decrementado de uma
unidade. Assim, a matriz numeros possui tamanho 4 e seus índices variam de 0 a 3, sendo 0 o
índice do primeiro elemento e 3 o índice do último elemento. No caso da matriz numeros, os
valores 1, 2, 4 e -9 são armazenados na posição 0, 1, 2 e 3 respectivamente. Abaixo, a
representação gráfica da matriz numeros:
Valores 1 2 4 -9
Índices 0 1 2 3
No final do programa, foi criado um laço for para auxiliar a exibição de cada valor
armazenado na matriz. Note que a variável inteira i auxilia no acesso aos índices da matriz.
Para tanto, durante a execução do laço for o valor de i varia de 0 até numeros.length – 1.
Toda matriz em Java possui o atributo constante length, o qual armazena de forma implícita o
tamanho da matriz. Por ser uma constante, o seu valor nunca deve ser alterado de forma
implícita, mas sim ser utilizado para se obter de forma segura o tamanho da matriz sendo
utilizada.
Se você prestou atenção ao exemplo da classe MatrizValores e aos últimos
parágrafos, você deve ter percebido que para acessar uma posição específica de uma matriz
devemos utilizar o nome da variável da matriz seguido de um colchete de abertura ([), o
número referente ao índice desejado e um colchete de fechamento. O programa abaixo
exemplifica o acesso aos valores de uma matriz por meio de seus índices:
public class ExemploAcessoPosicoes {
public static void main(String[] args) {
int[] matriz = { 23, 98, -173, 1, 99, 50 };
int terceiroNumero = matriz[2]; // -173
int ultimoNumero = matriz[matriz.length - 1]; // 50
int primeiroNumero = matriz[0]; // 23
}
}
Os exemplos anteriores exibiram matrizes de inteiros. É possível criar matrizes de todos
os tipos que vimos até então nesta apostila. O programa abaixo ilustra algumas matrizes de
tipos variados:
public class MatrizesVariadas {
public static void main(String[] args) {
double[] matrizDouble = { -3.4, 5.7, 90D, 187.123 };
for (int i = 0; i < matrizDouble.length; i++) {
System.out.println(matrizDouble[i]);
}
String[] diasSemana = { "Segunda", "Terça", "Quarta", "Quinta",
"Sexta", "Sábado", "Domingo" };
for (int i = 0; i < diasSemana.length; i++) {
System.out.println(diasSemana[i]);
}
char[] conceitosNotas = { 'A', 'B', 'C', 'D', 'E' };
for (int i = 0; i < conceitosNotas.length; i++) {
System.out.println(conceitosNotas[i]);
}
boolean[] matrizBooleanos = { true, true, false, true, false, false };
for (int i = 0; i < matrizBooleanos.length; i++) {
System.out.println(matrizBooleanos[i]);
}
}
}
Um laço de repetição que não vimos na seção anterior é o laço for-each, o qual é
utilizado para se percorrer matrizes e listas (não importa ainda o que é uma lista!). Este tipo de
laço simplifica em muito a forma de se percorrer uma matriz, porém só pode ser utilizado para
a leitura da matriz, ou seja, não é possível alterar qualquer valor da matriz no código interno a
um laço for-each. Abaixo, a classe MatrizValores reescrita de tal forma a utilizar
instanciação indireta e um laço for-each para exibir os valores da matriz numeros:
public class MatrizValores {
public static void main(String[] args) {
int[] numeros = { 1, 2, 4, -9 };
for (int elemento : numeros) {
System.out.println(elemento);
}
}
}
Você deve ter reparado que a classe MatrizValores ficou mais “enxuta” nesta versão,
graças à instanciação indireta da matriz numeros e do uso do laço for-each para exibir os
valores da matriz. Diferentemente do laço for convencional, o laço for-each (em português,
“para cada”) possui apenas dois argumentos ao invés de três. Além disso, estes dois
argumentos são obrigatórios e são separados por dois pontos (:) ao invés de ponto e vírgula (;).
Para entender o funcionamento deste laço de repetição, devemos entender
primeiramente o que é o segundo argumento do laço para depois entender o primeiro
argumento. O segundo argumento de um laço for-each contém a matriz ou lista que
desejamos percorrer. No nosso exemplo, desejamos percorrer a matriz numeros. O primeiro
argumento contém a variável que vai armazenar o valor da matriz a ser visitado em cada
iteração do laço de repetição. No nosso exemplo, a variável elemento guarda o valor atual
sendo visitado na iteração. Antes do início da próxima iteração, o valor da variável elemento é
atualizado com o valor do próximo elemento da matriz numeros.
Dentro do contexto de matrizes, a classe String da linguagem Java oferece o método
split, o qual quebra a string original de acordo com a ocorrência de uma substring, retornando
assim uma matriz de strings. Para melhor ilustrar a utilidade do método split, veja o exemplo
abaixo:
public class ExemploSplit {
public static void main(String[] args) {
String frase = "Isto é uma frase completa";
// Quebra a string original em cada ocorrência de um espaço em branco
String[] palavrasDaFrase = frase.split(" ");
for (String palavra : palavrasDaFrase) {
System.out.println(palavra);
}
}
}
Todas as matrizes que vimos nos exemplos desta seção até então são ditas matrizes
unidimensionais, ou seja, matrizes de uma dimensão. Estas matrizes são comumente
chamadas de matrizes lineares ou vetores. Em uma matriz bidimensional, cada elemento
da matriz é endereçado por dois índices simultaneamente, um representando a linha da matriz
em que o elemento se situa e o outro representando a coluna da matriz em que o elemento se
situa. Por exemplo, considere a representação gráfica de uma matriz bidimensional abaixo:
Linha/coluna 0 1 2 3
0 -9 0 6 24
1 7 500 1092 71
2 12 -128 67 100
No exemplo, o valor 7 está situado na linha 1, coluna 0. Desta forma, 1 e 0 são os seus
índices de linha e coluna respectivamente. Da mesma forma, o valor 100 está situado na linha
2, coluna 3, sendo assim 2 e 3 os seus índices de linha e coluna. O programa abaixo cria uma
matriz bidimensional para armazenar estes valores e depois percorre a matriz resultante
utilizando dois laços for convencionais:
public class ExemploMatrizBidimensional {
public static void main(String[] args) {
int[][] matrizBidimensional = { { -9, 0, 6, 24 }, { 7, 500, 1092, 71 },
{ 12, -128, 67, 100 } };
/**
* Os laços abaixo imprimirão no console:
* -9 0 6 24
* 7 500 1092 71
* 12 -128 67 100
*/
for (int i = 0; i < matrizBidimensional.length; i++) {
for (int j = 0; j < matrizBidimensional[i].length; j++) {
System.out.print(matrizBidimensional[i][j] + "t");
}
System.out.println("");
}
}
}
Na primeira linha do algoritmo foi declarada a matriz matrizBidimensional. Note que
ao invés de somente um par de abertura-fechamento de colchetes, foram utilizados dois pares.
A regra é que, para cada dimensão a ser utilizada, um par de abertura-fechamento de
colchetes seja utilizado na declaração da variável da matriz. Assim, no exemplo são utilizados
dois pares pois a nossa matriz é bidimensional.
Outra diferença ocorre na instanciação da matriz. Você pode entender uma matriz
bidimensional como um conjunto de matrizes unidimensionais. Imagine que em cada linha da
matriz bidimensional, você tem uma matriz unidimensional. Assim, note que na instanciação
da matriz do exemplo acima cada linha está separada por chaves. Desta forma, podemos
entender que cada elemento da matriz bidimensional é uma matriz unidimensional (uma linha
da matriz) e, em cada linha, temos um conjunto de valores.
Como cada valor está armazenado em uma linha, que por sua vez está armazenada na
matriz bidimensional, para acessar um valor na matriz necessitamos de dois índices: um para
referenciar a linha correta onde o valor se encontra e outro para referenciar sua posição na
linha. Assim, para percorrer a matriz bidimensional precisamos de dois laços de repetição, um
para percorrer as linhas da matriz e, para cada linha da matriz, outro laço para percorrer os
seus valores.
Analisando o código do último exemplo, o primeiro laço de repetição (o que percorre as
linhas matriz) não é diferente do laço que percorria as matrizes unidimensionais nos exemplos
anteriores. No exemplo, o laço for utiliza um índice i que varia de 0 a
matrizBidimensional.length – 1, ou seja, de 0 a 2, os índices das linhas da matriz. A grande
diferença está no segundo laço for, o mais interno. Ele utiliza um índice j para percorrer cada
valor da linha i. Assim, j varia de 0 a matrizBidimensional[i].length – 1, isto é, de 0 até o
tamanho da linha decrementado em uma unidade. Por fim, note que cada valor da matriz é
acessado utilizando os índices i e j, respectivamente linha e coluna.
Se você prestou atenção a este último exemplo e ao último parágrafo, você pode estar
se perguntando: por quê o valor de j vai até matrizBidimensional[i].length – 1 e não até 2,
ou seja, uma constante fixa que se utilizada também resolveria o problema? Bem, existem dois
motivos para tanto. Primeiramente, a forma na qual os dois laços for foram escritos é escalável
no sentido que não importam as dimensões da matriz, ela será percorrida corretamente. Por
fim, não necessariamente os tamanhos das linhas da matriz devem ser iguais! No exemplo
abaixo, cada linha da matriz possui um tamanho diferente:
public class MatrizTamanhosDistintos {
public static void main(String[] args) {
/**
* Declara uma matriz bidimensional de dimensões variáveis.
*/
int[][] matrizBidimensional = { { 1, 2, 3, 4 }, { 5, 6 }, { 7, 8, 9 } };
for (int i = 0; i < matrizBidimensional.length; i++) {
for (int j = 0; j < matrizBidimensional[i].length; j++) {
System.out.print(matrizBidimensional[i][j] + "t");
}
System.out.println("");
}
}
}
Nos dois últimos exemplos as matrizes bidimensionais foram instanciadas
indiretamente. O exemplo abaixo exibe uma matriz sendo instanciada diretamente, tendo seus
valores preenchidos de forma automática por meio de dois laços for e, por fim, sendo exibida:
public class MatrizBidimensionalInstDireta {
public static void main(String[] args) {
// Declara uma matriz bidimensional com dimensões explícitas de 4 x 3
int[][] matrizBidimensional = new int[4][3];
for (int i = 0; i < matrizBidimensional.length; i++) {
for (int j = 0; j < matrizBidimensional[i].length; j++) {
matrizBidimensional[i][j] = i + j;
}
}
for (int i = 0; i < matrizBidimensional.length; i++) {
for (int j = 0; j < matrizBidimensional[i].length; j++) {
System.out.print(matrizBidimensional[i][j] + "t");
}
System.out.println("");
}
}
}
Também é possível percorrer uma matriz bidimensional utilizando laços for-each. O
exemplo abaixo mostra uma matriz de Strings sendo percorrida por dois laços for-each:
public class MatrizBidimensionalForEach {
public static void main(String[] args) {
// Declara uma matriz de strings com dimensões implícitas de 3 x 3
String[][] matrizStrings = {
{ "linha 0 coluna 0", "linha 0 coluna 1", "linha 0 coluna 2" },
{ "linha 1 coluna 0", "linha 1 coluna 1", "linha 1 coluna 2" },
{ "linha 2 coluna 0", "linha 2 coluna 1", "linha 2 coluna 2" },
};
for (String[] linha : matrizStrings) {
for (String valor : linha) {
System.out.print(valor + "t");
}
System.out.println("");
}
}
}
A matriz matrizStrings é uma matriz bidimensional; assim ela pode ser interpretada
como um conjunto de linhas. Desta forma, o primeiro laço for-each do exemplo acima percorre
as linhas da matriz, armazenando cada linha na matriz unidimensional linha. O laço for-each
mais interno percorre cada valor de cada linha, armazenando cada valor na variável valor.
É possível criar matrizes de várias dimensões, porém quanto maior o número de
dimensões de uma matriz menor é o número de aplicações práticas para ela. Apenas a título
de curiosidade, analise a matriz tridimensional do exemplo abaixo e tente entender o código do
exemplo:
public class ExemploMatrizTridimensional {
public static void main(String[] args) {
// Que tal uma matriz tridimensional de dimensões 2 x 2 x 3? :D
int[][][] matriz = {
{
{ 1, 2, 3 },
{ 4, 5, 6 }
},
{
{ 7, 8, 9 },
{ 10, 11, 12 }
}
};
// Percorrendo a matriz tridimensional
for (int[][] subMatriz : matriz) {
for (int[] linha : subMatriz) {
for (int elemento : linha) {
System.out.print(elemento + "t");
}
System.out.println("");
}
System.out.println("");
}
}
}
Exercícios:
a) Escreva um programa que crie uma matriz unidimensional de inteiros de tamanho 10,
preencha cada posição da matriz com um valor aleatório entre [0..100] e exiba em uma linha
os elementos da matriz em ordem inversa.
b) Escreva um programa que leia do usuário 10 valores inteiros, armazene tais valores
em uma matriz unidimensional e exiba na tela apenas os valores que sejam divisíveis por 3.
c) Escreva um programa que leia as notas de 15 alunos, exiba as notas lidas e informe
qual foi a nota média, a maior nota e a menor nota.
d) Escreva um programa que leia do usuário dez números reais, armazene tais valores
em uma matriz unidimensional, calcule e mostre a quantidade de números negativos e a soma
dos números positivos da matriz.
e) Escreva um programa que sorteie 20 números inteiros, exiba os na tela em uma
única linha (separados por vírgula) e depois leia do usuário um número inteiro x e verifique se
x foi sorteado.
f) Escreva um programa que leia dois números inteiros a e b, crie uma matriz de
dimensões a x b, preencha aleatoriamente esta matriz com valores 0 ou 1 e exiba a matriz na
tela de maneira bem formatada, ou seja, respeitando as posições dos elementos quanto a linha
e coluna.
g) Escreva um programa que leia uma matriz bidimensional de dimensões 4 x 4 e
imprima a diagonal principal da matriz.
h) Escreva um programa que leia dois números inteiros a e b, crie uma matriz de
dimensões a x b, preencha a matriz com valores informados pelo usuário e depois imprima a
matriz transposta da matriz original. A matriz transposta de uma matriz é a matriz resultante
da troca de linhas por colunas da matriz original. Abaixo, alguns exemplos de matrizes
transpostas:
i) Escreva um programa que leia dois números inteiros a e b, crie uma matriz de
dimensões a x b, preencha a matriz com valores informados pelo usuário e verifique se a
matriz é simétrica. Uma matriz é dita simétrica se ela é igual à sua matriz transposta.
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução
Java Programação Introdução

Weitere ähnliche Inhalte

Was ist angesagt?

Curso Java Básico - Aula 01
Curso Java Básico - Aula 01Curso Java Básico - Aula 01
Curso Java Básico - Aula 01Natanael Fonseca
 
lista de exercícios de estrutura de dados Básico primeira prova
lista de exercícios de estrutura de dados Básico primeira prova lista de exercícios de estrutura de dados Básico primeira prova
lista de exercícios de estrutura de dados Básico primeira prova Rogério Cardoso
 
Linguagem de programação
Linguagem de programaçãoLinguagem de programação
Linguagem de programaçãoSandro Lopes
 
Tutorial java script orientado à objeto e jquery
Tutorial java script orientado à objeto e jqueryTutorial java script orientado à objeto e jquery
Tutorial java script orientado à objeto e jqueryLuan Campos
 
Poo1 aula 2 - java - apresentação do netbeans e 1º programa
Poo1   aula 2 - java - apresentação do netbeans e 1º programaPoo1   aula 2 - java - apresentação do netbeans e 1º programa
Poo1 aula 2 - java - apresentação do netbeans e 1º programaDenis Sobrenome
 
Java introdução ao java
Java   introdução ao javaJava   introdução ao java
Java introdução ao javaArmando Daniel
 
JAVA: Muito mais que uma linguagem
JAVA: Muito mais que uma linguagemJAVA: Muito mais que uma linguagem
JAVA: Muito mais que uma linguagemliverig
 
Java recursos avançados - multithreading
Java   recursos avançados - multithreadingJava   recursos avançados - multithreading
Java recursos avançados - multithreadingArmando Daniel
 
Pacotes -organizando_suas_classes_e_bibliotecas
Pacotes  -organizando_suas_classes_e_bibliotecasPacotes  -organizando_suas_classes_e_bibliotecas
Pacotes -organizando_suas_classes_e_bibliotecasPedro Neto
 
Introdução à Shellscript
Introdução à ShellscriptIntrodução à Shellscript
Introdução à ShellscriptVinícius Hax
 

Was ist angesagt? (20)

Shell script
Shell script Shell script
Shell script
 
Curso Java Básico - Aula 01
Curso Java Básico - Aula 01Curso Java Básico - Aula 01
Curso Java Básico - Aula 01
 
1707331929 ltp iv java original
1707331929 ltp iv   java original1707331929 ltp iv   java original
1707331929 ltp iv java original
 
lista de exercícios de estrutura de dados Básico primeira prova
lista de exercícios de estrutura de dados Básico primeira prova lista de exercícios de estrutura de dados Básico primeira prova
lista de exercícios de estrutura de dados Básico primeira prova
 
Fascículo1java
Fascículo1javaFascículo1java
Fascículo1java
 
Manual robotec
Manual robotecManual robotec
Manual robotec
 
Linguagem de programação
Linguagem de programaçãoLinguagem de programação
Linguagem de programação
 
Tutorial java script orientado à objeto e jquery
Tutorial java script orientado à objeto e jqueryTutorial java script orientado à objeto e jquery
Tutorial java script orientado à objeto e jquery
 
Guia php
Guia phpGuia php
Guia php
 
Introd aplicjava
Introd aplicjavaIntrod aplicjava
Introd aplicjava
 
Java
JavaJava
Java
 
Java primeiros-passos
Java primeiros-passosJava primeiros-passos
Java primeiros-passos
 
Apostila linguagem pascal
Apostila linguagem pascalApostila linguagem pascal
Apostila linguagem pascal
 
Poo1 aula 2 - java - apresentação do netbeans e 1º programa
Poo1   aula 2 - java - apresentação do netbeans e 1º programaPoo1   aula 2 - java - apresentação do netbeans e 1º programa
Poo1 aula 2 - java - apresentação do netbeans e 1º programa
 
Java introdução ao java
Java   introdução ao javaJava   introdução ao java
Java introdução ao java
 
JAVA: Muito mais que uma linguagem
JAVA: Muito mais que uma linguagemJAVA: Muito mais que uma linguagem
JAVA: Muito mais que uma linguagem
 
Java recursos avançados - multithreading
Java   recursos avançados - multithreadingJava   recursos avançados - multithreading
Java recursos avançados - multithreading
 
Pacotes -organizando_suas_classes_e_bibliotecas
Pacotes  -organizando_suas_classes_e_bibliotecasPacotes  -organizando_suas_classes_e_bibliotecas
Pacotes -organizando_suas_classes_e_bibliotecas
 
Introdução à Shellscript
Introdução à ShellscriptIntrodução à Shellscript
Introdução à Shellscript
 
01 java fundamentos
01 java fundamentos01 java fundamentos
01 java fundamentos
 

Andere mochten auch

Estruturas de Dados Básicas
Estruturas de Dados BásicasEstruturas de Dados Básicas
Estruturas de Dados BásicasSidney Roberto
 
Aula06 - exercícios redes sem fio
Aula06 -  exercícios redes sem fioAula06 -  exercícios redes sem fio
Aula06 - exercícios redes sem fioCarlos Veiga
 
2. Programação e resolução de problemas; Algoritmos; Snap! – Fundamentos de P...
2. Programação e resolução de problemas; Algoritmos; Snap! – Fundamentos de P...2. Programação e resolução de problemas; Algoritmos; Snap! – Fundamentos de P...
2. Programação e resolução de problemas; Algoritmos; Snap! – Fundamentos de P...Manuel Menezes de Sequeira
 
1. Computador; Línguas naturais; Linguagens de Programação; Algoritmo e progr...
1. Computador; Línguas naturais; Linguagens de Programação; Algoritmo e progr...1. Computador; Línguas naturais; Linguagens de Programação; Algoritmo e progr...
1. Computador; Línguas naturais; Linguagens de Programação; Algoritmo e progr...Manuel Menezes de Sequeira
 
Apostila de Introdução aos Algoritmos - usando o Visualg
Apostila de Introdução aos Algoritmos - usando o VisualgApostila de Introdução aos Algoritmos - usando o Visualg
Apostila de Introdução aos Algoritmos - usando o VisualgRegis Magalhães
 
Introdução 1 cristologia
Introdução 1 cristologiaIntrodução 1 cristologia
Introdução 1 cristologiafrpoverello
 

Andere mochten auch (10)

Estruturas de Dados Básicas
Estruturas de Dados BásicasEstruturas de Dados Básicas
Estruturas de Dados Básicas
 
Laços de Repetição
Laços de RepetiçãoLaços de Repetição
Laços de Repetição
 
Classes e Objetos
Classes e ObjetosClasses e Objetos
Classes e Objetos
 
Aula06 - exercícios redes sem fio
Aula06 -  exercícios redes sem fioAula06 -  exercícios redes sem fio
Aula06 - exercícios redes sem fio
 
2. Programação e resolução de problemas; Algoritmos; Snap! – Fundamentos de P...
2. Programação e resolução de problemas; Algoritmos; Snap! – Fundamentos de P...2. Programação e resolução de problemas; Algoritmos; Snap! – Fundamentos de P...
2. Programação e resolução de problemas; Algoritmos; Snap! – Fundamentos de P...
 
1. Computador; Línguas naturais; Linguagens de Programação; Algoritmo e progr...
1. Computador; Línguas naturais; Linguagens de Programação; Algoritmo e progr...1. Computador; Línguas naturais; Linguagens de Programação; Algoritmo e progr...
1. Computador; Línguas naturais; Linguagens de Programação; Algoritmo e progr...
 
Apostila de Introdução aos Algoritmos - usando o Visualg
Apostila de Introdução aos Algoritmos - usando o VisualgApostila de Introdução aos Algoritmos - usando o Visualg
Apostila de Introdução aos Algoritmos - usando o Visualg
 
Algoritmo - tipos de dados
Algoritmo - tipos de dadosAlgoritmo - tipos de dados
Algoritmo - tipos de dados
 
Listas (parte 1)
Listas (parte 1)Listas (parte 1)
Listas (parte 1)
 
Introdução 1 cristologia
Introdução 1 cristologiaIntrodução 1 cristologia
Introdução 1 cristologia
 

Ähnlich wie Java Programação Introdução

Ähnlich wie Java Programação Introdução (20)

Compilando em java
Compilando em javaCompilando em java
Compilando em java
 
Introdução ao java Alo Mundo
Introdução ao java Alo MundoIntrodução ao java Alo Mundo
Introdução ao java Alo Mundo
 
Aula1- Java PRof.ª Cristiane Fidelix
Aula1- Java PRof.ª Cristiane FidelixAula1- Java PRof.ª Cristiane Fidelix
Aula1- Java PRof.ª Cristiane Fidelix
 
Tutorial instalacão java
Tutorial instalacão javaTutorial instalacão java
Tutorial instalacão java
 
Tutorial java
Tutorial javaTutorial java
Tutorial java
 
Java1
Java1Java1
Java1
 
Aula1
Aula1Aula1
Aula1
 
Linguagem Java, fundamentos da linguagem Java
Linguagem Java, fundamentos da linguagem JavaLinguagem Java, fundamentos da linguagem Java
Linguagem Java, fundamentos da linguagem Java
 
Linguagem c
Linguagem cLinguagem c
Linguagem c
 
Aula 1
Aula 1Aula 1
Aula 1
 
Spring & Struts
Spring & StrutsSpring & Struts
Spring & Struts
 
Linguagem de java
Linguagem de javaLinguagem de java
Linguagem de java
 
Introducao logica2
Introducao logica2Introducao logica2
Introducao logica2
 
ptt
pttptt
ptt
 
Bada
BadaBada
Bada
 
40 php orientado a objetos
40 php orientado a objetos40 php orientado a objetos
40 php orientado a objetos
 
php orientado_a_objetos
php orientado_a_objetosphp orientado_a_objetos
php orientado_a_objetos
 
40 php orientado a objetos
40 php orientado a objetos40 php orientado a objetos
40 php orientado a objetos
 
Apostila php orientado a objetos
Apostila php   orientado a objetosApostila php   orientado a objetos
Apostila php orientado a objetos
 
Conceitos Fundamentais de Programacao
Conceitos Fundamentais de ProgramacaoConceitos Fundamentais de Programacao
Conceitos Fundamentais de Programacao
 

Mehr von Sidney Roberto

Precisamos falar sobre MERN stack
Precisamos falar sobre MERN stackPrecisamos falar sobre MERN stack
Precisamos falar sobre MERN stackSidney Roberto
 
Personagens negros na cultura nerd
Personagens negros na cultura nerdPersonagens negros na cultura nerd
Personagens negros na cultura nerdSidney Roberto
 
Mantendo os dados do seu app web offline com PouchDB
Mantendo os dados do seu app web offline com PouchDBMantendo os dados do seu app web offline com PouchDB
Mantendo os dados do seu app web offline com PouchDBSidney Roberto
 
Regulamento da batalha campal do DCN IV
Regulamento da batalha campal do DCN IVRegulamento da batalha campal do DCN IV
Regulamento da batalha campal do DCN IVSidney Roberto
 
Regulamento dos concursos de cosplay e cospobre do DCN IV
Regulamento dos concursos de cosplay e cospobre do DCN IVRegulamento dos concursos de cosplay e cospobre do DCN IV
Regulamento dos concursos de cosplay e cospobre do DCN IVSidney Roberto
 
Regulamento Cosplay e Cospobre - DCN 3 IFMS-AQ
Regulamento Cosplay e Cospobre - DCN 3 IFMS-AQRegulamento Cosplay e Cospobre - DCN 3 IFMS-AQ
Regulamento Cosplay e Cospobre - DCN 3 IFMS-AQSidney Roberto
 
Tecnologias e Mercado de Trabalho
Tecnologias e Mercado de TrabalhoTecnologias e Mercado de Trabalho
Tecnologias e Mercado de TrabalhoSidney Roberto
 
Palestra de boas vindas aos estudantes do curso TSI do IFMS Aquidauana
Palestra de boas vindas aos estudantes do curso TSI do IFMS AquidauanaPalestra de boas vindas aos estudantes do curso TSI do IFMS Aquidauana
Palestra de boas vindas aos estudantes do curso TSI do IFMS AquidauanaSidney Roberto
 
Web Scraping: aplicações nos negócios e na ciência
Web Scraping: aplicações nos negócios e na ciênciaWeb Scraping: aplicações nos negócios e na ciência
Web Scraping: aplicações nos negócios e na ciênciaSidney Roberto
 
Regulamento do Concurso de Cosplay - Dia da Cultura Nerd IFMS-AQ
Regulamento do Concurso de Cosplay - Dia da Cultura Nerd IFMS-AQRegulamento do Concurso de Cosplay - Dia da Cultura Nerd IFMS-AQ
Regulamento do Concurso de Cosplay - Dia da Cultura Nerd IFMS-AQSidney Roberto
 
Tutorial - Como criar sua primeira app para Android
Tutorial - Como criar sua primeira app para AndroidTutorial - Como criar sua primeira app para Android
Tutorial - Como criar sua primeira app para AndroidSidney Roberto
 
Minha opinião sobre o sistema educacional de base brasileiro
Minha opinião sobre o sistema educacional de base brasileiroMinha opinião sobre o sistema educacional de base brasileiro
Minha opinião sobre o sistema educacional de base brasileiroSidney Roberto
 
Vamos aprender algo diferente? Introdução à linguagem Python (parte 2)
Vamos aprender algo diferente? Introdução à linguagem Python (parte 2)Vamos aprender algo diferente? Introdução à linguagem Python (parte 2)
Vamos aprender algo diferente? Introdução à linguagem Python (parte 2)Sidney Roberto
 
Vamos aprender algo diferente? Introdução à linguagem Python (aula 1)
Vamos aprender algo diferente? Introdução à linguagem Python (aula 1)Vamos aprender algo diferente? Introdução à linguagem Python (aula 1)
Vamos aprender algo diferente? Introdução à linguagem Python (aula 1)Sidney Roberto
 
Manipulação de Datas em Java
Manipulação de Datas em JavaManipulação de Datas em Java
Manipulação de Datas em JavaSidney Roberto
 
Estrutura de Programas
Estrutura de ProgramasEstrutura de Programas
Estrutura de ProgramasSidney Roberto
 
O que é Interação Humano-Computador?
O que é Interação Humano-Computador?O que é Interação Humano-Computador?
O que é Interação Humano-Computador?Sidney Roberto
 
Representação e Manipulação de Informações
Representação e Manipulação de InformaçõesRepresentação e Manipulação de Informações
Representação e Manipulação de InformaçõesSidney Roberto
 
Conceitos Iniciais de Linguagens de Programação
Conceitos Iniciais de Linguagens de ProgramaçãoConceitos Iniciais de Linguagens de Programação
Conceitos Iniciais de Linguagens de ProgramaçãoSidney Roberto
 

Mehr von Sidney Roberto (20)

Precisamos falar sobre MERN stack
Precisamos falar sobre MERN stackPrecisamos falar sobre MERN stack
Precisamos falar sobre MERN stack
 
Personagens negros na cultura nerd
Personagens negros na cultura nerdPersonagens negros na cultura nerd
Personagens negros na cultura nerd
 
Mantendo os dados do seu app web offline com PouchDB
Mantendo os dados do seu app web offline com PouchDBMantendo os dados do seu app web offline com PouchDB
Mantendo os dados do seu app web offline com PouchDB
 
Regulamento da batalha campal do DCN IV
Regulamento da batalha campal do DCN IVRegulamento da batalha campal do DCN IV
Regulamento da batalha campal do DCN IV
 
Regulamento dos concursos de cosplay e cospobre do DCN IV
Regulamento dos concursos de cosplay e cospobre do DCN IVRegulamento dos concursos de cosplay e cospobre do DCN IV
Regulamento dos concursos de cosplay e cospobre do DCN IV
 
Regulamento Cosplay e Cospobre - DCN 3 IFMS-AQ
Regulamento Cosplay e Cospobre - DCN 3 IFMS-AQRegulamento Cosplay e Cospobre - DCN 3 IFMS-AQ
Regulamento Cosplay e Cospobre - DCN 3 IFMS-AQ
 
Tecnologias e Mercado de Trabalho
Tecnologias e Mercado de TrabalhoTecnologias e Mercado de Trabalho
Tecnologias e Mercado de Trabalho
 
Palestra de boas vindas aos estudantes do curso TSI do IFMS Aquidauana
Palestra de boas vindas aos estudantes do curso TSI do IFMS AquidauanaPalestra de boas vindas aos estudantes do curso TSI do IFMS Aquidauana
Palestra de boas vindas aos estudantes do curso TSI do IFMS Aquidauana
 
Web Scraping: aplicações nos negócios e na ciência
Web Scraping: aplicações nos negócios e na ciênciaWeb Scraping: aplicações nos negócios e na ciência
Web Scraping: aplicações nos negócios e na ciência
 
Regulamento do Concurso de Cosplay - Dia da Cultura Nerd IFMS-AQ
Regulamento do Concurso de Cosplay - Dia da Cultura Nerd IFMS-AQRegulamento do Concurso de Cosplay - Dia da Cultura Nerd IFMS-AQ
Regulamento do Concurso de Cosplay - Dia da Cultura Nerd IFMS-AQ
 
Tutorial - Como criar sua primeira app para Android
Tutorial - Como criar sua primeira app para AndroidTutorial - Como criar sua primeira app para Android
Tutorial - Como criar sua primeira app para Android
 
Minha opinião sobre o sistema educacional de base brasileiro
Minha opinião sobre o sistema educacional de base brasileiroMinha opinião sobre o sistema educacional de base brasileiro
Minha opinião sobre o sistema educacional de base brasileiro
 
Vamos aprender algo diferente? Introdução à linguagem Python (parte 2)
Vamos aprender algo diferente? Introdução à linguagem Python (parte 2)Vamos aprender algo diferente? Introdução à linguagem Python (parte 2)
Vamos aprender algo diferente? Introdução à linguagem Python (parte 2)
 
Vamos aprender algo diferente? Introdução à linguagem Python (aula 1)
Vamos aprender algo diferente? Introdução à linguagem Python (aula 1)Vamos aprender algo diferente? Introdução à linguagem Python (aula 1)
Vamos aprender algo diferente? Introdução à linguagem Python (aula 1)
 
Fatores Humanos
Fatores HumanosFatores Humanos
Fatores Humanos
 
Manipulação de Datas em Java
Manipulação de Datas em JavaManipulação de Datas em Java
Manipulação de Datas em Java
 
Estrutura de Programas
Estrutura de ProgramasEstrutura de Programas
Estrutura de Programas
 
O que é Interação Humano-Computador?
O que é Interação Humano-Computador?O que é Interação Humano-Computador?
O que é Interação Humano-Computador?
 
Representação e Manipulação de Informações
Representação e Manipulação de InformaçõesRepresentação e Manipulação de Informações
Representação e Manipulação de Informações
 
Conceitos Iniciais de Linguagens de Programação
Conceitos Iniciais de Linguagens de ProgramaçãoConceitos Iniciais de Linguagens de Programação
Conceitos Iniciais de Linguagens de Programação
 

Java Programação Introdução

  • 1. INSTITUTO FEDERAL DE MATO GROSSO DO SUL Tecnologia em Sistemas para Internet Disciplina: Linguagem de Programação I Prof.º Msc. Sidney Roberto de Sousa Apostila – Linguagem de Programação I 1 - Conteúdo da apostila • Criando um programa em Java • Compilando e executando programas em Java • Imprimindo texto na tela • Trabalhando com números inteiros • Trabalhando com números reais • Operações matemáticas ◦ Operações binárias ◦ Operações unárias • Trabalhando com booleanos e operações lógicas • Trabalhando com strings • Lendo valores do usuário • Controlando o fluxo do programa • Utilizando laços de repetição • Matrizes 2 - Criando um programa em Java Um programa Java básico precisa ser escrito dentro de uma classe. Em um futuro próximo, aprenderemos mais a respeito sobre classes e objetos. Por enquanto, tudo o que precisamos saber é que todo o algoritmo do nosso programa Java precisa ser escrito dentro de uma definição de classe, conforme o exemplo abaixo. public class MeuPrograma { public static void main(String[] args) { // O seu algoritmo vai aqui! } } No exemplo, a nossa classe chama-se MeuPrograma. O nome de uma classe Java deve obrigatoriamente começar com uma letra e não pode conter caracteres especiais (como por exemplo $%”&#-+=/(){}[]*@!.?`'ªº). É uma convenção que o nome de classes Java sejam escritas no formato Camel Case, ou seja, com cada palavra do nome iniciada por uma letra maiúscula e todos os caracteres restantes em minúsculo. Todas as classes que escreveremos nesta disciplina conterá o método main, exatamente da forma como foi escrito no exemplo acima. Dentro do método main, na única linha de código do método, existe um comentário explicando que o código do algoritmo do programa deve ser escrito a partir daquele ponto. Comentários não são códigos de programa. Eles servem somente para se comentar algo sobre o código que está sendo escrito. Por exemplo, você pode querer inserir comentários que expliquem o raciocínio por trás do algoritmo que você desenvolveu, ou mesmo um lembrete para você mesmo a respeito de um trecho de código mais complexo. Abaixo, alguns exemplos de comentários.
  • 2. // Eu sou um comentário de uma linha // Eu sou um comentário de // duas linhas /* * Eu também sou um comentário de * duas linhas! */ Outra coisa a ser notada é que tanto o corpo de código da classe MeuPrograma quanto o corpo de código do método main são delimitados por chaves. Esta delimitação é obrigatória e nos ajuda a organizar o nosso código. Uma vez que você escreveu o seu programa dentro de uma classe e de um método main, você deve salvar o arquivo de texto que contém o código que você escreveu. A nomenclatura deste arquivo deve seguir obrigatoriamente o padrão abaixo: NOME_DA_CLASSE.java Por exemplo, a classe MeuPrograma do nosso exemplo deve ser salva no arquivo MeuPrograma.java. Tome muito cuidado para não se esquecer deste procedimento! Exercício a) Crie a classe MeuPrograma conforme o exemplo anterior e salve a classe em um arquivo apropriado (conforme ensinado nesta seção). 3 - Compilando e executando programas em Java Um programa Java precisa ser compilado para bytecodes antes que a máquina virtual Java possa executá-lo. Para tanto, a plataforma Java oferece um compilador Java, presente no script javac. Antes que você possa utilizar o script javac, talvez você deseje adicioná-lo às suas variáveis de ambiente, para que você possa executá-lo em qualquer pasta. No Windows, primeiramente você deve informar ao sistema operacional onde os arquivos da máquina virtual Java estão localizados, criando a variável de ambiente JAVA_HOME: Nome da variável: JAVA_HOME Valor da variável: PASTA_ONDE_O_JAVA_FOI_INSTALADO Por exemplo, se você instalou a última versão do Java1 em uma instalação padrão, sem definir um outro diretório, provavelmente você fará a seguinte configuração: Nome da variável: JAVA_HOME Valor da variável: C:Program FilesJavajdk1.7.0_17 Após criar a variável de ambiente JAVA_HOME, você precisa informar ao Windows onde estão localizados os programas da máquina virtual Java. Para tanto, basta você adicionar o caminho dos programas na variável de ambiente PATH (ATENÇÃO: Esta variável provavelmente já existe na sua instalação do Windows. Assim, coloque o caminho dos executáveis Java no final da string do valor da variável PATH. NÃO APAGUE o conteúdo já existente da variável!). Caso você tenha instalado a última versão do Java em uma instalação padrão como citado anteriormente, você deve colocar o valor abaixo no final da string do valor da variável de ambiente PATH (lembrando que quando uma variável de ambiente possui vários valores, cada valor deve ser separado pelo caractere ';'): C:Program FilesJavajdk1.7.0_17bin Uma vez que você tenha realizado todas estas configurações (caso tenha sido 1 Data de 08/04/2013.
  • 3. necessário realizá-las), o seu computador está pronto para compilar e executar os seus programas Java. Para compilar um programa Java, entre no PROMPT do DOS, use o comando cd para entrar na pasta onde o seu arquivo .java está localizado e utilize o comando javac para compilar o seu programa. Por exemplo, considere o nosso programa escrito na classe MeuPrograma, a qual está dentro do arquivo MeuPrograma.java. Assim, para compilar o seu programa você precisa digitar o comando abaixo: javac MeuPrograma.java Ao fazer isto, caso o seu programa não contenha nenhum erro, o compilador Java cria um arquivo chamado MeuPrograma.class na mesma pasta onde o seu programa está situado. Este arquivo contém os bytecodes do seu programa para que a máquina virtual Java possa executá-lo. Assim, para executar o seu programa, você precisa digitar o comando abaixo: java MeuPrograma E pronto! Agora é só testar o seu programa! Exercícios a) Abra o terminal de linha de comando, encontre a pasta onde o arquivo da classe MeuPrograma se encontra e compile e execute a classe MeuPrograma. 4 – Imprimindo texto na tela Uma das primeiras coisas úteis que podemos aprender é imprimir texto em linha de comando por meio de um programa Java. No Windows, o shell de linha de comando mais utilizado é o PROMPT do MS-DOS. No Linux, temos vários tipos de shells, como o bash e o dash. O programa abaixo imprime a mensagem “Olá! Eu sou um programa escrito em Java!” na tela. public class MeuPrograma { public static void main(String[] args) { System.out.print("Olá! Eu sou um programa escrito em Java!"); } } O método print, existente no atributo out da classe System do Java imprime mensagens em linha de comando. Se você compilar e executar este programa, ele irá gerar a seguinte saída no shell: Note que o texto impresso pelo programa provocou uma má formatação no shell de linha de comando, pois o texto impresso e a linha de comando atual ficaram na mesma linha! Para evitar este tipo de problema, podemos utilizar o método println ao invés do método print, conforme o exemplo abaixo: public class MeuPrograma { public static void main(String[] args) { System.out.println("Olá! Eu sou um programa escrito em Java!"); } } suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$ javac MeuPrograma.java  suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$ java MeuPrograma  Olá! Eu sou um programa escrito em Java!suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$
  • 4. O método println imprime a mensagem desejada na tela do shell, porém ele pula uma linha do shell após a impressão. Abaixo, a saída do programa acima: Existem basicamente duas formas de se imprimir múltiplas linhas na tela. A primeira forma é utilizar um println por frase, conforme abaixo: public class MeuPrograma { public static void main(String[] args) { System.out.println("Olá! Eu sou um programa escrito em Java!"); System.out.println("Estou imprimindo duas linhas na tela."); } } A outra forma é utilizar o caractere especial 'n' dentro do método print. Este caractere faz com que o texto seja quebrado em outra linha. O programa abaixo gera a mesma saída do programa do exemplo acima: public class MeuPrograma { public static void main(String[] args) { System.out.print("Olá! Eu sou um programa escrito em Java!nEstou imprimindo duas linhas na tela.n"); } } Opcionalmente, você pode inserir tabulações nas frases a serem impressas na tela, a fim de se obter uma melhor formatação do texto. Para inserir uma tabulação, utilizamos o caractere especial 't'. O programa abaixo imprime uma frase na tela, inserindo uma tabulação no início da frase: public class MeuPrograma { public static void main(String[] args) { System.out.println("tOlá! A tabulação no início desta frase simula o início de um parágrafo."); } } Exercícios a) Escreva um programa que imprima na tela o poema a seguir utilizando uma ou mais chamadas ao método println, sabendo que cada frase possui uma tabulação em seu início. BILHETE  Se tu me amas, ama­me baixinho  Não o grites de cima dos telhados  Deixa em paz os passarinhos  Deixa em paz a mim!  Se me queres,  enfim,  tem de ser bem devagarinho, Amada,  que a vida é breve, e o amor mais breve ainda...  Mario Quintana b) Escreva um programa que imprima na tela o mesmo poema acima, porém utilizando somente uma chamada ao método print. suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$ javac MeuPrograma.java  suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$ java MeuPrograma  Olá! Eu sou um programa escrito em Java! suesid@suesid­Inspiron­7520:~/workspace/TestesGerais/src/br/edu/ifms/aula$
  • 5. 5 - Trabalhando com números inteiros Muitos dos problemas do mundo real que necessitam de um programa de computador para serem resolvidos envolvem números. Considere o seguinte problema: uma pessoa possui 53 pacotes de biscoito salgado e 87 pacotes de biscoito doce em seu estoque e ela precisa saber quantos pacotes de biscoito ela possui no total. Note que este problema envolve apenas números inteiros, ou seja, número que não precisam de casas decimais para representá-los. Vamos escrever um programa para resolver este problema: public class SomaPacotesBiscoito { public static void main(String[] args) { int numeroPacotesBiscoitoSalgado = 53; int numeroPacotesBiscoitoDoce = 87; int totalPacotes = numeroPacotesBiscoitoSalgado + numeroPacotesBiscoitoDoce; System.out.println("Você possui " + totalPacotes + " pacotes de biscoito."); } } Para resolver este problema, precisamos utilizar três variáveis. Uma variável é um local de armazenamento de dados. Você pode pensar em uma variável como uma gaveta capaz de armazenar itens. Toda variável possui um nome, o qual deve começar com uma letra e não pode conter caracteres especiais. É uma forte convenção que variáveis em Java iniciem com letras minúsculas. As três variáveis que utilizamos neste programa são do tipo int. Uma variável do tipo int só pode armazenar números inteiros. Existem outros tipos em Java que podem armazenar números inteiros. Para uma melhor explicação sobre tipos inteiros, veja os slides da aula 3. A primeira variável utilizada no programa acima chama-se numeroPacotesBiscoitoSalgado. Ela guarda o número de pacotes de biscoito salgado contidos no estoque da pessoa do nosso problema. A segunda variável do nosso programa chama-se numeroPacotesBiscoitoDoce. Por sua vez, ela guarda o número de pacotes de biscoito doce existentes no estoque. A soma total de pacotes resulta em um número inteiro, visto que ela é composta pela soma de dois números inteiros. Assim, a última variável do nosso programa (totalPacotes) armazena a soma do número de pacotes de biscoito salgado com o número de pacotes de biscoito doce. Observe bem a linha de código que executa esta soma. O operador '=' simboliza que algum valor será atribuído à variável totalPacotes. O operador '+' simboliza a soma entre os valores de numeroPacotesBiscoitoSalgado e numeroPacotesBiscoitoDoce. Veremos mais em frente nesta apostila outros tipos de operações matemáticas possíveis em Java. O número total de pacotes é exibido na última linha do programa. A fim de facilitar o entendimento do usuário a respeito do que foi realizado no programa, exibimos a ele uma frase explicativa contendo o número total de pacotes calculado. Note que utilizamos o operador '+' para concatenar a frase que queremos exibir para o usuário com o número total de pacotes. Esta concatenação transforma o número inteiro em texto, podendo assim ser juntado à frase. O programa exibe a seguinte saída na tela: Você possui 140 pacotes de biscoito. 6 - Trabalhando com números reais Agora, imagine que a pessoa do exemplo anterior deseje saber qual o peso total dos biscoitos que ela possui em estoque. Ela sabe que cada pacote de biscoito salgado pesa 0,350 kg e cada pacote de biscoito doce pesa 0,414 kg. Note que agora alguns números do nosso problema não são inteiros – no caso, os pesos dos pacotes. Assim, não podemos armazenar tais valores em variáveis inteiras. A seguir, a solução para este problema:
  • 6. public class CalculoPesoPacotesBiscoito { public static void main(String[] args) { int numeroPacotesBiscoitoSalgado = 53; int numeroPacotesBiscoitoDoce = 87; double pesoTotalBiscoitosSalgados = numeroPacotesBiscoitoSalgado * 0.350; double pesoTotalBiscoitosDoces = numeroPacotesBiscoitoDoce * 0.414; double pesoTotalPacotes = pesoTotalBiscoitosSalgados + pesoTotalBiscoitosDoces; System.out.println("O seu estoque de biscoitos pesa " + pesoTotalPacotes + " kg."); } } Além das duas variáveis inteiras para armazenar o número total de pacotes de cada tipo de biscoito, o nosso programa possui mais três variáveis do tipo double para armazenar o peso total de biscoitos salgados, o peso total de biscoitos doces e o peso total de biscoitos em estoque. O tipo double é utilizado para definir que as três variáveis armazenam números reais. Uma variável do tipo double pode armazenar tanto números reais quanto números inteiros. O tipo float também é utilizado para se definir variáveis para armazenar números reais. Para entender melhor as diferenças entre estes dois tipos, veja os slides da aula 3. O programa acima imprime a seguinte mensagem na tela: O seu estoque de biscoitos pesa 54.568 kg. 7 - Operações matemáticas Na linguagem Java é possível compor desde operações matemáticas simples - como somar ou subtrair dois valores - até operações mais complexas. No exemplo anterior, o nosso código realizou duas operações matemáticas básicas: a soma entre dois valores, por meio do operador '+' e a multiplicação entre dois valores, por meio do operador '*'. Podemos agrupar as operações matemáticas em Java em dois tipos: operações binárias e operações unárias. 7.1 Operações binárias Uma operação binária é uma operação matemática que envolve dois valores distintos. Tais valores podem ser constantes ou oriundos de variáveis. A tabela abaixo mostra as operações matemáticas binárias possíveis em Java. Operação Operador Expressão Adição + a = b + c; Subtração - a = b – c; Multiplicação * a = b * c; Divisão / a = b / c; Operações matemáticas do tipo a = a OPERADOR b; podem ser abreviadas. A tabela abaixo mostra as abreviações possíveis. Expressão Expressão abreviada a = a + b; a += b; a = a - b; a -= b; a = a * b; a *= b; a = a / b; a /= b;
  • 7. O programa abaixo contém algumas operações matemáticas binárias simples: public class ExemploOperacoesBinarias { public static void main(String[] args) { int valor1 = 45; // Somando o valor de uma variável com um constante int valor2 = valor1 + 76; // 121 // Somando o valor de duas variáveis valor1 = valor1 + valor2; // 166 // Realizando a mesma operação, usando uma abreviação valor1 += valor2; // 287 // Subtraindo o valor de duas constantes double numeroReal = 687.35 - 790; // −102.65 numeroReal -= 100; // −202,65 numeroReal *= -1; // 202,65 double resultado = numeroReal / valor1; // 0.7060975609756097 resultado /= resultado; // 1 } } Podemos compor operações matemáticas mais complexas, como fórmulas matemáticas. A seguir, alguns programas que contém fórmulas conhecidas: public class Bhaskara { public static void main(String[] args) { double a = 5; double b = 6; double c = 4; double delta = b * b - 4 * a * c; // -44 System.out.println("Delta = " + delta); } } public class AreaCircunferencia { public static void main(String[] args) { /* * Constantes em Java são definidas por meio do prefixo final. * O valor da constante deve ser definido obrigatoriamente * no momento de sua declaração. * O valor de uma constante não é mutável. Isto significa que * após a inicialização da constante, instruções como esta: * PI = 456.87; * Gerariam um erro. */ final double PI = 3.14159; double raio = 5; double areaCircunferencia = PI * raio * raio; // 78.53975 System.out.println("Área da circunferência = " + areaCircunferencia); } } public class AreaQuadrado { public static void main(String[] args) { double lado = 4.5; double areaQuadrado = lado * lado; // 20.25 System.out.println("Área do quadrado = " + areaQuadrado); } } Vale a pena salientar que as operações de multiplicação e divisão possuem precedência sobre as operações de adição e subtração. Caso a fórmula precise ser calculada utilizando uma ordem de precedência diferente à ordem normal, é preciso utilizar parênteses para se definir os trechos de precedência. Considere o exemplo abaixo:
  • 8. public class ExemploPrecedencia { public static void main(String[] args) { int valor1 = 7; int valor2 = 9; int resultado = valor1 * (98 - valor2) * 4; // 2492 System.out.println(resultado); } } Note que a fórmula do programa acima resultaria no valor 650 caso não houvessem os parênteses, pois primeiramente seriam calculadas as multiplicações para depois ser calculada a subtração. Porém, o uso dos parênteses faz com que a subtração seja calculada inicialmente, fazendo com que a fórmula resulte no valor 2492. Exercícios Para cada problema abaixo, escreva um programa para resolvê-lo: a) Uma pessoa viaja em seu veículo de passeio pelo estado de Mato Grosso do Sul. Em um determinado momento, ela chega no município de Guia Lopes da Laguna. Porém, o seu objetivo é chegar até o município de Bonito, o qual se situa a 45 km de distância do município de Guia Lopes da Laguna. Dado que seu veículo viaja sob a velocidade média de 80 km/h, quanto tempo (em minutos) a pessoa demorará para chegar até o município de Bonito? (Recordando que segundo a física mecânica, a fórmula para se encontrar o intervalo de tempo é tempo=distância/velocidade. Não se esqueça de realizar a conversão para minutos no final!) b) Um pedreiro utilizou 1000 tijolos para construir 30 metros de muro. Dado que ele ainda necessita construir 6 metros de muro, quantos tijolos ele ainda necessitará utilizar? (Não se preocupe se o número da resposta não for inteiro) c) Um artesão deseja construir uma torre uniforme de 3,5 m de altura utilizando cartas de baralho. Ele já conseguiu construir 1,75 m da torre, utilizando para tanto 557 baralhos. Sabendo que um baralho tradicional possui 52 cartas, quantas cartas ele ainda necessitará para finalizar a construção da sua torre? (Não se preocupe se o número da resposta não for inteiro) d) Em uma pesquisa eleitoral, identificou-se que 432 pessoas pretendem votar no candidato José da Silva; 284 pessoas pretendem votar na candidata Ana Alencar; 698 pessoas pretendem votar na candidata Carolina Bezerra; por fim, 173 pessoas se mostraram indecisas quanto a que candidato votar. Qual o percentual de indecisos levantado nesta pesquisa eleitoral? 7.2 Operações unárias Uma operação unária envolve apenas uma variável. Em Java, existem duas operações unárias matemáticas, o incremento e o decremento. O operador de incremento faz com que o valor atual da variável seja incrementado em uma unidade, ou seja, a variável recebe o seu valor atual somado em uma unidade. Por sua vez, o operador decremento faz com que o valor da variável seja decrementado em uma unidade, ou seja, a variável recebe o seu valor atual subtraído em uma unidade. A tabela abaixo exibe estas operações. Operação Operador Expressão Incremento ++ a++; ou ++a; Decremento -- a--; ou --a; Em alguns casos, o uso do operador unário antes ou depois da variável pode resultar em valores distintos. O programa abaixo exibe alguns exemplos de incremento e decremento,
  • 9. além dos resultados da operação unária com operadores antes e depois da variável: public class ExemploOperacoesUnarias { public static void main(String[] args) { double valor = 2.7; valor++; // 3.7 int numero = 58; numero--; // 57 int outroNumero = 57; int valorInteiro = ++numero; // valor recebe 58 valorInteiro = outroNumero++; // valor recebe 57! } } 8 – Trabalhando com booleanos e operações lógicas Na linguagem Java, um valor booleano só pode ter um dentre dois valores: true e false, respectivamente verdadeiro e falso. Saber trabalhar com valores booleanos é essencial para a criação de programas complexos em Java, conforme veremos a partir desta seção. Em Java, um valor booleano pode ser armazenado em uma variável do tipo boolean. Um operação realizada entre dois valores booleanos é chamada de operação lógica (ou booleana) binária. O resultado de uma operação lógica só pode resultar em um valor booleano, ou seja, true ou false. Existem basicamente duas operações lógicas binárias, as operações AND e OR. Em Java, o operador && simboliza uma operação AND. Uma operação AND só resulta o valor true se e somente se os dois valores da operação forem iguais a true; caso contrário, o resultado da operação será false. A tabela abaixo exibe os resultados para cada operação AND possível entre dois valores booleanos: a b a && b true true true true false false false true false false false false A operação OR em Java é simbolizada pelo operador ||. Uma operação OR só resulta o valor false se e somente se os dois valores da operação forem iguais a false. A tabela abaixo exibe os resultados para cada operação OR possível entre dois valores booleanos: a b a || b true true true true false true false true true false false false Existe apenas uma operação unária sobre valores booleanos, a operação de negação. Em Java, esta operação é simbolizada pelo operador !. Quando um valor booleano é negado, o seu valor é invertido. A tabela abaixo exibe os resultados possíveis para cada negação: a !a true false false true
  • 10. O programa abaixo mostra alguns exemplos de operações booleanas binárias e unárias: public class ExemploOperacoesBooleanas { public static void main(String[] args) { boolean a = true; boolean b = false; boolean resultado = a && b; // false resultado = a || b; // true resultado = !a; // false resultado = !b; // true /* * Operações AND e OR não possuem precedência uma sobre a outra. As * operações são calculadas par a par. */ resultado = false && true || false || true; // true } } É possível criar operações lógicas envolvendo números inteiros ou reais. Existem muitas situações em que precisamos comparar dois ou mais números. As operações AND e OR não se aplicam a números diretamente. As operações lógicas possíveis entre dois valores numéricos são exibidas na tabela abaixo: Operação Operador Expressão Igual == a == b Diferente != a != b Maior > a > b Menor < a < b Maior ou igual >= a >= b Menor ou igual <= a <= b O programa abaixo exemplifica as operações da tabela acima: public class ExemploOperacoesLogicasNumericas { public static void main(String[] args) { int numero = 67; double outroNumero = -178.54; boolean saoIguais = numero == outroNumero; // false boolean saoDiferentes = numero != outroNumero; // true boolean primeiroEMaior = numero > outroNumero; // true boolean primeiroEMenor = numero < outroNumero; // false boolean menorOuIgual = 67 <= numero; // true boolean maiorOuIgual = -177 >= outroNumero; // true } } Operações lógicas unárias possuem precedência sobre as operações binárias. Operações lógicas binárias de comparação entre números (==, !=, >, <, >=, <=) possuem precedência sobre as operações AND e OR (&& e ||). Se você deseja forçar a precedência de uma determinada operação lógica binária, tal operação deve ser escrita entre parênteses, como no exemplo abaixo: public class ExemploPrecedenciaOperacoesLogicas { public static void main(String[] args) { boolean resultado = (98 < 89) && (true && false) || true; // true } }
  • 11. 9 - Trabalhando com strings Uma string é uma cadeia de caracteres. Nós já trabalhamos com strings nesta apostila, quando criamos programas para imprimir texto na tela: public class MeuPrograma { public static void main(String[] args) { System.out.print("Olá! Eu sou um programa escrito em Java!"); } } Neste exemplo, o programa imprime a string “Olá! Eu sou um programa escrito em Java!” na tela. Em Java, uma string deve ser delimitada por aspas duplas (“”). A string deste exemplo é dita constante, pois em seu ciclo de vida o seu valor não é alterado. Para guardar o seu valor e opcionalmente alterá-lo, podemos armazenar esta string em uma variável. A linguagem Java utiliza a classe String para armazenar strings. Abaixo, um exemplo simples de uso da classe String: public class ExemploStringSimples { public static void main(String[] args) { String umaString = "Olá! Eu sou um programa escrito em Java!"; System.out.println(umaString); } } Uma propriedade importante de uma string é o seu tamanho. O tamanho de uma string é o número de caracteres imprimíveis ou não imprimíveis (ex.: 'n' e 't') que ela possui. Lembre-se sempre que o caractere de espaço em branco ' ' também é um caractere válido e imprimível, influenciando assim no tamanho da string. Para se obter o tamanho de uma string, basta utilizar o método length da classe String, conforme o exemplo abaixo: public class ExemploTamanhoString { public static void main(String[] args) { String umaString = "Olá! Eu sou um programa escrito em Java!"; int tamanho = umaString.length(); // 40 System.out.println("A string '" + umaString + "' possui tamanho " + tamanho); } } A menor string possível é a string vazia (“”), ou seja, uma string que não possui ao menos um caractere. Existem duas formas básicas de se verificar se uma string é vazia ou não. A primeira é verificar se o seu tamanho é igual a 0, utilizando o método length; a segunda é verificar diretamente se a string é vazia por meio do método isEmpty da classe String. Este método retorna true se a string for vazia ou false caso contrário. Abaixo, um programa que exemplifica estas duas formas de verificação: public class ExemploStringVazia { public static void main(String[] args) { String umaString = ""; int tamanho = umaString.length(); System.out.println("Tamanho: " + tamanho+ ". Se for zero, então a string é vazia."); boolean estaVazia = umaString.isEmpty(); System.out.println("Está vazia? " + estaVazia); } } É possível concatenar duas ou mais strings utilizando o operador '+'. De fato, nós já fizemos isto algumas vezes nesta apostila, quando imprimimos texto na tela. Note que em muitos exemplos, nós acabamos concatenando strings com números ou mesmo com valores booleanos. Quando uma operação de concatenação é realizada entre uma string e um outro
  • 12. valor não string, tal operação sempre resulta em uma string. Para entender melhor isto, verifique o exemplo abaixo: public class ExemploConcatenacaoStrings { public static void main(String[] args) { String primeiraParte = "Meu nome é "; String segundaParte = " Sidney."; String fraseCompleta = primeiraParte + segundaParte; // Meu nome é Sidney. System.out.println(fraseCompleta); int numero = 567; String umaString = "Eu escolhi o número " + numero; // Eu escolhi o número 567 System.out.println(umaString); double numeroReal = 45.67; umaString = "Eu escolhi o número " + numeroReal; // Eu escolhi o número 45.67 System.out.println(umaString); /* * É possível abreviar concatenações locais, i.e., concatenação entre * uma string e ela mesma. */ umaString += ". Também escolhi o valor " + true + "."; // Eu escolhi o número 45.67. Também escolhi o valor true. System.out.println(umaString); } } Existem duas formas de verificar se duas strings são iguais. A primeira forma é utilizar o operador == entre as duas strings. Porém, existem alguns casos em que comparar strings desta forma pode levar a resultados inesperados. A forma mais segura de se verificar se duas strings são iguais é utilizando o método equals da classe String. O programa abaixo exemplifica estas duas formas: public class ExemploStringsIguais { public static void main(String[] args) { String primeiraString = "Copie-me se for capaz!"; String segundaString = "Copie-me se for capaz!"; boolean saoIguais = primeiraString == segundaString; // true saoIguais = primeiraString.equals(segundaString); // true saoIguais = segundaString.equals(primeiraString); // true } } No exemplo acima, as duas strings foram consideradas iguais pois todos os caracteres de cada posição de uma string é igual ao da outra string. Ambos os tipos de comparação são sensíveis a casos, ou seja, consideram se as letras contidas nas strings são maiúsculas ou minúsculas. Isto significa que, para ambos os tipos de comparação, os caracteres 'a' e 'A', por exemplo, são distintos. Assim, se alterarmos o programa do exemplo anterior conforme abaixo, os resultados serão diferentes: public class ExemploStringsIguais { public static void main(String[] args) { String primeiraString = "Copie-me Se for Capaz!"; String segundaString = "Copie-me se for capaz!"; boolean saoIguais = primeiraString == segundaString; // false saoIguais = primeiraString.equals(segundaString); // false saoIguais = segundaString.equals(primeiraString); // false } } A classe String oferece o método equalsIgnoreCase para se realizar comparações de igualdade entre duas strings ignorando casos, ou seja, maiúsculas e minúsculas. Vamos reescrever a classe ExemploStringsIguais para que ela possa realizar a comparação entre as duas strings ignorando casos:
  • 13. public class ExemploStringsIguais { public static void main(String[] args) { String primeiraString = "Copie-me Se for Capaz!"; String segundaString = "Copie-me se for capaz!"; boolean saoIguais = primeiraString.equalsIgnoreCase(segundaString); // true } } Uma forma alternativa de se comparar duas strings ignorando casos é convertendo ambas as strings para algum caso específico. Por exemplo, podemos converter os caracteres de ambas as strings para minúsculo; assim, ao compararmos as strings com o método equals ele retornará o valor true. A classe String oferece o método toLowerCase para transformar todos os caracteres da string para minúsculo e o método toUpperCase para transformar todos os caracteres da string para maiúsculo. O programa a seguir verifica a igualdade entre duas strings utilizando duas abordagens distintas: public class ComparacaoAlternativaStrings { public static void main(String[] args) { String primeiraString = "Copie-me Se for Capaz!"; String segundaString = "Copie-me se for capaz!"; // Converte as strings para minúsculo primeiraString = primeiraString.toLowerCase(); segundaString = segundaString.toLowerCase(); boolean saoIguais = primeiraString.equals(segundaString); // true primeiraString = "Crie outra String igual a MIM!"; segundaString = "crie outra string igual a mim!"; // Converte as strings para maiúsculo primeiraString = primeiraString.toUpperCase(); segundaString = segundaString.toUpperCase(); saoIguais = primeiraString.equals(segundaString); // true } } Como dito anteriormente, uma string é uma cadeia de caracteres. Um caractere pode ser armazenado em uma variável do tipo char. Uma variável do tipo char só pode armazenar um único caractere imprimível ou não imprimível. É possível pegar um determinado caractere de uma string de acordo com a sua posição (índice) na string. O primeiro caractere de uma string é localizado na posição 0; o último caractere de uma string é localizado na posição length() - 1, ou seja, se uma string possui tamanho 10, o seu último caractere é localizado na posição 9. A tabela abaixo ilustra a indexação de caracteres na string “Olá mundo!”. No exemplo, a posição 4 da string guarda o caractere 'm', assim como a posição 3 da string guarda o caractere ' ' (espaço em branco). O l á m u n d o ! 0 1 2 3 4 5 6 7 8 9 Para pegar um caractere de uma string situado em uma posição em específico, utilizamos o método charAt da classe String. O programa a seguir mostra o uso do método charAt. Note que cada caractere recuperado da string de exemplo é armazenado em uma variável do tipo char:
  • 14. public class PegaCaractereString { public static void main(String[] args) { String umaString = "Uma string é uma cadeia de caracteres."; char caractere = umaString.charAt(5); // 't' /* * Caracteres constantes devem ser delimitados por aspas simples e não * aspas duplas, como fazemos com strings. */ boolean igualT = caractere == 't'; // true // Pega o primeiro caractere da string caractere = umaString.charAt(0); // 'U' System.out.println("Primeiro caractere: " + caractere); // Pega o último caractere da string caractere = umaString.charAt(umaString.length() - 1); // '.' System.out.println("Último caractere: " + caractere); } } Anteriormente nesta seção vimos como concatenar duas ou mais strings em uma única string. Porém, em alguns casos precisamos quebrar uma string de tal forma a resultar uma string menor ou mesmo quebrar a string original em duas ou mais strings, de acordo com alguma necessidade. O método substring da classe String retorna uma parte da string original, de acordo com as posições delimitadoras desejadas. O programa a seguir pega partes de uma string utilizando o método substring de duas formas distintas: public class ExemploSubstring { public static void main(String[] args) { String umaString = "Olá, mundo! Eu sou uma string!"; /* * Pega a parte da string que inicia na posição 11 e termina na posição * length() - 1: " Eu sou uma string!" */ String parteDaString = umaString.substring(11); /* * Pega a parte da string que inicia na posição 0 e termina na posição * 10: "Olá, mundo!" */ parteDaString = umaString.substring(0, 11); } } Agora, digamos que queremos verificar se uma string contém uma substring, ou seja, uma string de tamanho menor ou igual à string original. Por exemplo, digamos que queremos verificar se uma string contém a substring “animal”. Para resolver este problema, utilizaremos o método contains da classe String: public class ExemploContains { public static void main(String[] args) { String umaString = "Ontem foi visto um animal na praça central."; /* * O método contains da classe String verifica a existência de uma * substring na string pesquisada. */ boolean temAnimalNaFrase = umaString.contains("animal"); // true /* * Agora, faremos uma verificação ignorando casos */ boolean temPracaNaFrase = umaString.toUpperCase().contains("CENTRAL"); // true } } Uma operação também possível em strings é substituir uma determinada substring por outra string. Para tanto, a classe String oferece dois métodos. O método replace substitui todas as ocorrências de uma substring por uma outra string desejada. Por sua vez, o método replaceAll substitui todas as substrings que correspondem a uma determinada expressão regular por uma outra string desejada. A seguir, alguns exemplos de substituições de strings:
  • 15. public class ExemploSubstituicoes { public static void main(String[] args) { String umaString = "A Ana comeu banana... mas que sacana!"; // A Ana comeu banana... mas que espertinha! System.out.println(umaString.replace("sacana", "espertinha")); // A Ana comeu bANAna... mas que sacANA! System.out.println(umaString.replace("ana", "ANA")); /* * Substitui todas as vogais minúsculas pelo dígito 0: * "A An0 c0m00 b0n0n0... m0s q00 s0c0n0!" */ System.out.println(umaString.replaceAll("[aeiou]", "0")); /* * Substitui todas as ocorrências da substring "ana" pela string "eno", * ignorando casos: "A eno comeu benona... mas que saceno!" */ System.out.println(umaString.replaceAll("(?i)ana", "eno")); /* * Substitui todas as vogais pela vogal 'i': * "i ini cimii binini... mis qii sicini!" */ System.out.println(umaString.replaceAll("(?i)[aeiou]", "i")); } } Por fim, uma operação comum a se realizar em strings é remover espaços em branco no início e no final. Muitas vezes usuários ao preencher formulários acabam deixando espaços em branco indesejados nestas posições. Para resolver este problema, a classe String oferece o método trim, cujo exemplo de uso é mostrado a seguir: public class ExemploTrim { public static void main(String[] args) { String umaString = " por gentileza, remova estes espaços em branco "; /* * O metodo trim da classe String remove os caracteres em branco no * início e no fim da string. */ umaString = umaString.trim(); // “por gentileza, remova estes espaços em branco” System.out.println(umaString); } } Exercícios: a) Escreva um programa que imprima os caracteres inicial, final e o situado exatamente no meio da frase “Eu sou um aspirante a programador de sucesso!”. b) Escreva um programa que substitua todas as ocorrências da substring “alo” na string “A Salomé escalonou os robalos que nadavam pelos ralos” pela string “ito”. c) Escreva um programa que armazene cada metade da string “Um dia eu fui uma string completa...” em uma variável distinta. d) Escreva um programa que insira o caractere '[' no início e o caractere ']' no final da string “Meu Deus, estou entre colchetes!”. e) Escreva um programa que armazene cada palavra da string “Um dia eu fui uma string completa...” em uma variável distinta, utilizando chamadas ao método substring.
  • 16. 10 - Lendo valores do usuário Todos os programas dos exemplos vistos até então nesta apostila não são interativos. Ou seja, eles não promovem a interação entre o usuário e computador. A partir de agora, vamos aprender a ler números e strings do usuário a fim de alimentar os nossos programas. 10.1 – Lendo dados do usuário via linha de comando Podemos ler números e strings do usuário via linha de comando em Java por meio da classe Scanner do pacote java.util. Para utilizar a classe Scanner em nossos programas, precisamos importar esta classe por meio da instrução import. O exemplo abaixo, lê um número inteiro do usuário, utilizando o método nextInt da classe Scanner. Note que na primeira linha de código nós realizamos a importação da classe Scanner: import java.util.Scanner; public class LeitorValorInteiroTeclado { public static void main(String[] args) { Scanner leitor = new Scanner(System.in); // O código abaixo lê um valor inteiro do teclado System.out.println("Digite a sua idade:"); int idade = leitor.nextInt(); System.out.println("Você tem " + idade + " anos de idade."); } } Para realizar a leitura de números reais do usuário, utilizamos o método nextFloat da classe Scanner. Lembre-se de utilizar vírgula ao invés de ponto quando for informar o número real na leitura. A seguir, um exemplo de leitura de um número real com o método nextFloat: import java.util.Scanner; public class LeitorValorPontoFlutuanteTeclado { public static void main(String[] args) { Scanner leitor = new Scanner(System.in); // O código abaixo lê um valor inteiro e um valor float do teclado System.out.println("Digite a sua idade:"); int idade = leitor.nextInt(); System.out.println("Digite o seu peso em kg:"); float peso = leitor.nextFloat(); System.out.println("Você tem " + idade + " anos e pesa " + peso + " kg."); } } Por fim, para realizar a leitura de strings do usuário via linha de comando, utilizamos o método nextLine da classe Scanner. O programa a seguir lê do usuário a sua comida preferida: import java.util.Scanner; public class LeitorStringTeclado { public static void main(String[] args) { Scanner leitor = new Scanner(System.in); /* * O código abaixo lê uma string do teclado. * Ao terminar de digitar a string, o usuário * deve teclar ENTER. */ System.out.println("Qual a sua comida favorita?"); String resposta = leitor.nextLine(); System.out.println("A sua comida favorita é " + resposta + "."); } }
  • 17. 10.2 – Lendo dados do usuário via janelas de Dialog Opcionalmente, você pode realizar a leitura dos dados do usuário via janelas de Dialog, a fim de deixar o seu programa mais amigável ao usuário. Você pode também exibir o resultado do processamento do seu programa em uma janela de Dialog. Para realizar esta tarefa, utilizaremos a classe JOptionPane do pacote javax.swing. O método showInputDialog da classe JOptionPane exibe uma janela de Dialog com um campo de texto para a leitura. Por exemplo, considere o exemplo contido na classe LeitorValorInteiroTeclado da seção 10.1. Naquele exemplo, o programa lia a idade do usuário via linha de comando. Utilizando o método showInputDialog podemos criar uma janela de Dialog como a da figura abaixo: Após lermos a idade do usuário, exibiremos uma frase informando a sua idade por meio do método showMessageDialog da classe JOptionPane, o qual criará uma janela de Dialog simples de mensagem. A janela de saída ficará como a janela da figura abaixo: Abaixo, o programa correspondente: import javax.swing.JOptionPane; public class LeitorInteiroDialog { public static void main(String[] args) { /* * Exibe uma janela para ler a resposta do usuário. * Após, exibe outra janela para exibir a resposta * digitada pelo usuário. */ String resposta = JOptionPane.showInputDialog("Qual a sua idade?"); int idade = Integer.parseInt(resposta); // Converte a string em inteiro JOptionPane.showMessageDialog(null, "Você tem " + idade + " anos de idade."); } } O método showInputDialog sempre retorna strings. Assim, para converter a idade informada pelo usuário em um valor inteiro, utilizamos o método parseInt da classe Integer. Na última linha utilizamos o método showMessageInputDialog para exibir a janela com a mensagem ao usuário. Em um outro momento, veremos como customizar estas janelas de entrada e saída de dados. O programa logo a seguir lê a idade e o peso do usuário, convertendo a string com a informação do peso em um valor do tipo float. O segundo programa a seguir exibe a simples leitura de strings do usuário:
  • 18. import javax.swing.JOptionPane; public class LeitorFloatDialog { public static void main(String[] args) { String resposta = JOptionPane.showInputDialog("Qual a sua idade?"); int idade = Integer.parseInt(resposta); // Converte a string em inteiro resposta = JOptionPane.showInputDialog("Qual o seu peso em kg?"); float peso = Float.parseFloat(resposta); // Converte a string em float JOptionPane.showMessageDialog(null, "Você tem " + idade + " anos de idade" + "e pesa " + peso + " kg."); } } import javax.swing.JOptionPane; public class LeitorStringDialog { public static void main(String[] args) { /* * Exibe uma janela para ler a resposta do usuário. * Após, exibe outra janela para exibir a resposta * digitada pelo usuário. */ String resposta = JOptionPane.showInputDialog("Qual a sua comida favorita?"); JOptionPane.showMessageDialog(null, "A sua comida favorita é " + resposta); } } Exercícios a) Escreva um programa que leia do usuário o seu nome completo e informa a ele quantos caracteres o seu nome possui (lembre-se de não contar espaços em branco). b) Escreva um programa que leia duas frases do usuário e exibe a na tela a segunda frase concatenada com a primeira frase. c) Escreva um programa que leia do usuário o valor do raio de uma circunferência e exiba na tela o valor da área desta circunferência. d) Escreva um programa que leia do usuário o tamanho dos lados de um retângulo e imprima na tela o valor da área deste retângulo. e) Escreva um programa que leia uma frase do usuário e imprima os caracteres inicial, final e o situado exatamente no meio da frase. 11 - Controlando o fluxo do programa Cada programa visto nos exemplos desta apostila até então possui um único fluxo possível de execução. Isto significa que todas as linhas de código do programa serão executadas, a menos que ocorra algum tipo de erro durante a execução do programa. Porém, existem muitos problemas em que desejamos poder controlar o fluxo de execução do nosso programa, ou seja, controlar quais linhas de código serão executadas de acordo com uma ou mais condições. Neste caso, o programa terá mais de um fluxo de execução possível. Por exemplo, considere o programa que lê a idade do usuário. Digamos que desejamos customizar a mensagem ao usuário de acordo com a sua idade. Se o usuário tiver menos de 18 anos, informamos que ele é menor de idade; caso contrário, informamos que ele já é maior de idade. Para resolver este problema, utilizaremos as instruções if e else da linguagem Java. A seguir, o programa correspondente:
  • 19. import java.util.Scanner; public class ExemploIfElse { public static void main(String[] args) { Scanner leitor = new Scanner(System.in); System.out.println("Digite a sua idade:"); int idade = leitor.nextInt(); if (idade < 18) { // se idade maior que 18, então: System.out.println("Você é menor de idade."); } else { // senão System.out.println("Você é maior de idade."); } } } A instrução if recebe como argumento um valor booleano. No nosso caso, passamos como argumento uma expressão lógica, que por sua vez resultará em um valor booleano. Se este valor for igual a true, então o código delimitado pelas chaves da instrução if será executado; caso contrário, o código delimitado pelas chaves da instrução else será executado. No exemplo acima, temos apenas duas situações que são mutuamente exclusivas. Porém, existem vários problemas os quais necessitam de múltiplas condições para realizar o roteamento de múltiplos fluxos de execução possíveis. O programa abaixo lê a idade do usuário e informa em que faixa de idade o usuário se encontra: import java.util.Scanner; public class ExemploCondicoesMultiplas { public static void main(String[] args) { Scanner leitor = new Scanner(System.in); System.out.println("Digite a sua idade:"); int idade = leitor.nextInt(); if (idade <= 10) { System.out.println("Você tem menos de 11 anos."); } else if (idade <= 20) { System.out.println("Você tem entre 11 e 20 anos."); } else if (idade <= 30) { System.out.println("Você tem entre 21 e 30 anos."); } else if (idade <= 50) { System.out.println("Você tem entre 31 e 50 anos."); } else { System.out.println("Você tem mais de 50 anos."); } } } Agora, considere este problema. Após lermos a idade do usuário, devemos informar se ele é menor ou maior de idade. Além disso, se a idade do usuário for ímpar, também informaremos tal fato. O programa a seguir resolve este problema:
  • 20. import java.util.Scanner; public class ExemploIfsNaoExclusivos { public static void main(String[] args) { Scanner leitor = new Scanner(System.in); System.out.println("Digite a sua idade:"); int idade = leitor.nextInt(); if (idade < 18) { // se idade maior que 18, então: System.out.println("Você é menor de idade."); } else { // senão System.out.println("Você é maior de idade."); } /* * Utilizamos o operador MOD (%) para verificar se o número abaixo é * ímpar. O operador MOD retorna o resto da divisão inteira entre o * primeiro número e o segundo. */ if (idade % 2 == 1) { System.out.println("Você possui uma idade ímpar."); } } } Note que neste exemplo temos duas condições não exclusivas, pois a condição do segundo if é executada de forma independente ao primeiro if. Como você já deve ter observado, o código controlado por toda instrução if e else é delimitado por chaves. Quando o código de uma instrução if ou else possui apenas uma linha, o uso de chaves é opcional, como mostra o exemplo a seguir: import java.util.Scanner; public class ExemploIfSemChaves { public static void main(String[] args) { Scanner leitor = new Scanner(System.in); System.out.println("Qual a sua cor preferida?"); String cor = leitor.nextLine(); if (cor.equalsIgnoreCase("amarelo")) System.out.println("Legal! Amarelo é uma cor tranquila."); else System.out.println("Hmmm... prefiro amarelo."); } } Agora, imagine que devemos escrever um programa que simule uma calculadora simples, capaz de efetuar adições, subtrações, multiplicações e divisões. O nosso programa funcionará da seguinte forma. Ele solicitará ao usuário dois números reais. Após isto, ele exibirá ao usuário um menu de operações matemáticas a serem realizadas sobre os números que ele informou, conforme abaixo: Escolha a operação desejada: 1 – Soma 2 – Subtração 3 – Multiplicação 4 – Divisão Por exemplo, se o usuário deseja multiplicar os dois números que ele informou, então ele escolherá a opção 3, digitando assim este número no teclado para que o programa possa enfim realizar a multiplicação dos dois valores. Vamos resolver este problema utilizando as instruções if e else:
  • 21. import java.util.Scanner; public class Calculadora { public static void main(String[] args) { Scanner leitor = new Scanner(System.in); System.out.println("Digite o primeiro valor:"); double primeiroValor = leitor.nextFloat(); System.out.println("Digite o segundo valor:"); double segundoValor = leitor.nextFloat(); System.out.println("Escolha a operação desejada:"); System.out.println("1 - Soma"); System.out.println("2 - Subtração"); System.out.println("3 - Multiplicação"); System.out.println("4 - Divisão"); int opcao = leitor.nextInt(); double resultado = 0; if (opcao == 1) { resultado = primeiroValor + segundoValor; } else if (opcao == 2) { resultado = primeiroValor - segundoValor; } else if (opcao == 3) { resultado = primeiroValor * segundoValor; } else if (opcao == 4) { // Evita a divisão por 0, pois isto causa um erro. if (segundoValor != 0) { resultado = primeiroValor / segundoValor; } else { System.out.println("Não é possível dividir por zero!"); } } else { System.out.println("Opção inválida."); } if (opcao <= 4) { System.out.println("Resultado: " + resultado); } } } No programa acima, foi escrita uma instrução if para cada valor de escolha possível no menu. Problemas de decisão deste tipo podem ser implementados utilizando a instrução switch. Reescreveremos a classe Calculadora, utilizando uma instrução switch para realizar o controle da opção escolhida:
  • 22. import java.util.Scanner; public class Calculadora { public static void main(String[] args) { Scanner leitor = new Scanner(System.in); System.out.println("Digite o primeiro valor:"); double primeiroValor = leitor.nextFloat(); System.out.println("Digite o segundo valor:"); double segundoValor = leitor.nextFloat(); System.out.println("Escolha a operação desejada:"); System.out.println("1 - Soma"); System.out.println("2 - Subtração"); System.out.println("3 - Multiplicação"); System.out.println("4 - Divisão"); int opcao = leitor.nextInt(); double resultado = 0; switch (opcao) { case 1: resultado = primeiroValor + segundoValor; break; case 2: resultado = primeiroValor - segundoValor; break; case 3: resultado = primeiroValor * segundoValor; break; case 4: if (segundoValor != 0) { resultado = primeiroValor / segundoValor; } else { System.out.println("Não é possível dividir por zero!"); } break; default: System.out.println("Opção inválida."); } if (opcao <= 4) { System.out.println("Resultado: " + resultado); } } } No exemplo acima, a instrução switch escolhe o fluxo correto de acordo com a opção digitada pelo usuário. Caso a opção digitada seja 1, 2 3 ou 4, o cálculo correto é realizado com os dois números reais informados pelo usuário. Note que ao final de cada instrução case existe uma instrução break. A instrução break interrompe a execução da instrução switch. Ou seja, o programa irá executar o código seguinte ao final da instrução switch. A instrução break é opcional. No nosso caso, ela é necessária para garantir que, assim que o cálculo correto for realizado, o programa sairá da instrução switch. Note também que no final da instrução switch foi colocada uma instrução default. O código de uma instrução default só é executado caso nenhum dos casos seja satisfeito. No nosso exemplo, se o usuário digitar uma opção inválida, ou seja, diferente de 1, 2, 3 ou 4, então o código da instrução default é executado, informando que a opção digitada pelo usuário é inválida. A instrução break não foi escrita no final da instrução default, pois como a instrução default simboliza o último caso possível dentro da instrução switch, não existe a necessidade de se interromper a execução da instrução switch neste ponto. Apenas uma instrução default pode ser escrita dentro de uma instrução switch. Condições mutuamente exclusivas do tipo if-else que definem o valor de uma variável podem ser escritas utilizando uma operação ternária. Considere o exemplo a seguir:
  • 23. public class VerificaParidade { public static void main(String[] args) { // Sorteia um número entre [0..100] // O tipo long armazena números inteiros de alta precisão long numeroAleatorio = System.currentTimeMillis() % 101; String resposta = numeroAleatorio + " é "; if (numeroAleatorio % 2 == 0) { resposta += "par"; } else { resposta += "ímpar"; } System.out.println(resposta); } } Neste exemplo, um valor inteiro é sorteado e então o programa deve informar se o número é par ou ímpar. As instrução if e else definem qual a resposta correta a ser armazenada na variável resposta, cujo valor será impresso na tela. Vamos reescrever este programa, utilizando uma operação ternária: public class VerificaParidade { public static void main(String[] args) { // Sorteia um número entre [0..100] // O tipo long armazena números inteiros de alta precisão long numeroAleatorio = System.currentTimeMillis() % 101; String resposta = numeroAleatorio + " é "; resposta += numeroAleatorio % 2 == 0 ? "par" : "impar"; System.out.println(resposta); } } Uma operação ternária é escrita da seguinte forma: v = c ? a : b; Na expressão acima, v representa a variável que irá receber o valor da expressão. O símbolo c representa a condição lógica a ser testada na expressão. O símbolo a representa o valor a ser atribuído a v caso a condição c seja satisfeita. Por fim, b representa o valor a ser atribuído a v caso a condição c não seja satisfeita. Exercícios: a) Escreva um programa que leia um número inteiro do usuário e informe ao usuário se este número é divisível por 7. b) Escreva um programa leia do usuário sua altura e peso, calcule o seu índice de massa corporal (IMC) e informe na tela o seu grau de obesidade. O IMC é dado pela fórmula abaixo: IMC = peso / altura² Abaixo, os graus de obesidade referentes a cada faixa de IMC: IMC < 18.5: Abaixo do peso 18.5 <= IMC <= 24.9: Peso normal 24.9 < IMC <= 29.9: Sobrepeso 29.9 < IMC <= 34.9: Obesidade de grau I 34.9 < IMC <= 39.9: Obesidade de grau c) Escreva um programa que leia as notas de quatro provas do usuário, calcula a média das notas. Se a média for maior ou igual a 7, então informe ao usuário que ele foi aprovado. Se a média for maior que 5 e menor que 7, informe que ele está de recuperação. Por fim, se a média for inferior a 5, informe que ele foi reprovado.
  • 24. 12 - Utilizando laços de repetição Imagine que devemos escrever um programa para imprimir na tela a sequência de 1 até 4 em uma mesma linha. Este problema é extremamente simples e é resolvido pelo programa abaixo: public class ProblemaSimplesDemais { public static void main(String[] args) { System.out.println("1 2 3 4"); } } Agora, considere que o nosso problema seja criar um programa que leia do usuário um valor inteiro positivo n e imprima na tela a sequência de 1 até n em uma mesma linha. Vamos tentar resolver este problema utilizando a mesma estratégia da solução anterior: public class SolucaoNaoMuitoInteligente { public static void main(String[] args) { System.out.println("Digite um numero inteiro positivo:"); Scanner leitor = new Scanner(System.in); int n = leitor.nextInt(); // Garantindo que o valor de n seja positivo... if (n < 0) { n = n * -1; } else if (n == 0) { n = 1; } // E lá vamos nós... if (n == 1) { System.out.println("1"); } else if (n == 2) { System.out.println("1 2"); } else if (n == 3) { System.out.println("1 2 3"); } else if (n == 4) { System.out.println("1 2 3 4"); } else if (n == 5) { System.out.println("1 2 3 4 5"); } else if (n == 6) { System.out.println("1 2 3 4 5 6"); } // .. continua... até quando? } } Obviamente, o programa acima não consegue resolver o problema de fato, uma vez que ele só informa a resposta correta para valores de n entre [1..6]. O grande problema do programa acima é que ele não é escalável aos valores de n, ou seja, ele não consegue resolver o problema para qualquer valor de n. A questão é: como saberemos quais os possíveis valores de n que o usuário poderá digitar? Não há como saber! Ele pode digitar qualquer valor superior a 0. Assim, quantas condições lógicas necessitaríamos para resolver o problema de fato? Na realidade, infinitas condições! Desta forma, precisamos escrever um código que seja capaz de imprimir todos os números da sequência, porém utilizando um número fixo e mínimo de linhas de código. Para tanto, precisamos de alguma forma escrever um código que repita a impressão dos números de forma categórica e estratégica. Para realmente resolver este problema, precisamos utilizar um laço de repetição. A linguagem Java oferece três laços de repetição distintos: o laço while, o laço do-while e o laço for. O programa a seguir resolve o nosso problema utilizando um laço while:
  • 25. import java.util.Scanner; public class ExemploWhile { public static void main(String[] args) { System.out.println("Digite um numero inteiro positivo:"); Scanner leitor = new Scanner(System.in); int n = leitor.nextInt(); // Garantindo que o valor de n seja positivo... if (n < 0) { n = n * -1; } else if (n == 0) { n = 1; } int contador = 1; while (contador <= n) { System.out.print(contador + " "); contador++; } } } O laço while recebe como argumento uma condição lógica, chamada de condição de manutenção do laço. No nosso exemplo, enquanto o valor da variável contador for menor ou igual ao valor da variável n, o laço while repetirá a execução do código localizado entre as chaves. Note que agora para qualquer valor de n a mensagem correta será impressa. A variável contador é inicializada com o valor 1, que é o primeiro valor que o nosso programa deve imprimir. A cada iteração, o valor da variável contador é impresso. Logo em seguida, o valor da variável é incrementado em uma unidade. Assim, na próxima iteração, o valor a ser impresso é uma unidade maior que o valor atual. O laço while só é executado se e somente se a sua condição lógica de manutenção for satisfeita. Assim, para que um laço while execute ao menos uma iteração, a sua condição lógica de manutenção deve ser satisfeita ao menos uma vez. Agora, resolveremos o problema mais uma vez, porém utilizando o laço do-while: import java.util.Scanner; public class ExemploDoWhile { public static void main(String[] args) { System.out.println("Digite um numero inteiro positivo:"); Scanner leitor = new Scanner(System.in); int n = leitor.nextInt(); // Garantindo que o valor de numero seja positivo... if (n < 0) { n = n * -1; } else if (n == 0) { n = 1; } int contador = 0; do { contador++; System.out.print(contador + " "); } while (contador < n); } } Neste exemplo, o laço do-while repete a execução do trecho de código localizado entre as chaves enquanto o valor da variável contador for menor que o valor da variável n. A variável contador é inicializada com o valor 0. Este não é o valor correto do primeiro valor a ser impresso, porém no início de cada iteração, o valor da variável contador é incrementado em uma unidade. Logo em seguida, o valor correto é impresso na tela. O laço é executado até que o valor da variável contador seja menor que o valor da variável n. Isto parece um tanto anti-intuitivo no início mas, se você analisar o código acima, você verá que esta condição se deve ao fato de que o incremento do valor da variável contador é realizado antes de que este seja impresso na tela.
  • 26. O laço do-while sempre executa ao menos uma iteração. Assim, para que um laço do-while execute após a primeira iteração, a sua condição lógica de manutenção deve ser satisfeita ao menos uma vez. Por fim, resolveremos novamente o problema, agora utilizando o laço for: import java.util.Scanner; public class ExemploFor { public static void main(String[] args) { System.out.println("Digite um numero inteiro positivo:"); Scanner leitor = new Scanner(System.in); int n = leitor.nextInt(); // Garantindo que o valor de numero seja positivo... if (n < 0) { n = n * -1; } else if (n == 0) { n = 1; } for(int contador = 1; contador <= n; contador++) { System.out.print(contador + " "); } } } No exemplo acima, o laço for pode ser lido da seguinte forma: para o valor de contador partindo de 1 até atingir o valor de n, incrementando o valor de contador em uma unidade a cada iteração, repita o trecho de código entre as chaves. O primeiro argumento de um laço for contém as inicializações desejadas para o laço. No caso, a variável contador é inicializada com o valor 1. Esta inicialização é executada somente uma vez, antes mesmo da execução da primeira iteração do laço. O segundo argumento de um laço for é a condição lógica de manutenção do laço. Ou seja, é o teste lógico realizado antes de cada iteração para avaliar se a iteração deve ser executada ou se o laço deve parar de executar iterações. No caso, o laço executará enquanto o valor da variável contador for menor ou igual ao valor da variável n. O terceiro e último argumento de um laço for contém o código a ser executado no final de cada iteração. No caso, após o valor da variável contador ser exibido, ele é incrementado em uma unidade. Desta forma, o código contido no primeiro argumento do laço for é executado apenas uma vez e antes do laço começar a sua execução. A condição de manutenção do laço contida no segundo argumento do laço for é executada sempre e antes da execução de cada iteração. Por fim, o código contido no terceiro e último argumento do laço for é executado sempre e no final da execução de cada iteração. O uso de qualquer um dos argumentos do laço for é opcional. O programa abaixo ilustra a omissão dos argumentos do laço for: public class ExemploOmissaoArgumentosFor { public static void main(String[] args) { int i = 0; // Omitimos o primeiro argumento, pois ele não é necessário neste caso for (; i < 10; i++) { System.out.println("Linha " + i); } // Omitimos o terceiro argumento, pois ele não é necessário neste caso for (i = 0; i < 10;) { System.out.println("Linha " + i); i++; } // A omissão do segundo argumento pode fazer com que o laço execute // infinitamente. Para terminar a execução do programa, digite CTRL + C for (i = 0;; i++) { System.out.println("Linha " + i); } } }
  • 27. Os três argumentos do laço for podem ser combinados para diversas finalidades. O programa abaixo exibe na tela uma sequência numérica regressiva: public class SequenciaRegressivaFor { public static void main(String[] args) { int numero = 10; for (int i = numero; i > 0; i--) { System.out.print(i + " "); } } } Abaixo, um exemplo mais complexo do uso do laço for: import java.util.Scanner; public class ExemploComplexoFor { public static void main(String[] args) { System.out.println("Digite um numero inteiro positivo:"); Scanner leitor = new Scanner(System.in); int n = leitor.nextInt(); // Garantindo que o valor de numero seja positivo... if (n < 0) { n = n * -1; } else if (n == 0) { n = 1; } for (int contador = n, contador2 = n, contador3 = n; contador >= 0 && contador2 >= 0 && contador3 >= 0; contador--, contador2 -= 2, contador3 -= 3) { System.out.print("[" + contador + ", "); System.out.print(contador2 + ", "); System.out.print(contador3 + "] "); } } } Exercícios: a) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na tela a sequência: 1 2 3 … n-1 n Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa: 1 2 3 4 5 b) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na tela a sequência: n n-1 n-2 … 3 2 1 Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa: 5 4 3 2 1 c) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na tela a sequência: 1, 2, 3, … n-1, n
  • 28. Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa: 1, 2, 3, 4, 5 d) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na tela a sequência: n-1, n-2, n-3, … 3, 2, 1 Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa: 5, 4, 3, 2, 1 e) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na tela a sequência: [1|2|3|...|n-1|n] Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa: [1|2|3|4|5] f) Escreva um programa que leia do usuário um valor inteiro positivo n e imprima na tela a sequência: 1, 2, 3, … n, n-1, n-2,..., 3, 2, 1 Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser impressa: 1, 2, 3, 4, 5, 4, 3, 2, 1 g) Escreva um algoritmo que leia do usuário um valor n entre [1..100] e então imprima na tela a seguinte sequência: 1, 1, 2 1, 2, 3 ... 1, 2, 3, …, n - 1, n 1, 2, 3, …, n – 1 … 1, 2, 3 1, 2 1 Por exemplo, caso o valor n seja 5, a seguinte sequência abaixo deve ser impressa: 1 1, 2 1, 2, 3 1, 2, 3, 4 1, 2, 3, 4, 5 1, 2, 3, 4 1, 2, 3 1, 2 1 Caso o valor de n seja 1, então a sequência abaixo deve ser impressa: 1
  • 29. h) Escreva um programa leia do usuário valores inteiros entre [0..100] até que o usuário digite o valor -1 e calcule a média aritmética destes valores (P.S.: o valor -1 não deve ser incluído no cálculo). i) Escreva um programa que leia do usuário 10 valores inteiros entre [0..100] e calcule o produto destes valores. j) Escreva um programa que leia do usuário um valor n entre [1..100] e imprima na tela os primeiros n números da sequência de Fibonacci. Em uma sequência de Fibonacci, cada valor é a soma dos dois últimos valores da sequência anteriores a ele. Como exemplo, a linha abaixo contém os oito primeiros números da sequência de Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13 13 – Matrizes Todas as variáveis que criamos em nossos exemplos até então possuem a capacidade de armazenamento de apenas um valor por vez. Por exemplo, considere o programa abaixo: public class ValorNumero { public static void main(String[] args) { int numero = 1; numero = 2; numero = 4; numero = -9; System.out.println(numero); } } Durante a sua execução, o programa atribui quatro valores distintos à variável numero, porém apenas o valor -9 é impresso, pois este foi o último valor associado à variável. Ou seja, não é possível armazenar mais de um valor simultaneamente na variável numero. O programa abaixo exibe uma possível solução a este problema: public class DiversosValores { public static void main(String[] args) { int numero1 = 1; int numero2 = 2; int numero3 = 4; int numero4 = -9; System.out.println(numero1); System.out.println(numero2); System.out.println(numero3); System.out.println(numero4); } } Neste exemplo, cada valor foi armazenado em uma variável distinta e o valor de cada variável foi impresso separadamente no final do programa. Note que se tivéssemos que armazenar mais valores, teríamos que criar mais variáveis, além de mais instruções para exibir tais valores na tela. Desta forma, esta solução deixa de ser prática à medida que o número de valores aumenta. Uma solução mais elegante ao problema anterior é utilizar uma matriz para assim poder armazenar vários valores em uma única variável. Matrizes são estruturas de dados que representam uma coleção de elementos, onde cada elemento é representado por uma única chave. O programa abaixo apresenta uma possível solução ao problema anterior, utilizando uma matriz para armazenar os valores:
  • 30. public class MatrizValores { public static void main(String[] args) { int[] numeros = new int[4]; numeros[0] = 1; numeros[1] = 2; numeros[2] = 4; numeros[3] = -9; for (int i = 0; i < numeros.length; i++) { System.out.println(numeros[i]); } } } Vamos analisar este programa passo-a passo. Na primeira linha do algoritmo do programa, foi criada uma matriz de inteiros de tamanho quatro, ou seja, capaz de armazenar quatro valores inteiros. Preste atenção na sintaxe de declaração e instanciação desta matriz. No código anterior ao símbolo de atribuição (=) foi declarada uma variável chamada numeros. Note que diferentemente à sintaxe de declaração de uma variável comum do tipo int, foram colocados colchetes de abertura e encerramento ([]) após a palavra reservada int. Isto denota que a variável sendo criada é uma matriz e será capaz de armazenar um conjunto de valores inteiros. Nós dizemos que o código anterior ao símbolo de atribuição representa a declaração da variável numeros. No código posterior ao símbolo de atribuição a variável numeros é instanciada, ou seja, é alocado o espaço de memória a ser ocupado pela variável. Neste exemplo, a variável numeros obtém espaço de memória suficiente para armazenar quatro valores do tipo int. Como cada valor do tipo int utiliza 4 bytes de memória de armazenamento, a matriz numeros ocupará 16 bytes de memória, ou seja, 4 bytes * 4 espaços. Assim, dizemos que o código posterior ao símbolo de atribuição representa a instanciação da variável numeros. Este tipo de instanciação é dito instanciação direta, pois o número de elementos da matriz é definido explicitamente. Uma outra forma de instanciação é a indireta, como mostra a linha abaixo: int[] numeros = { 1, 2, 4, -9 }; Neste exemplo, em uma única linha a matriz numeros foi declarada, instanciada (indiretamente) e inicializada, ou seja, os seus valores já foram determinados. Este tipo de instanciação é dito indireto pois o número de elementos da matriz é definido implicitamente. No exemplo, ao passarmos quatro valores à matriz numeros, fica-se definido que esta matriz terá capacidade de armazenamento de quatro valores inteiros. Voltando ao exemplo da classe MatrizValores, da segunda à quinta linha do algoritmo é realizada a inicialização da matriz numeros, ou seja, ela recebe os valores os quais deve armazenar. Cada valor é atribuído separadamente e endereçado por meio de um índice específico. Os índices de uma matriz vão de 0 até o tamanho da matriz decrementado de uma unidade. Assim, a matriz numeros possui tamanho 4 e seus índices variam de 0 a 3, sendo 0 o índice do primeiro elemento e 3 o índice do último elemento. No caso da matriz numeros, os valores 1, 2, 4 e -9 são armazenados na posição 0, 1, 2 e 3 respectivamente. Abaixo, a representação gráfica da matriz numeros: Valores 1 2 4 -9 Índices 0 1 2 3 No final do programa, foi criado um laço for para auxiliar a exibição de cada valor armazenado na matriz. Note que a variável inteira i auxilia no acesso aos índices da matriz. Para tanto, durante a execução do laço for o valor de i varia de 0 até numeros.length – 1. Toda matriz em Java possui o atributo constante length, o qual armazena de forma implícita o tamanho da matriz. Por ser uma constante, o seu valor nunca deve ser alterado de forma implícita, mas sim ser utilizado para se obter de forma segura o tamanho da matriz sendo utilizada. Se você prestou atenção ao exemplo da classe MatrizValores e aos últimos parágrafos, você deve ter percebido que para acessar uma posição específica de uma matriz devemos utilizar o nome da variável da matriz seguido de um colchete de abertura ([), o número referente ao índice desejado e um colchete de fechamento. O programa abaixo
  • 31. exemplifica o acesso aos valores de uma matriz por meio de seus índices: public class ExemploAcessoPosicoes { public static void main(String[] args) { int[] matriz = { 23, 98, -173, 1, 99, 50 }; int terceiroNumero = matriz[2]; // -173 int ultimoNumero = matriz[matriz.length - 1]; // 50 int primeiroNumero = matriz[0]; // 23 } } Os exemplos anteriores exibiram matrizes de inteiros. É possível criar matrizes de todos os tipos que vimos até então nesta apostila. O programa abaixo ilustra algumas matrizes de tipos variados: public class MatrizesVariadas { public static void main(String[] args) { double[] matrizDouble = { -3.4, 5.7, 90D, 187.123 }; for (int i = 0; i < matrizDouble.length; i++) { System.out.println(matrizDouble[i]); } String[] diasSemana = { "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo" }; for (int i = 0; i < diasSemana.length; i++) { System.out.println(diasSemana[i]); } char[] conceitosNotas = { 'A', 'B', 'C', 'D', 'E' }; for (int i = 0; i < conceitosNotas.length; i++) { System.out.println(conceitosNotas[i]); } boolean[] matrizBooleanos = { true, true, false, true, false, false }; for (int i = 0; i < matrizBooleanos.length; i++) { System.out.println(matrizBooleanos[i]); } } } Um laço de repetição que não vimos na seção anterior é o laço for-each, o qual é utilizado para se percorrer matrizes e listas (não importa ainda o que é uma lista!). Este tipo de laço simplifica em muito a forma de se percorrer uma matriz, porém só pode ser utilizado para a leitura da matriz, ou seja, não é possível alterar qualquer valor da matriz no código interno a um laço for-each. Abaixo, a classe MatrizValores reescrita de tal forma a utilizar instanciação indireta e um laço for-each para exibir os valores da matriz numeros: public class MatrizValores { public static void main(String[] args) { int[] numeros = { 1, 2, 4, -9 }; for (int elemento : numeros) { System.out.println(elemento); } } } Você deve ter reparado que a classe MatrizValores ficou mais “enxuta” nesta versão, graças à instanciação indireta da matriz numeros e do uso do laço for-each para exibir os valores da matriz. Diferentemente do laço for convencional, o laço for-each (em português, “para cada”) possui apenas dois argumentos ao invés de três. Além disso, estes dois argumentos são obrigatórios e são separados por dois pontos (:) ao invés de ponto e vírgula (;). Para entender o funcionamento deste laço de repetição, devemos entender primeiramente o que é o segundo argumento do laço para depois entender o primeiro argumento. O segundo argumento de um laço for-each contém a matriz ou lista que desejamos percorrer. No nosso exemplo, desejamos percorrer a matriz numeros. O primeiro argumento contém a variável que vai armazenar o valor da matriz a ser visitado em cada iteração do laço de repetição. No nosso exemplo, a variável elemento guarda o valor atual sendo visitado na iteração. Antes do início da próxima iteração, o valor da variável elemento é
  • 32. atualizado com o valor do próximo elemento da matriz numeros. Dentro do contexto de matrizes, a classe String da linguagem Java oferece o método split, o qual quebra a string original de acordo com a ocorrência de uma substring, retornando assim uma matriz de strings. Para melhor ilustrar a utilidade do método split, veja o exemplo abaixo: public class ExemploSplit { public static void main(String[] args) { String frase = "Isto é uma frase completa"; // Quebra a string original em cada ocorrência de um espaço em branco String[] palavrasDaFrase = frase.split(" "); for (String palavra : palavrasDaFrase) { System.out.println(palavra); } } } Todas as matrizes que vimos nos exemplos desta seção até então são ditas matrizes unidimensionais, ou seja, matrizes de uma dimensão. Estas matrizes são comumente chamadas de matrizes lineares ou vetores. Em uma matriz bidimensional, cada elemento da matriz é endereçado por dois índices simultaneamente, um representando a linha da matriz em que o elemento se situa e o outro representando a coluna da matriz em que o elemento se situa. Por exemplo, considere a representação gráfica de uma matriz bidimensional abaixo: Linha/coluna 0 1 2 3 0 -9 0 6 24 1 7 500 1092 71 2 12 -128 67 100 No exemplo, o valor 7 está situado na linha 1, coluna 0. Desta forma, 1 e 0 são os seus índices de linha e coluna respectivamente. Da mesma forma, o valor 100 está situado na linha 2, coluna 3, sendo assim 2 e 3 os seus índices de linha e coluna. O programa abaixo cria uma matriz bidimensional para armazenar estes valores e depois percorre a matriz resultante utilizando dois laços for convencionais: public class ExemploMatrizBidimensional { public static void main(String[] args) { int[][] matrizBidimensional = { { -9, 0, 6, 24 }, { 7, 500, 1092, 71 }, { 12, -128, 67, 100 } }; /** * Os laços abaixo imprimirão no console: * -9 0 6 24 * 7 500 1092 71 * 12 -128 67 100 */ for (int i = 0; i < matrizBidimensional.length; i++) { for (int j = 0; j < matrizBidimensional[i].length; j++) { System.out.print(matrizBidimensional[i][j] + "t"); } System.out.println(""); } } } Na primeira linha do algoritmo foi declarada a matriz matrizBidimensional. Note que ao invés de somente um par de abertura-fechamento de colchetes, foram utilizados dois pares. A regra é que, para cada dimensão a ser utilizada, um par de abertura-fechamento de colchetes seja utilizado na declaração da variável da matriz. Assim, no exemplo são utilizados dois pares pois a nossa matriz é bidimensional. Outra diferença ocorre na instanciação da matriz. Você pode entender uma matriz bidimensional como um conjunto de matrizes unidimensionais. Imagine que em cada linha da matriz bidimensional, você tem uma matriz unidimensional. Assim, note que na instanciação
  • 33. da matriz do exemplo acima cada linha está separada por chaves. Desta forma, podemos entender que cada elemento da matriz bidimensional é uma matriz unidimensional (uma linha da matriz) e, em cada linha, temos um conjunto de valores. Como cada valor está armazenado em uma linha, que por sua vez está armazenada na matriz bidimensional, para acessar um valor na matriz necessitamos de dois índices: um para referenciar a linha correta onde o valor se encontra e outro para referenciar sua posição na linha. Assim, para percorrer a matriz bidimensional precisamos de dois laços de repetição, um para percorrer as linhas da matriz e, para cada linha da matriz, outro laço para percorrer os seus valores. Analisando o código do último exemplo, o primeiro laço de repetição (o que percorre as linhas matriz) não é diferente do laço que percorria as matrizes unidimensionais nos exemplos anteriores. No exemplo, o laço for utiliza um índice i que varia de 0 a matrizBidimensional.length – 1, ou seja, de 0 a 2, os índices das linhas da matriz. A grande diferença está no segundo laço for, o mais interno. Ele utiliza um índice j para percorrer cada valor da linha i. Assim, j varia de 0 a matrizBidimensional[i].length – 1, isto é, de 0 até o tamanho da linha decrementado em uma unidade. Por fim, note que cada valor da matriz é acessado utilizando os índices i e j, respectivamente linha e coluna. Se você prestou atenção a este último exemplo e ao último parágrafo, você pode estar se perguntando: por quê o valor de j vai até matrizBidimensional[i].length – 1 e não até 2, ou seja, uma constante fixa que se utilizada também resolveria o problema? Bem, existem dois motivos para tanto. Primeiramente, a forma na qual os dois laços for foram escritos é escalável no sentido que não importam as dimensões da matriz, ela será percorrida corretamente. Por fim, não necessariamente os tamanhos das linhas da matriz devem ser iguais! No exemplo abaixo, cada linha da matriz possui um tamanho diferente: public class MatrizTamanhosDistintos { public static void main(String[] args) { /** * Declara uma matriz bidimensional de dimensões variáveis. */ int[][] matrizBidimensional = { { 1, 2, 3, 4 }, { 5, 6 }, { 7, 8, 9 } }; for (int i = 0; i < matrizBidimensional.length; i++) { for (int j = 0; j < matrizBidimensional[i].length; j++) { System.out.print(matrizBidimensional[i][j] + "t"); } System.out.println(""); } } } Nos dois últimos exemplos as matrizes bidimensionais foram instanciadas indiretamente. O exemplo abaixo exibe uma matriz sendo instanciada diretamente, tendo seus valores preenchidos de forma automática por meio de dois laços for e, por fim, sendo exibida: public class MatrizBidimensionalInstDireta { public static void main(String[] args) { // Declara uma matriz bidimensional com dimensões explícitas de 4 x 3 int[][] matrizBidimensional = new int[4][3]; for (int i = 0; i < matrizBidimensional.length; i++) { for (int j = 0; j < matrizBidimensional[i].length; j++) { matrizBidimensional[i][j] = i + j; } } for (int i = 0; i < matrizBidimensional.length; i++) { for (int j = 0; j < matrizBidimensional[i].length; j++) { System.out.print(matrizBidimensional[i][j] + "t"); } System.out.println(""); } } } Também é possível percorrer uma matriz bidimensional utilizando laços for-each. O exemplo abaixo mostra uma matriz de Strings sendo percorrida por dois laços for-each:
  • 34. public class MatrizBidimensionalForEach { public static void main(String[] args) { // Declara uma matriz de strings com dimensões implícitas de 3 x 3 String[][] matrizStrings = { { "linha 0 coluna 0", "linha 0 coluna 1", "linha 0 coluna 2" }, { "linha 1 coluna 0", "linha 1 coluna 1", "linha 1 coluna 2" }, { "linha 2 coluna 0", "linha 2 coluna 1", "linha 2 coluna 2" }, }; for (String[] linha : matrizStrings) { for (String valor : linha) { System.out.print(valor + "t"); } System.out.println(""); } } } A matriz matrizStrings é uma matriz bidimensional; assim ela pode ser interpretada como um conjunto de linhas. Desta forma, o primeiro laço for-each do exemplo acima percorre as linhas da matriz, armazenando cada linha na matriz unidimensional linha. O laço for-each mais interno percorre cada valor de cada linha, armazenando cada valor na variável valor. É possível criar matrizes de várias dimensões, porém quanto maior o número de dimensões de uma matriz menor é o número de aplicações práticas para ela. Apenas a título de curiosidade, analise a matriz tridimensional do exemplo abaixo e tente entender o código do exemplo: public class ExemploMatrizTridimensional { public static void main(String[] args) { // Que tal uma matriz tridimensional de dimensões 2 x 2 x 3? :D int[][][] matriz = { { { 1, 2, 3 }, { 4, 5, 6 } }, { { 7, 8, 9 }, { 10, 11, 12 } } }; // Percorrendo a matriz tridimensional for (int[][] subMatriz : matriz) { for (int[] linha : subMatriz) { for (int elemento : linha) { System.out.print(elemento + "t"); } System.out.println(""); } System.out.println(""); } } } Exercícios: a) Escreva um programa que crie uma matriz unidimensional de inteiros de tamanho 10, preencha cada posição da matriz com um valor aleatório entre [0..100] e exiba em uma linha os elementos da matriz em ordem inversa. b) Escreva um programa que leia do usuário 10 valores inteiros, armazene tais valores em uma matriz unidimensional e exiba na tela apenas os valores que sejam divisíveis por 3. c) Escreva um programa que leia as notas de 15 alunos, exiba as notas lidas e informe qual foi a nota média, a maior nota e a menor nota. d) Escreva um programa que leia do usuário dez números reais, armazene tais valores
  • 35. em uma matriz unidimensional, calcule e mostre a quantidade de números negativos e a soma dos números positivos da matriz. e) Escreva um programa que sorteie 20 números inteiros, exiba os na tela em uma única linha (separados por vírgula) e depois leia do usuário um número inteiro x e verifique se x foi sorteado. f) Escreva um programa que leia dois números inteiros a e b, crie uma matriz de dimensões a x b, preencha aleatoriamente esta matriz com valores 0 ou 1 e exiba a matriz na tela de maneira bem formatada, ou seja, respeitando as posições dos elementos quanto a linha e coluna. g) Escreva um programa que leia uma matriz bidimensional de dimensões 4 x 4 e imprima a diagonal principal da matriz. h) Escreva um programa que leia dois números inteiros a e b, crie uma matriz de dimensões a x b, preencha a matriz com valores informados pelo usuário e depois imprima a matriz transposta da matriz original. A matriz transposta de uma matriz é a matriz resultante da troca de linhas por colunas da matriz original. Abaixo, alguns exemplos de matrizes transpostas: i) Escreva um programa que leia dois números inteiros a e b, crie uma matriz de dimensões a x b, preencha a matriz com valores informados pelo usuário e verifique se a matriz é simétrica. Uma matriz é dita simétrica se ela é igual à sua matriz transposta.