Desafio Rust
Processador de formas com if let e match
Enunciado
Crie um enum Forma com as variantes Circulo(f64), Retangulo { largura: f64, altura: f64 } e Triangulo { base: f64, altura: f64 }. Implemente area(&self) -> f64 usando match. No main, crie um vetor de formas, calcule a área total e, usando if let, verifique se alguma forma é um círculo e imprima seu raio. Exiba a área total formatada com duas casas decimais.
Requisitos
- O enum
Formadeve ter as três variantes com os dados especificados. - A função
areadeve usarmatchexaustivo e retornarf64. - O
maindeve criar um vetor com pelo menos um círculo, um retângulo e um triângulo. - Calcular e imprimir a área total com duas casas decimais.
- Usar
if letpara encontrar e imprimir o raio do primeiro círculo do vetor.
Código inicial
enum Forma {
Circulo(f64),
Retangulo { largura: f64, altura: f64 },
Triangulo { base: f64, altura: f64 },
}
impl Forma {
fn area(&self) -> f64 {
// Complete com match
todo!()
}
}
fn main() {
let formas = vec![
Forma::Circulo(1.0),
Forma::Retangulo { largura: 2.0, altura: 3.0 },
Forma::Triangulo { base: 4.0, altura: 5.0 },
];
// Calcule a área total
// Use if let para achar um círculo e imprimir seu raio
}
Saída esperada
Área total: 19.14
Raio do círculo: 1
Ver dica
Para a área do círculo, use std::f64::consts::PI. Para o if let, itere sobre &formas e use if let Forma::Circulo(raio) = forma. Lembre-se de que raio será uma referência (&f64), então use *raio para obter o valor.
Mostrar solução
enum Forma {
Circulo(f64),
Retangulo { largura: f64, altura: f64 },
Triangulo { base: f64, altura: f64 },
}
impl Forma {
fn area(&self) -> f64 {
match self {
Forma::Circulo(raio) => std::f64::consts::PI * raio * raio,
Forma::Retangulo { largura, altura } => largura * altura,
Forma::Triangulo { base, altura } => (base * altura) / 2.0,
}
}
}
fn main() {
let formas = vec![
Forma::Circulo(1.0),
Forma::Retangulo { largura: 2.0, altura: 3.0 },
Forma::Triangulo { base: 4.0, altura: 5.0 },
];
// Calcula a área total
let total: f64 = formas.iter().map(|f| f.area()).sum();
println!("Área total: {:.2}", total);
// Usa if let para achar o primeiro círculo e imprimir seu raio
for forma in &formas {
if let Forma::Circulo(raio) = forma {
println!("Raio do círculo: {}", raio);
break;
}
}
}
Passo a passo
- Definimos o enum
Formacom três variantes, cada uma com os dados necessários. - Implementamos o método
areausandomatch selfpara calcular a área de cada forma. - No braço
Circulo, usamosstd::f64::consts::PIe o raio extraído. - No braço
Retangulo, desestruturamoslarguraealturae multiplicamos. - No braço
Triangulo, desestruturamosbaseealturae aplicamos a fórmula(base * altura) / 2.0. - No
main, criamos um vetor de formas. - Calculamos a área total com
iter().map(|f| f.area()).sum(). - Imprimimos a área total com duas casas decimais.
- Iteramos sobre as formas e usamos
if let Forma::Circulo(raio) = formapara encontrar o primeiro círculo, imprimimos seu raio e saímos do loop combreak.
Por que funciona
O match dentro de area cobre todas as variantes, retornando o cálculo correto para cada uma. O método recebe &self, então os padrões desestruturam referências automaticamente. O if let permite verificar apenas a variante Circulo sem precisar de um match completo, e o break garante que apenas o primeiro círculo seja impresso.
Erros comuns
- Esquecer de tratar uma variante no
match: erro de compilação por não exaustividade. - Tentar usar
raiocomof64diretamente noif let: comoformaé&Forma,raioé&f64; é preciso desreferenciar com*raiose for usar em cálculos, mas na impressãoprintln!aceita referência. - Não importar
std::f64::consts::PI: erro de nome não encontrado. Use o caminho completo ouuse std::f64::consts::PI;. - Esquecer o
breaknoif let: imprimiria todos os círculos, não apenas o primeiro.
Outra forma de resolver
Usar formas.iter().find_map(|f| if let Forma::Circulo(r) = f { Some(*r) } else { None }) para obter o raio do primeiro círculo de forma mais funcional. Preferível quando se quer evitar loops explícitos.
Saída esperada
Área total: 19.14
Raio do círculo: 1