Chuyển tới nội dung chính

🌡️ Chuyển Đổi Nhiệt Độ

🎯 Mục Tiêu Dự Án

Xây dựng ứng dụng chuyển đổi nhiệt độ giữa ba đơn vị:

  • 🌡️ Celsius (°C) - Thông dụng ở châu Âu, Việt Nam
  • 🌡️ Fahrenheit (°F) - Dùng ở Mỹ
  • 🌡️ Kelvin (K) - Đơn vị khoa học

Bạn Sẽ Học Được

  • ✅ Tạo functions với nhiều tham số
  • ✅ Sử dụng enums cho các lựa chọn
  • ✅ Xây dựng menu tương tác
  • ✅ Format số với độ chính xác
  • ✅ Validate input người dùng

📐 Công Thức Chuyển Đổi

Celsius ↔ Fahrenheit

°F = (°C × 9/5) + 32
°C = (°F - 32) × 5/9

Celsius ↔ Kelvin

K = °C + 273.15
°C = K - 273.15

Fahrenheit ↔ Kelvin

K = (°F - 32) × 5/9 + 273.15
°F = (K - 273.15) × 9/5 + 32

📦 Bước 1: Tạo Project

cargo new temperature_converter
cd temperature_converter

🎮 Bước 2: Version 1 - Basic Converter

use std::io;

fn main() {
println!("🌡️ Chuyển Đổi Nhiệt Độ");
println!("======================");

loop {
println!("\n📋 Menu:");
println!(" 1. Celsius → Fahrenheit");
println!(" 2. Fahrenheit → Celsius");
println!(" 3. Celsius → Kelvin");
println!(" 4. Kelvin → Celsius");
println!(" 5. Thoát");

print!("\n📝 Chọn (1-5): ");

let choice = get_input();

match choice.trim() {
"1" => convert_celsius_to_fahrenheit(),
"2" => convert_fahrenheit_to_celsius(),
"3" => convert_celsius_to_kelvin(),
"4" => convert_kelvin_to_celsius(),
"5" => {
println!("👋 Tạm biệt!");
break;
},
_ => println!("⚠️ Lựa chọn không hợp lệ!"),
}
}
}

fn get_input() -> String {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("❌ Không đọc được input!");
input
}

fn get_temperature() -> f64 {
loop {
print!("📝 Nhập nhiệt độ: ");
let input = get_input();

match input.trim().parse::<f64>() {
Ok(temp) => return temp,
Err(_) => println!("⚠️ Vui lòng nhập số hợp lệ!"),
}
}
}

fn convert_celsius_to_fahrenheit() {
let celsius = get_temperature();
let fahrenheit = (celsius * 9.0 / 5.0) + 32.0;
println!("✅ {}°C = {:.2}°F", celsius, fahrenheit);
}

fn convert_fahrenheit_to_celsius() {
let fahrenheit = get_temperature();
let celsius = (fahrenheit - 32.0) * 5.0 / 9.0;
println!("✅ {}°F = {:.2}°C", fahrenheit, celsius);
}

fn convert_celsius_to_kelvin() {
let celsius = get_temperature();
let kelvin = celsius + 273.15;
println!("✅ {}°C = {:.2}K", celsius, kelvin);
}

fn convert_kelvin_to_celsius() {
let kelvin = get_temperature();

if kelvin < 0.0 {
println!("⚠️ Kelvin không thể âm!");
return;
}

let celsius = kelvin - 273.15;
println!("✅ {}K = {:.2}°C", kelvin, celsius);
}

🚀 Chạy Thử

cargo run

Output mẫu:

🌡️  Chuyển Đổi Nhiệt Độ
======================

📋 Menu:
1. Celsius → Fahrenheit
2. Fahrenheit → Celsius
3. Celsius → Kelvin
4. Kelvin → Celsius
5. Thoát

📝 Chọn (1-5): 1

📝 Nhập nhiệt độ: 25
✅ 25°C = 77.00°F

🎨 Bước 3: Version 2 - Với Enum

Sử dụng enum để code rõ ràng hơn:

use std::io;

#[derive(Debug, Clone, Copy)]
enum TemperatureUnit {
Celsius,
Fahrenheit,
Kelvin,
}

