Desafio Rust
Calculadora com expressões e retorno implícito
Enunciado
Crie uma função calcula(a: i32, b: i32, op: char) -> Result<i32, String> que realize operações básicas (+ - * /) e retorne Ok(resultado) ou Err(mensagem) em caso de operador inválido ou divisão por zero. Use blocos como expressões e retorno implícito. No main, itere sobre uma lista de operações e imprima o resultado ou a mensagem de erro.
Requisitos
- A função deve se chamar
calculae aceitari32,i32echar. - Deve retornar
Result<i32, String>. - Deve tratar divisão por zero com
Err("Divisão por zero".to_string()). - Deve tratar operador inválido com
Err(format!("Operador inválido: {}", op)). - O
maindeve imprimir os resultados no formatoa op b = resultadooua op b = Erro: mensagem.
Código inicial
fn calcula(a: i32, b: i32, op: char) -> Result<i32, String> {
// escreva seu código aqui
}
fn main() {
let operacoes = [(10, 5, '+'), (10, 0, '/'), (7, 3, '*'), (8, 2, '%')];
for &(a, b, op) in &operacoes {
match calcula(a, b, op) {
Ok(res) => println!("{} {} {} = {}", a, op, b, res),
Err(e) => println!("{} {} {} = Erro: {}", a, op, b, e),
}
}
}
Saída esperada
10 + 5 = 15
10 / 0 = Erro: Divisão por zero
7 * 3 = 21
8 % 2 = Erro: Operador inválido: %
Ver dica
Use match op para selecionar a operação. Cada braço pode ser um bloco que retorna Ok(...) ou Err(...). Lembre-se de verificar divisão por zero antes de dividir.
Mostrar solução
fn calcula(a: i32, b: i32, op: char) -> Result<i32, String> {
match op {
'+' => Ok(a + b),
'-' => Ok(a - b),
'*' => Ok(a * b),
'/' => {
if b == 0 {
Err("Divisão por zero".to_string())
} else {
Ok(a / b)
}
}
_ => Err(format!("Operador inválido: {}", op)),
}
}
fn main() {
let operacoes = [(10, 5, '+'), (10, 0, '/'), (7, 3, '*'), (8, 2, '%')];
for &(a, b, op) in &operacoes {
match calcula(a, b, op) {
Ok(res) => println!("{} {} {} = {}", a, op, b, res),
Err(e) => println!("{} {} {} = Erro: {}", a, op, b, e),
}
}
}
Passo a passo
- A função
calcularecebe doisi32e umchar, retornandoResult<i32, String>. - Usamos
match oppara comparar o caractere com cada operador suportado. - Para
'+','-','*', retornamos diretamenteOkcom o resultado da operação. - Para
'/', verificamos seb == 0; se sim, retornamosErrcom a mensagem; senão,Ok(a / b). - O braço
_captura qualquer outro caractere e retornaErrcomformat!. - Cada braço do
matché uma expressão; o valor do braço escolhido é o retorno implícito da função. - Em
main, iteramos sobre um array de tuplas e usamosmatchnoResultpara imprimir o sucesso ou o erro.
Por que funciona
O match é uma expressão que avalia para um valor. Como todos os braços retornam Result<i32, String>, o tipo do match é esse Result, que se torna o retorno implícito da função. O uso de blocos dentro do braço '/' permite lógica condicional sem return explícito. O retorno implícito mantém o código conciso e idiomático.
Erros comuns
- Esquecer o braço
_nomatch: o compilador exige exaustividade e dá erro. - Tentar dividir por zero sem verificar: panic em tempo de execução.
- Retornar
Ok(a / b)diretamente no braço'/'sem checarb == 0: panic. - Usar
returndentro dos braços: funciona, mas não é necessário e foge do estilo.
Outra forma de resolver
Usar if/else if em vez de match:
fn calcula(a: i32, b: i32, op: char) -> Result<i32, String> {
if op == '+' { Ok(a + b) }
else if op == '-' { Ok(a - b) }
else if op == '*' { Ok(a * b) }
else if op == '/' {
if b == 0 { Err("Divisão por zero".to_string()) }
else { Ok(a / b) }
} else {
Err(format!("Operador inválido: {}", op))
}
}
match é preferível por ser mais legível e exaustivo.
Saída esperada
10 + 5 = 15
10 / 0 = Erro: Divisão por zero
7 * 3 = 21
8 % 2 = Erro: Operador inválido: %