🎯 Construção de um Conversor de Escalas Termométricas em Rust
Em poucas palavras
Aplicar conceitos de Segurança de Tipos e Encapsulamento para criar uma ferramenta de conversão entre Celsius, Fahrenheit e Kelvin, focando em um código que previne erros em tempo de compilação.
📝 Notas e Desenvolvimento
🔗 Conexões e Contexto
- Atlas: MdC - Gestão de conhecimento pessoal
- Notas Relacionadas:
📚 Referências e Fontes
Links Externos
Citações Diretas
📂 Outros Conteúdos Preservados
🌡️ Projeto: Conversor de Temperatura em Rust
Objetivo
Aplicar conceitos de Segurança de Tipos e Encapsulamento para criar uma ferramenta de conversão entre Celsius, Fahrenheit e Kelvin, focando em um código que previne erros em tempo de compilação.
🛠️ 1. Contexto e Desafio
A conversão de temperaturas é um excelente exercício para dominar a manipulação de fórmulas e o controle de fluxo. Em Rust, elevamos este desafio utilizando estruturas que garantem que o programa nunca entre em um estado inválido.
O Desafio: Criar uma CLI (Interface de Linha de Comando) que solicite um valor e permita ao usuário escolher livremente as escalas de origem e destino.
📋 2. Requisitos do Projeto
Funcionais (O que o pRograma fAz)
- Entrada Robusta: O usuário deve digitar o valor. Se digitar letras, o programa deve avisar e solicitar novamente (sem travar).
- Menus Dinâmicos: Seleção clara para escala de Origem e escala de Destino.
- Precisão: Exibição do resultado com duas casas decimais e sua respectiva unidade.
Técnicos (Como o Rust dEve sEr uSado)
- Enums: Para representar as escalas, garantindo que não existam “opções fantasmas”.
- Blocos
impl: Para anexar a lógica de conversão e formatação diretamente ao tipo de dado. - Pattern Matching: Para resolver as fórmulas matemáticas de forma exaustiva e elegante.
- Prevenção de Panic: Substituir
.expect()ou.unwrap()por tratamentos de erro dentro de loops.
💻 3. Implementação Sugerida
Abaixo, a solução idiomática que separa a interface do usuário (IO) da lógica de negócio (Matemática).
use std::io::{self, Write};
/// Define as escalas termométricas suportadas.
/// Derivamos Copy e Clone para facilitar a passagem da escala entre funções.
#[derive(Debug, Clone, Copy, PartialEq)]
enum TemperatureScale {
Celsius,
Fahrenheit,
Kelvin,
}
impl TemperatureScale {
/// Realiza a conversão baseada na escala atual (self) e na escala de destino (target).
fn convert_to(&self, value: f64, target: TemperatureScale) -> f64 {
if *self == target { return value; }
match (self, target) {
(Self::Celsius, Self::Fahrenheit) => (value * 9.0 / 5.0) + 32.0,
(Self::Celsius, Self::Kelvin) => value + 273.15,
(Self::Fahrenheit, Self::Celsius) => (value - 32.0) * 5.0 / 9.0,
(Self::Fahrenheit, Self::Kelvin) => (value - 32.0) * 5.0 / 9.0 + 273.15,
(Self::Kelvin, Self::Celsius) => value - 273.15,
(Self::Kelvin, Self::Fahrenheit) => (value - 273.15) * 9.0 / 5.0 + 32.0,
_ => unreachable!(),
}
}
/// Retorna a representação textual da unidade.
fn unit(&self) -> &str {
match self {
Self::Celsius => "°C",
Self::Fahrenheit => "°F",
Self::Kelvin => "K",
}
}
}
fn main() {
println!("--- Conversor de Temperatura Profissional ---");
let value = get_value_from_user();
println!("\nSelecione a escala de ORIGEM:");
let from_scale = get_choice_from_user();
println!("\nSelecione a escala de DESTINO:");
let to_scale = get_choice_from_user();
let result = from_scale.convert_to(value, to_scale);
println!(
"\n✅ Resultado: {:.2}{} = {:.2}{}",
value, from_scale.unit(), result, to_scale.unit()
);
}
fn get_value_from_user() -> f64 {
loop {
print!("Digite o valor da temperatura: ");
io::stdout().flush().unwrap();
let mut input = String::new();
io::stdin().read_line(&mut input).ok();
match input.trim().parse::<f64>() {
Ok(num) => return num,
Err(_) => println!("❌ Erro: Digite um número válido (ex: 36.5)."),
}
}
}
fn get_choice_from_user() -> TemperatureScale {
loop {
print!("1. Celsius | 2. Fahrenheit | 3. Kelvin: ");
io::stdout().flush().unwrap();
let mut input = String::new();
io::stdin().read_line(&mut input).ok();
match input.trim() {
"1" => return TemperatureScale::Celsius,
"2" => return TemperatureScale::Fahrenheit,
"3" => return TemperatureScale::Kelvin,
_ => println!("⚠️ Escolha inválida."),
}
}
}🧠 4. Conceitos Aprendidos
| Conceito | Aplicação neste projeto |
|---|---|
impl Block | Centraliza as fórmulas matemáticas dentro do contexto do Enum. |
| Exhaustive Matching | O Rust garante que você não esqueceu nenhuma combinação de conversão (ex: Kelvin para Fahrenheit). |
| Zero-Cost Abstractions | O uso de Enums e métodos não deixa o programa mais lento que usar if/else manuais, mas o torna muito mais seguro. |
io::stdout().flush() | Essencial para garantir que prompts de texto apareçam antes da entrada do usuário em ambientes de terminal. |
Dica de Ouro: Observe como o método convert_to recebe target: TemperatureScale. Isso permite que você expanda o programa para 10 escalas diferentes e a lógica de chamada na main continuará sendo exatamente uma única linha!