impl TemperatureUnit {
fn symbol(&self) -> &str {
match self {
TemperatureUnit::Celsius => "°C",
TemperatureUnit::Fahrenheit => "°F",
TemperatureUnit::Kelvin => "K",
}
}

fn name(&self) -> &str {
match self {
TemperatureUnit::Celsius => "Celsius",
TemperatureUnit::Fahrenheit => "Fahrenheit",
TemperatureUnit::Kelvin => "Kelvin",
}
}
}

struct Temperature {
value: f64,
unit: TemperatureUnit,
}

impl Temperature {
fn new(value: f64, unit: TemperatureUnit) -> Result<Self, String> {
// Kiểm tra Kelvin không âm
if matches!(unit, TemperatureUnit::Kelvin) && value < 0.0 {
return Err("Kelvin không thể âm!".to_string());
}

// Kiểm tra absolute zero
let absolute_zero_celsius = -273.15;
let temp_celsius = match unit {
TemperatureUnit::Celsius => value,
TemperatureUnit::Fahrenheit => (value - 32.0) * 5.0 / 9.0,
TemperatureUnit::Kelvin => value - 273.15,
};

if temp_celsius < absolute_zero_celsius {
return Err("Nhiệt độ không thể thấp hơn absolute zero (-273.15°C)!".to_string());
}

Ok(Temperature { value, unit })
}

fn convert_to(&self, target_unit: TemperatureUnit) -> Temperature {
if matches!(self.unit, target_unit) {
return Temperature {
value: self.value,
unit: self.unit,
};
}

// Chuyển về Celsius trước
let celsius = match self.unit {
TemperatureUnit::Celsius => self.value,
TemperatureUnit::Fahrenheit => (self.value - 32.0) * 5.0 / 9.0,
TemperatureUnit::Kelvin => self.value - 273.15,
};

// Chuyển từ Celsius sang đơn vị đích
let value = match target_unit {
TemperatureUnit::Celsius => celsius,
TemperatureUnit::Fahrenheit => (celsius * 9.0 / 5.0) + 32.0,
TemperatureUnit::Kelvin => celsius + 273.15,
};

Temperature {
value,
unit: target_unit,
}
}

fn display(&self) -> String {
format!("{:.2}{}", self.value, self.unit.symbol())
}
}

fn main() {
println!("🌡️ Chuyển Đổi Nhiệt Độ - Version 2");
println!("===================================");

loop {
println!("\n📋 Chọn đơn vị nguồn:");
println!(" 1. Celsius (°C)");
println!(" 2. Fahrenheit (°F)");
println!(" 3. Kelvin (K)");
println!(" 4. Thoát");

let choice = get_input("📝 Chọn (1-4): ");

let from_unit = match choice.trim() {
"1" => TemperatureUnit::Celsius,
"2" => TemperatureUnit::Fahrenheit,
"3" => TemperatureUnit::Kelvin,
"4" => {
println!("👋 Tạm biệt!");
break;
},
_ => {
println!("⚠️ Lựa chọn không hợp lệ!");
continue;
}
};

let value = match get_number(&format!("📝 Nhập nhiệt độ ({}): ", from_unit.symbol())) {
Some(v) => v,
None => continue,
};

let temp = match Temperature::new(value, from_unit) {
Ok(t) => t,
Err(e) => {
println!("⚠️ {}", e);
continue;
}
};

println!("\n🔄 Kết quả chuyển đổi:");

// Hiển thị tất cả đơn vị
for unit in [TemperatureUnit::Celsius, TemperatureUnit::Fahrenheit, TemperatureUnit::Kelvin] {
let converted = temp.convert_to(unit);
println!(" {} → {}", from_unit.name(), converted.display());
}
}
}

fn get_input(prompt: &str) -> String {
use std::io::Write;
print!("{}", prompt);
std::io::stdout().flush().unwrap();

let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("❌ Không đọc được input!");
input
}

fn get_number(prompt: &str) -> Option<f64> {
let input = get_input(prompt);
match input.trim().parse::<f64>() {
Ok(n) => Some(n),
Err(_) => {
println!("⚠️ Vui lòng nhập số hợp lệ!");
None
}
}
}

🎨 Bước 4: Version 3 - Table Display

Hiển thị bảng chuyển đổi đẹp mắt:

use std::io;

#[derive(Debug, Clone, Copy, PartialEq)]
enum TemperatureUnit {
Celsius,
Fahrenheit,
Kelvin,
}

