Projeto Calculadora
O primeiro projeto do guia: uma calculadora que roda no terminal. Ela pergunta a operação e os dois números, mostra o resultado e continua até você digitar sair. Parece simples, e é de propósito: o desafio não é a conta, é fazer o programa não quebrar quando alguém digita "abc", divide por zero ou escolhe uma operação que não existe.
- Ler números e texto do teclado com Scanner.
- Escolher a conta com o switch com setas.
- Organizar o código em métodos com parâmetros e retorno.
- Validar a entrada com
hasNextDouble(e ver o que acontece sem validar). - Tratar a divisão por zero de um double.
- Repetir tudo com while, break e continue.
O que vamos construir
Esta é a calculadora pronta, rodando na máquina da Ana. Tudo que aparece depois dos : nas perguntas foi digitado por ela:
$ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, / ou sair): + Primeiro número: 10 Segundo número: 5 10.0 + 5.0 = 15.0 Operação (+, -, *, / ou sair): / Primeiro número: 7 Segundo número: 2 7.0 / 2.0 = 3.5 Operação (+, -, *, / ou sair): % Operação desconhecida: % « operação que não existe Operação (+, -, *, / ou sair): * Primeiro número: seis "seis" não é um número. Tente de novo. « texto no lugar de número Primeiro número: 6 Segundo número: 1,5 « decimal com vírgula (veja a etapa 1) 6.0 * 1.5 = 9.0 Operação (+, -, *, / ou sair): / Primeiro número: 1 Segundo número: 0 Não dá para dividir por zero. Operação (+, -, *, / ou sair): sair Até logo!
Vamos chegar lá em seis etapas:
- Ler dois números e somar (
Scanner,nextDouble). - Escolher a operação (
switchcom setas). - Organizar em métodos (
calcular,lerNumero,operacaoValida). - Validar o que foi digitado (
hasNextDouble). - Não dividir por zero.
- Repetir até "sair" (
while,break,continue).
Antes de começar
Você precisa saber criar e rodar um programa (Olá, Mundo), usar variáveis double e String e ter visto o básico do Scanner. No seu computador, crie a pasta do projeto; o arquivo vai se chamar Calculadora.java, porque a classe se chama Calculadora:
$ mkdir -p java/calculadora $ cd java/calculadora
Etapa 1 · Ler dois números e somar
O começo de toda calculadora: pedir dois números e mostrar a soma. Para ler do teclado, o Java usa um Scanner (em inglês, "leitor", "escâner"), um objeto que lê o que você digita e transforma em números ou texto.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Primeiro número: ");
double a = entrada.nextDouble();
System.out.print("Segundo número: ");
double b = entrada.nextDouble();
double soma = a + b;
System.out.println(a + " + " + b + " = " + soma);
}
}
| Linha | O que faz |
|---|---|
import java.util.Scanner; | Avisa que vamos usar a classe Scanner, que mora no pacote java.util. Sem isso, o javac diz cannot find symbol (veja Pacotes e import). |
Scanner entrada = new Scanner(System.in); | Cria o leitor. System.in é a entrada padrão: o teclado. Criamos um Scanner e usamos o programa inteiro. |
System.out.print("Primeiro número: "); | print, sem ln: não pula linha, então o que a pessoa digitar aparece logo depois dos dois-pontos. |
double a = entrada.nextDouble(); | Espera a pessoa digitar e apertar Enter, e converte o texto num double (número com casas decimais). |
a + " + " + b + " = " + soma | Junta números e texto numa frase só (concatenação). |
$ java Calculadora.java === Calculadora da Ana === Primeiro número: 10 Segundo número: 5 10.0 + 5.0 = 15.0
Repare no 10.0: a Ana digitou 10, mas a variável é double, e o Java sempre mostra um double com pelo menos uma casa decimal. Na última etapa você vai ver um desafio para deixar isso mais bonito.
O Scanner lê os números no formato do idioma do sistema. Na máquina da Ana, em português do Brasil, o separador decimal é a vírgula: 2,5 funciona e 2.5 dá erro. Já o println de um double sempre usa ponto:
$ java Calculadora.java === Calculadora da Ana === Primeiro número: 2,5 Segundo número: 1,25 2.5 + 1.25 = 3.75 $ java Calculadora.java === Calculadora da Ana === Primeiro número: 2.5 Exception in thread "main" java.util.InputMismatchException at java.base/java.util.Scanner.throwFor(Scanner.java:977) at java.base/java.util.Scanner.next(Scanner.java:1632) at java.base/java.util.Scanner.nextDouble(Scanner.java:2603) at Calculadora.main(Calculadora.java:9)
InputMismatchException quer dizer "a entrada não combina com o que foi pedido": o nextDouble queria um número e encontrou um texto que, em português, não é número. A última linha mostra onde: Calculadora.java, linha 9. Na etapa 4, a calculadora vai aprender a se defender disso.
Missão (etapa 1): o programa já lê o primeiro número. Leia o segundo número na variável b e mostre a soma no formato 10.0 + 5.0 = 15.0. A entrada 10 e 5 já vem preenchida.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Primeiro número: ");
double a = entrada.nextDouble();
// peça e leia o segundo número
// calcule e mostre a soma
}
}
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Primeiro número: ");
double a = entrada.nextDouble();
System.out.print("Segundo número: ");
double b = entrada.nextDouble();
double soma = a + b;
System.out.println(a + " + " + b + " = " + soma);
}
}
Etapa 2 · Escolher a operação
Agora a calculadora pergunta qual conta fazer. A operação é um texto ("+", "-"…), lido com entrada.next(), que devolve a próxima "palavra" digitada. Para escolher a conta, um switch com setas: ele compara o texto com cada case e devolve o valor da seta escolhida.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Primeiro número: ");
double a = entrada.nextDouble();
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
System.out.print("Segundo número: ");
double b = entrada.nextDouble();
double resultado = switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> {
System.out.println("Operação desconhecida: " + op);
yield 0;
}
};
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
}
- double resultado =
- O
switchaqui é uma expressão: ele produz um valor, que vai pararesultado. - switch (op)
- Olha o valor de
ope procura ocaseigual. ComString, a comparação é pelo conteúdo do texto. - case "+" -> a + b;
- Se
opfor"+", o valor do switch éa + b. A seta->não "cai" no próximo case: não precisa debreak. - default -> { … yield 0; }
- Qualquer outro texto. Como aqui há duas instruções, elas vão entre chaves, e
yield("render", "entregar") diz qual valor o switch devolve.
$ java Calculadora.java === Calculadora da Ana === Primeiro número: 10 Operação (+, -, *, /): * Segundo número: 4 10.0 * 4.0 = 40.0 $ java Calculadora.java === Calculadora da Ana === Primeiro número: 10 Operação (+, -, *, /): / Segundo número: 4 10.0 / 4.0 = 2.5 $ java Calculadora.java === Calculadora da Ana === Primeiro número: 10 Operação (+, -, *, /): x Segundo número: 4 « a operação é inválida, mas ele pede o número mesmo assim Operação desconhecida: x 10.0 x 4.0 = 0.0 « e ainda mostra um resultado falso
A divisão 10.0 / 4.0 deu 2.5, e não 2, porque os dois números são double (divisão inteira só acontece entre inteiros; veja Operadores Aritméticos). A terceira execução mostra um defeito: com a operação x, o programa pede o segundo número à toa e mostra 0.0 como se fosse uma resposta. A etapa 3 conserta isso.
default
Este código tem um erro de propósito.
double resultado = switch (op) {
case "+" -> a + b;
case "-" -> a - b;
};
$ javac Calculadora.java
Calculadora.java:5: error: the switch expression does not cover all possible input values
double resultado = switch (op) {
^
1 error
"A expressão switch não cobre todos os valores possíveis." Um switch que devolve um valor precisa ter resposta para qualquer texto, e uma String pode ser qualquer coisa. Acrescente um default.
Missão (etapa 2): esta versão só sabe somar e subtrair. Acrescente os case de multiplicação (*) e divisão (/). A entrada da missão é 10, /, 4.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Primeiro número: ");
double a = entrada.nextDouble();
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
System.out.print("Segundo número: ");
double b = entrada.nextDouble();
double resultado = switch (op) {
case "+" -> a + b;
case "-" -> a - b;
default -> {
System.out.println("Operação desconhecida: " + op);
yield 0;
}
};
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
}
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Primeiro número: ");
double a = entrada.nextDouble();
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
System.out.print("Segundo número: ");
double b = entrada.nextDouble();
double resultado = switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> {
System.out.println("Operação desconhecida: " + op);
yield 0;
}
};
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
}
Etapa 3 · Organizar em métodos
O main está ficando comprido. Vamos separar o programa em métodos: blocos com nome, cada um com uma tarefa. É como numa cozinha: um cozinheiro corta, outro cozinha, outro monta o prato. Ao mesmo tempo, mudamos a ordem: a operação vem primeiro, e se ela for inválida o programa avisa e para, sem pedir os números à toa.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
return;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
| Método | Recebe | Devolve | Tarefa |
|---|---|---|---|
lerNumero | o Scanner e a pergunta | double | Mostra a pergunta e lê um número. Assim não repetimos print + nextDouble duas vezes. |
operacaoValida | a operação | boolean | true se for uma das quatro. case "+", "-", "*", "/" junta vários valores no mesmo case. |
calcular | os dois números e a operação | double | Faz a conta. Só faz conta: não lê teclado nem escreve na tela. Isso deixa o método fácil de testar e de reaproveitar. |
- static
- O método pertence à classe, e por isso o
main(que também éstatic) pode chamá-lo direto. Veja static. - double
- O tipo do valor devolvido (retorno).
- calcular(double a, String op, double b)
- O nome e os parâmetros: as "entradas" do método.
- return switch (op) { … };
- Devolve o valor que o switch produzir.
- default -> throw new IllegalArgumentException(…)
- Se alguém chamar
calcularcom uma operação inválida, o método lança uma exceção (avisa que recebeu um argumento ilegal) em vez de inventar um resultado. Veja throw e throws.
No main, o ! em !operacaoValida(op) quer dizer "não" (operadores lógicos), e o return sozinho encerra o main, ou seja, o programa.
$ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, /): - Primeiro número: 7 Segundo número: 2 7.0 - 2.0 = 5.0 $ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, /): % Operação desconhecida: % « agora ele para antes de pedir os números
Missão (etapa 3): o main chama calcular(a, op, b), mas o método ainda não existe (rode e veja o cannot find symbol). Escreva o método static double calcular(double a, String op, double b) com o switch das quatro operações.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
return;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
// escreva aqui o método calcular
}
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
return;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
Etapa 4 · Validar o que foi digitado
Hoje, se alguém digita uma palavra no lugar do número, a calculadora "explode":
$ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, /): + Primeiro número: abc Exception in thread "main" java.util.InputMismatchException at java.base/java.util.Scanner.throwFor(Scanner.java:977) at java.base/java.util.Scanner.next(Scanner.java:1632) at java.base/java.util.Scanner.nextDouble(Scanner.java:2603) at Calculadora.lerNumero(Calculadora.java:22) at Calculadora.main(Calculadora.java:14)
Leia o stack trace (a "pilha de chamadas") de baixo para cima: o main, na linha 14, chamou o lerNumero, que na linha 22 chamou o nextDouble, que lançou a exceção. As linhas com java.base/ são do próprio Java; as que importam para você são as do seu arquivo.
A solução é perguntar antes de ler. O método hasNextDouble() ("tem um próximo double?") olha o que foi digitado sem consumir e devolve true se aquilo é um número válido. Só mudamos o método lerNumero; o resto do programa fica igual:
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextDouble()) {
String lixo = entrada.next();
System.out.println("\"" + lixo + "\" não é um número. Tente de novo.");
System.out.print(pergunta);
}
return entrada.nextDouble();
}
- while (!entrada.hasNextDouble())
- "Enquanto o que foi digitado não for um número…" O
hasNextDoubleespera a pessoa digitar, se for preciso, mas não tira nada da entrada. - String lixo = entrada.next();
- Tira a palavra inválida da entrada. Esta linha é essencial: sem ela, o
hasNextDoubleolharia para o mesmo "abc" para sempre, num laço infinito. - "\"" + lixo + "\" …"
\"é uma aspa dentro do texto (caracteres especiais).- return entrada.nextDouble();
- Quando o laço termina, com certeza há um número esperando: agora é seguro ler.
$ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, /): + Primeiro número: abc "abc" não é um número. Tente de novo. Primeiro número: dez "dez" não é um número. Tente de novo. Primeiro número: 10 Segundo número: 2.5 « com ponto: em pt_BR, não é número "2.5" não é um número. Tente de novo. Segundo número: 2,5 10.0 + 2.5 = 12.5
Para cada nextXxx existe um hasNextXxx: hasNextInt(), hasNextLine(), hasNext()… Use-os sempre que a entrada vier de uma pessoa. A tabela completa está em Ler do Teclado (Scanner).
Missão (etapa 4): rode primeiro como está: a entrada da missão tem abc no lugar do primeiro número e o programa termina com InputMismatchException. Depois mude o lerNumero para usar hasNextDouble e mostrar "abc" não é um número. Tente de novo.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
return;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
return;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextDouble()) {
String lixo = entrada.next();
System.out.println("\"" + lixo + "\" não é um número. Tente de novo.");
System.out.print(pergunta);
}
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
Etapa 5 · Não dividir por zero
Na escola você aprendeu que não existe divisão por zero. O Java, com double, não reclama: ele responde com valores especiais.
$ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, /): / Primeiro número: 10 Segundo número: 0 10.0 / 0.0 = Infinity « "infinito" $ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, /): / Primeiro número: -10 Segundo número: 0 -10.0 / 0.0 = -Infinity $ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, /): / Primeiro número: 0 Segundo número: 0 0.0 / 0.0 = NaN « Not a Number: "não é um número"
Com números inteiros (int), a mesma conta não dá infinito: dá erro. Compare no JShell:
$ jshell | Welcome to JShell -- Version 25.0.4.1 | For an introduction type: /help intro jshell> 10 / 0 | Exception java.lang.ArithmeticException: / by zero | at (#1:1) jshell> 10.0 / 0 $2 ==> Infinity
Para uma calculadora de gente, "Infinity" não serve. Vamos conferir o divisor antes de calcular. No main, logo depois de ler o segundo número:
double b = lerNumero(entrada, "Segundo número: ");
if (op.equals("/") && b == 0) {
System.out.println("Não dá para dividir por zero.");
return;
}
double resultado = calcular(a, op, b);
- op.equals("/")
- Compara o conteúdo do texto. Nunca use
==para compararString(veja Strings). - &&
- "E": as duas condições precisam ser verdadeiras.
- b == 0
- Para números,
==está certo.0e0.0são iguais aqui. - return;
- Encerra o programa sem calcular. Na próxima etapa, ele vai virar
continue.
$ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, /): / Primeiro número: 10 Segundo número: 0 Não dá para dividir por zero.
Missão (etapa 5): com a entrada /, 10, 0, o programa mostra Infinity. Acrescente o if que mostra Não dá para dividir por zero. e encerra.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
return;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextDouble()) {
String lixo = entrada.next();
System.out.println("\"" + lixo + "\" não é um número. Tente de novo.");
System.out.print(pergunta);
}
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Operação (+, -, *, /): ");
String op = entrada.next();
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
return;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
if (op.equals("/") && b == 0) {
System.out.println("Não dá para dividir por zero.");
return;
}
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextDouble()) {
String lixo = entrada.next();
System.out.println("\"" + lixo + "\" não é um número. Tente de novo.");
System.out.print(pergunta);
}
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
Etapa 6 · Repetir até "sair"
Uma calculadora que faz uma conta e fecha não ajuda muito. A última etapa coloca o trabalho dentro de um laço while (true) ("enquanto verdadeiro", ou seja, para sempre) e dá duas saídas de emergência: break e continue. Só o main muda:
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
while (true) {
System.out.print("Operação (+, -, *, / ou sair): ");
String op = entrada.next();
if (op.equals("sair")) {
break;
}
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
continue;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
if (op.equals("/") && b == 0) {
System.out.println("Não dá para dividir por zero.");
continue;
}
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
System.out.println();
}
System.out.println("Até logo!");
}
| Instrução | O que acontece | Usada quando |
|---|---|---|
while (true) { … } | Repete o bloco sem parar, até um break. | Sempre: é o "programa ligado". |
break; | Sai do laço. O programa continua depois da } do while e mostra "Até logo!". | A pessoa digitou sair. |
continue; | Pula o resto desta volta e começa a próxima: pergunta a operação de novo. | Operação inválida ou divisão por zero. |
System.out.println(); | Escreve uma linha vazia, para separar uma conta da outra. | Depois de cada resultado. |
Os dois return da etapa anterior viraram continue: agora um erro não fecha o programa, só pula para a próxima conta. A sessão completa está em "O que vamos construir", no começo da página; aqui, uma bem curta:
$ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, / ou sair): + Primeiro número: 10 Segundo número: 5 10.0 + 5.0 = 15.0 Operação (+, -, *, / ou sair): sair Até logo!
No terminal do Linux, Ctrl+D significa "acabou a entrada". Se a Ana apertar isso na pergunta da operação, o next() não tem mais nada para ler:
$ java Calculadora.java === Calculadora da Ana === Operação (+, -, *, / ou sair): + Primeiro número: 10 Segundo número: 5 10.0 + 5.0 = 15.0 Operação (+, -, *, / ou sair): Exception in thread "main" java.util.NoSuchElementException at java.base/java.util.Scanner.throwFor(Scanner.java:975) at java.base/java.util.Scanner.next(Scanner.java:1516) at Calculadora.main(Calculadora.java:10)
NoSuchElementException = "não existe tal elemento". Para tratar, troque a condição do laço: while (entrada.hasNext()) só entra se ainda houver algo para ler. Fica como desafio.
Missão (etapa 6): coloque a parte de "perguntar e calcular" dentro de um while (true), saia com break quando a operação for sair e mostre Até logo! no fim. Troque os return por continue. A entrada da missão faz duas contas e sai.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
System.out.print("Operação (+, -, *, / ou sair): ");
String op = entrada.next();
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
return;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
if (op.equals("/") && b == 0) {
System.out.println("Não dá para dividir por zero.");
return;
}
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextDouble()) {
String lixo = entrada.next();
System.out.println("\"" + lixo + "\" não é um número. Tente de novo.");
System.out.print(pergunta);
}
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
while (true) {
System.out.print("Operação (+, -, *, / ou sair): ");
String op = entrada.next();
if (op.equals("sair")) {
break;
}
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
continue;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
if (op.equals("/") && b == 0) {
System.out.println("Não dá para dividir por zero.");
continue;
}
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
System.out.println();
}
System.out.println("Até logo!");
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextDouble()) {
String lixo = entrada.next();
System.out.println("\"" + lixo + "\" não é um número. Tente de novo.");
System.out.print(pergunta);
}
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
O código completo
A calculadora final, com as seis etapas juntas. Ela tem 57 linhas, quatro métodos e nenhum jeito fácil de quebrar.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
while (true) {
System.out.print("Operação (+, -, *, / ou sair): ");
String op = entrada.next();
if (op.equals("sair")) {
break;
}
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
continue;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
if (op.equals("/") && b == 0) {
System.out.println("Não dá para dividir por zero.");
continue;
}
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
System.out.println();
}
System.out.println("Até logo!");
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextDouble()) {
String lixo = entrada.next();
System.out.println("\"" + lixo + "\" não é um número. Tente de novo.");
System.out.print(pergunta);
}
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
Desafios extras
- Resto da divisão. Acrescente a operação
%(resto; veja Operadores Aritméticos). Lembre-se de mudar os dois métodos e o texto da pergunta. Resto por zero também deve ser recusado. - Potência. Acrescente
^usandoMath.pow(a, b)(Math). - Resultado bonito. Mostre o resultado com duas casas decimais usando
System.out.printf("%.2f%n", resultado). Em pt_BR, ele usa vírgula:3,50(veja Formatar Texto). - Sair sem exceção. Troque
while (true)porwhile (entrada.hasNext())para que Ctrl+D encerre o programa sem erro. - Memória. Guarde o último resultado numa variável e deixe a pessoa digitar
mno lugar de um número para usá-lo.
Desafio 1 no editor: acrescente a operação %. Com a entrada %, 10, 3, a calculadora deve mostrar 10.0 % 3.0 = 1.0.
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
while (true) {
System.out.print("Operação (+, -, *, / ou sair): ");
String op = entrada.next();
if (op.equals("sair")) {
break;
}
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
continue;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
if (op.equals("/") && b == 0) {
System.out.println("Não dá para dividir por zero.");
continue;
}
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
System.out.println();
}
System.out.println("Até logo!");
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextDouble()) {
String lixo = entrada.next();
System.out.println("\"" + lixo + "\" não é um número. Tente de novo.");
System.out.print(pergunta);
}
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("=== Calculadora da Ana ===");
while (true) {
System.out.print("Operação (+, -, *, /, % ou sair): ");
String op = entrada.next();
if (op.equals("sair")) {
break;
}
if (!operacaoValida(op)) {
System.out.println("Operação desconhecida: " + op);
continue;
}
double a = lerNumero(entrada, "Primeiro número: ");
double b = lerNumero(entrada, "Segundo número: ");
if ((op.equals("/") || op.equals("%")) && b == 0) {
System.out.println("Não dá para dividir por zero.");
continue;
}
double resultado = calcular(a, op, b);
System.out.println(a + " " + op + " " + b + " = " + resultado);
System.out.println();
}
System.out.println("Até logo!");
}
static double lerNumero(Scanner entrada, String pergunta) {
System.out.print(pergunta);
while (!entrada.hasNextDouble()) {
String lixo = entrada.next();
System.out.println("\"" + lixo + "\" não é um número. Tente de novo.");
System.out.print(pergunta);
}
return entrada.nextDouble();
}
static boolean operacaoValida(String op) {
return switch (op) {
case "+", "-", "*", "/", "%" -> true;
default -> false;
};
}
static double calcular(double a, String op, double b) {
return switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> a / b;
case "%" -> a % b;
default -> throw new IllegalArgumentException("Operação desconhecida: " + op);
};
}
}
Exercícios
1. Na máquina da Ana (pt_BR), o que acontece se ela digitar 2.5 num nextDouble()?
2. No lerNumero, o que acontece se você apagar a linha String lixo = entrada.next(); e alguém digitar "abc"?
3. O que continue faz dentro do while da calculadora?
4. Quanto vale 10.0 / 0 em Java?
Complete o método para que ele só leia quando houver um número esperando:
Resumo
- Um
Scanner(System.in)lê o teclado;nextDouble()lê números (com vírgula em pt_BR) enext()lê uma palavra. - O
switchcom setas devolve um valor e precisa dedefaultquando o tipo éString. - Métodos pequenos, cada um com uma tarefa, deixam o
mainfácil de ler. hasNextDouble()confere antes de ler; onext()descarta o que não serve.- Divisão de
doublepor zero dáInfinityouNaN; deint, dáArithmeticException. Confira o divisor antes. while (true)+break+continuefazem o "menu que repete".
Próximo projeto: Jogo da Adivinhação, com números aleatórios e enums.