impl TemperatureUnit {
fn symbol(&self) -> &str {
match self {
TemperatureUnit::Celsius => "°C",
TemperatureUnit::Fahrenheit => "°F",
TemperatureUnit::Kelvin => "K",
}
}
}

struct Temperature {
value: f64,
unit: TemperatureUnit,
}

impl Temperature {
fn new(value: f64, unit: TemperatureUnit) -> Result<Self, String> {
let absolute_zero_celsius = -273.15;
let temp_celsius = match unit {
TemperatureUnit::Celsius => value,
TemperatureUnit::Fahrenheit => (value - 32.0) * 5.0 / 9.0,
TemperatureUnit::Kelvin => value - 273.15,
};

if temp_celsius < absolute_zero_celsius - 0.01 {
return Err("Nhiệt độ thấp hơn absolute zero!".to_string());
}

Ok(Temperature { value, unit })
}

fn to_celsius(&self) -> f64 {
match self.unit {
TemperatureUnit::Celsius => self.value,
TemperatureUnit::Fahrenheit => (self.value - 32.0) * 5.0 / 9.0,
TemperatureUnit::Kelvin => self.value - 273.15,
}
}

fn convert_to(&self, target_unit: TemperatureUnit) -> f64 {
let celsius = self.to_celsius();
match target_unit {
TemperatureUnit::Celsius => celsius,
TemperatureUnit::Fahrenheit => (celsius * 9.0 / 5.0) + 32.0,
TemperatureUnit::Kelvin => celsius + 273.15,
}
}
}

fn main() {
println!("🌡️ Chuyển Đổi Nhiệt Độ - Ultimate Edition");
println!("==========================================");

loop {
println!("\n📋 Menu:");
println!(" 1. Chuyển đổi đơn lẻ");
println!(" 2. Hiển thị bảng chuyển đổi");
println!(" 3. So sánh nhiệt độ");
println!(" 4. Thoát");

let choice = get_input("📝 Chọn: ");

match choice.trim() {
"1" => convert_single(),
"2" => show_conversion_table(),
"3" => compare_temperatures(),
"4" => {
println!("👋 Tạm biệt!");
break;
},
_ => println!("⚠️ Lựa chọn không hợp lệ!"),
}
}
}

fn convert_single() {
let (value, from_unit) = match get_temperature_input() {
Some(t) => t,
None => return,
};

let temp = match Temperature::new(value, from_unit) {
Ok(t) => t,
Err(e) => {
println!("⚠️ {}", e);
return;
}
};

println!("\n╔════════════════════════╗");
println!("║ Kết Quả Chuyển Đổi ║");
println!("╠════════════════════════╣");
println!("║ Celsius │ {:>8.2}°C ║", temp.convert_to(TemperatureUnit::Celsius));
println!("║ Fahrenheit │ {:>8.2}°F ║", temp.convert_to(TemperatureUnit::Fahrenheit));
println!("║ Kelvin │ {:>9.2}K ║", temp.convert_to(TemperatureUnit::Kelvin));
println!("╚════════════════════════╝");
}

fn show_conversion_table() {
println!("\n🌡️ Bảng Chuyển Đổi Nhiệt Độ Thông Dụng");
println!("═══════════════════════════════════════");

let reference_temps = vec![
("Absolute Zero", -273.15),
("Nước đóng băng", 0.0),
("Nhiệt độ phòng", 20.0),
("Nhiệt độ cơ thể", 37.0),
("Nước sôi", 100.0),
];

println!("\n┌────────────────────┬─────────┬─────────┬─────────┐");
println!("│ Sự kiện │ °C │ °F │ K │");
println!("├────────────────────┼─────────┼─────────┼─────────┤");

for (name, celsius) in reference_temps {
let temp = Temperature::new(celsius, TemperatureUnit::Celsius).unwrap();
println!(
"│ {:18} │ {:>7.2} │ {:>7.2} │ {:>7.2} │",
name,
celsius,
temp.convert_to(TemperatureUnit::Fahrenheit),
temp.convert_to(TemperatureUnit::Kelvin)
);
}

println!("└────────────────────┴─────────┴─────────┴─────────┘");
}

fn compare_temperatures() {
println!("\n🔍 So Sánh Hai Nhiệt Độ");

println!("\n--- Nhiệt độ thứ nhất ---");
let (value1, unit1) = match get_temperature_input() {
Some(t) => t,
None => return,
};

println!("\n--- Nhiệt độ thứ hai ---");
let (value2, unit2) = match get_temperature_input() {
Some(t) => t,
None => return,
};

let temp1 = match Temperature::new(value1, unit1) {
Ok(t) => t,
Err(e) => {
println!("⚠️ Nhiệt độ 1: {}", e);
return;
}
};

let temp2 = match Temperature::new(value2, unit2) {
Ok(t) => t,
Err(e) => {
println!("⚠️ Nhiệt độ 2: {}", e);
return;
}
};

let celsius1 = temp1.to_celsius();
let celsius2 = temp2.to_celsius();

println!("\n📊 Kết quả so sánh:");
println!(" Nhiệt độ 1: {:.2}°C", celsius1);
println!(" Nhiệt độ 2: {:.2}°C", celsius2);

if (celsius1 - celsius2).abs() < 0.01 {
println!(" ➡️ Hai nhiệt độ bằng nhau!");
} else if celsius1 > celsius2 {
println!(" ➡️ Nhiệt độ 1 cao hơn {:.2}°C", celsius1 - celsius2);
} else {
println!(" ➡️ Nhiệt độ 2 cao hơn {:.2}°C", celsius2 - celsius1);
}
}

fn get_temperature_input() -> Option<(f64, TemperatureUnit)> {
println!("\nChọn đơn vị: 1=Celsius, 2=Fahrenheit, 3=Kelvin");
let unit_choice = get_input("📝 Đơn vị: ");

let unit = match unit_choice.trim() {
"1" => TemperatureUnit::Celsius,
"2" => TemperatureUnit::Fahrenheit,
"3" => TemperatureUnit::Kelvin,
_ => {
println!("⚠️ Lựa chọn không hợp lệ!");
return None;
}
};

let value = match get_number("📝 Giá trị: ") {
Some(v) => v,
None => return None,
};

Some((value, unit))
}

fn get_input(prompt: &str) -> String {
use std::io::Write;
print!("{}", prompt);
std::io::stdout().flush().unwrap();

let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("❌ Không đọc được input!");
input
}

fn get_number(prompt: &str) -> Option<f64> {
let input = get_input(prompt);
match input.trim().parse::<f64>() {
Ok(n) => Some(n),
Err(_) => {
println!("⚠️ Vui lòng nhập số hợp lệ!");
None
}
}
}

💡 Thông Tin Thú Vị

Absolute Zero

  • -273.15°C = -459.67°F = 0K
  • Nhiệt độ thấp nhất có thể có trong vũ trụ!

Nhiệt Độ Cơ Thể

  • Người: 37°C (98.6°F)
  • Chim: 40-42°C
  • Chó, mèo: 38-39°C

Kỷ Lục Thế Giới

  • Nóng nhất: 56.7°C (Death Valley, USA, 1913)
  • Lạnh nhất: -89.2°C (Nam Cực, 1983)

🐛 Lỗi Thường Gặp

Lỗi 1: Kelvin Âm

// ❌ SAI: Không kiểm tra
if matches!(unit, TemperatureUnit::Kelvin) && value < 0.0 {
return Err("Kelvin không thể âm!");
}

Lỗi 2: Công Thức Sai

// ❌ SAI
celsius * 9 / 5 + 32 // Integer division!

// ✅ ĐÚNG
celsius * 9.0 / 5.0 + 32.0

💪 Thử Thách

Thử Thách 1: Thêm Rankine

Thêm đơn vị Rankine (°R) - dùng trong kỹ thuật

Thử Thách 2: Lưu Lịch Sử

Lưu các phép chuyển đổi đã thực hiện

Thử Thách 3: GUI

Tạo giao diện đồ họa với crate iced hoặc egui

📚 Kiến Thức Đã Học

Enums: Định nghĩa types với variants ✅ Impl Blocks: Methods cho struct và enum ✅ Result: Error handling với custom messages ✅ Pattern Matching: matches! macro ✅ Formatting: Format số với độ chính xác ✅ Validation: Kiểm tra input hợp lệ

🎯 Bước Tiếp Theo

➡️ FizzBuzz Challenge - Thử thách kinh điển!


🎉 Tuyệt vời! Bạn đã master temperature conversion! 🌡️

Loading comments...