Skip to content
This is my space, where experience meets the will to start over. This is my space, where experience meets the will to start over.

The first step is knowing where you want to go.

  • Home
  • Coding Hub
    • Software & Project
      • Small Biz Ops – S.B.O.
        • SmallBizOps – Day 10/90
      • CRM/ERP
      • MyTracker
      • My Budget
    • Form Zero to “WoW”
      • JavaScript from Zero (Completed)
        • 2. Remove and Edit List Items
        • 3. Separate HTML and JavaScript, Use addEventListener and Conditional Logic
        • 4. Add Dynamic CSS Classes
        • 5. Save & Restore Your List with localStorage
        • 6 – Turn Your App into a Full To-Do List
      • Python from Zero (Completed)
        • 2. Lists & Loops
        • 3. Conditional Menus
        • 4. Edit & Remove Tasks (with closing: Python vs PHP and Large Data)
        • 5 – Save to File: Make Your Tasks Survive Restarts
        • 6 — Pythin from zero – Final Project Polishing: Numbering, Formatting, and Preparing for CSV
      • Rust – From Zero to “WoW” (Completed)
        • 1 – Setup and Project Structure in Rust
        • 2 – User input: validation and error handling
        • 3 – Rust from Zero to “WoW – BMI Calculation and Conditional Logic
        • 4 –Rust – Clear, Formatted Output
        • 5 – Rust – Final Thoughts: Precision as a Form of Respect
      • Go from Zero to “WoW” (Completed)
        • 1 – Why Go Is Perfect for a Personal Expense Tracker
        • 2 – Logging Expenses and Console Input
        • 3 – Go from Zero to “WoW” – Smart Filtering & Display Logic
        • 4 – Go – Saving Data to Local Files
        • 5 – Go – Final Project – Expense Tracker in Go
      • C++ from Zero to “WoW” (Completed)
        • 1 – Why C++ for file organization?
        • 2 – C++ – File Type Detection and Classification
        • 3 – C++ – Creating & Managing Subfolders
        • 4 – C++ – Safe File Movement and User Feedback
        • 5 – C++ – Order as Mental Clarity
      • Ubuntu – From Zero to “WoW” (Completed)
        • 2 – Ubuntu – The Desktop Environment and Essential Commands
        • 3 – Ubuntu – Managing Files, Folders, and Permissions
        • 4 – Ubuntu – Installing and Updating Software with APT and Snap
        • 5 – Ubuntu – Customizing the Desktop Environment
        • 6 – Ubuntu – Network and Device Configuration
        • 7 – Ubuntu – User Management & System Security — “The Cathedral of Permissions”
        • 8 – Ubuntu – The Talking Machine: Terminal & Bash Scripting
        • 9 – Ubuntu – Ubuntu as a Server or Development Environment
        • 10 – Ubuntu – Backup, Maintenance & Troubleshooting
    • Git Hub Repository
      • Small Biz Ops – S.B.O.
      • Mini ERP – PHP & MySQL
      • CleverCRM (Java, Spring Boot)
      • FraudWatch (Python, FastAPI + scikit-learn)
      • OnboardIQ – Smart Onboarding Portal (Flask + SQLite Demo)
    • ArchPilot
      • 1-Users & Roles, End-to-End (Architecture, Database, and Cross-Framework Code)
      • 2 – Client Registry (CRM) Across Frameworks
      • 3 – Project & Budget Tracker (ERP)
      • 4 – Approval Workflow Engine Multi-step routing, status tracking, escalation paths
      • 5 – Audit Trail & Versioning
    • Small Biz Ops – S.B.O.
  • Vivere in USA
  • P4Y
  • Testi poetici
    • 1 – Sospeso
    • 2 – Il bicchiere di vetro quieto
    • 3 – Quando l’amore inciampa
    • 4 – Ma chi siete davvero?
    • 5 – Above the Thread of Day
    • 6 – The Truth That Doesn’t Exist
    • 7 – All of You, I Miss
    • 8 – The Captain and the Ocean
    • 9 – Between Light and Mist
    • 10 – Il peso delle scelte
  • Contact
  • Admin
This is my space, where experience meets the will to start over.
This is my space, where experience meets the will to start over.

The first step is knowing where you want to go.

Coding – Step 11.3 – Rust from Zero to “WoW – BMI Calculation and Conditional Logic

Posted on 7 Ottobre 20257 Ottobre 2025 By Francesco

⚠️ Disclaimer: This project is for educational purposes only. BMI is a simplified indicator and should not be used as a substitute for medical evaluation.


What You’ll Learn

By the end of this lesson, you’ll be able to:

  • Use variables and input handling to gather user data.
  • Apply conditional logic (if/else and match with guards) for real-world classification problems.
  • Handle invalid inputs and runtime errors using Result and custom error types.
  • Write unit tests to verify logic correctness.
  • Structure your Rust program in a clean, maintainable way.

Step 1 – Understanding BMI

The Body Mass Index (BMI) is a simple numerical measure of body weight relative to height:

BMI = weight_kg / (height_m ^ 2)

Common categories:

  • Underweight: BMI < 18.5
  • Normal weight: 18.5 ≤ BMI < 25.0
  • Overweight: 25.0 ≤ BMI < 30.0
  • Obesity: BMI ≥ 30.0

This simple classification provides a great foundation for learning conditional branching in Rust.

Step 2 – Quick CLI Implementation

Let’s start with a short version that reads from the terminal and prints the BMI result. This helps you focus on core Rust syntax and flow control.

use std::io::{self, Write};

fn main() {
    println!("=== BMI Calculator (Quick Version) ===");

    let weight = prompt_float("Enter weight in kg (e.g., 72.4): ");
    let height = prompt_float("Enter height in meters (e.g., 1.78): ");

    if weight <= 0.0 || height <= 0.0 {
        eprintln!("Invalid values: both must be > 0.");
        std::process::exit(1);
    }

    let bmi = weight / (height * height);
    let category = classify_bmi(bmi);

    println!("\nBMI: {:.1}", bmi);
    println!("Category: {}", category);
}

fn prompt_float(msg: &str) -> f32 {
    print!("{}", msg);
    let _ = io::stdout().flush();

    let mut buf = String::new();
    io::stdin().read_line(&mut buf).expect("Failed to read input");

    let buf = buf.trim().replace(',', ".");
    buf.parse::<f32>().unwrap_or_else(|_| {
        eprintln!("Invalid input. Please use a number like 70.5");
        std::process::exit(1);
    })
}

fn classify_bmi(bmi: f32) -> &'static str {
    if bmi < 18.5 {
        "Underweight"
    } else if bmi < 25.0 {
        "Normal weight"
    } else if bmi < 30.0 {
        "Overweight"
    } else {
        "Obesity"
    }
}

Example:

=== BMI Calculator (Quick Version) ===
Enter weight in kg (e.g., 72.4): 72.4
Enter height in meters (e.g., 1.78): 1.78

BMI: 22.8
Category: Normal weight

Step 3 – Clean & Robust Implementation

Now, let’s improve the program structure by separating I/O from logic, introducing Result for safe error handling, and using enum with pattern matching.

use std::error::Error;
use std::fmt;
use std::io::{self, Write};

#[derive(Debug)]
enum BmiError {
    NonPositive(&'static str),
    Parse(String),
}

impl fmt::Display for BmiError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            BmiError::NonPositive(field) => write!(f, "{} must be > 0", field),
            BmiError::Parse(s) => write!(f, "Could not parse '{}'", s),
        }
    }
}

impl Error for BmiError {}

#[derive(Debug, Clone, Copy, PartialEq)]
enum BmiCategory { Underweight, Normal, Overweight, Obesity }

impl fmt::Display for BmiCategory {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use BmiCategory::*;
        write!(f, "{}", match self {
            Underweight => "Underweight",
            Normal => "Normal weight",
            Overweight => "Overweight",
            Obesity => "Obesity",
        })
    }
}

fn parse_float(prompt: &str, name: &'static str) -> Result<f32, BmiError> {
    print!("{}", prompt);
    let _ = io::stdout().flush();

    let mut s = String::new();
    io::stdin().read_line(&mut s).map_err(|_| BmiError::Parse("<stdin>".into()))?;

    let s = s.trim().replace(',', ".");
    let val: f32 = s.parse().map_err(|_| BmiError::Parse(s.clone()))?;
    if val <= 0.0 { return Err(BmiError::NonPositive(name)); }
    Ok(val)
}

fn bmi(weight: f32, height: f32) -> f32 {
    weight / (height * height)
}

fn category_from_bmi(bmi: f32) -> BmiCategory {
    use BmiCategory::*;
    match bmi {
        x if x < 18.5 => Underweight,
        x if x < 25.0 => Normal,
        x if x < 30.0 => Overweight,
        _ => Obesity,
    }
}

fn main() {
    println!("=== BMI Calculator (Robust Version) ===");
    if let Err(e) = run() {
        eprintln!("Error: {}", e);
        std::process::exit(1);
    }
}

fn run() -> Result<(), BmiError> {
    let weight = parse_float("Weight in kg: ", "weight")?;
    let height = parse_float("Height in meters: ", "height")?;

    let val = bmi(weight, height);
    let cat = category_from_bmi(val);

    println!("\nBMI: {:.1}", val);
    println!("Category: {}", cat);
    Ok(())
}

Step 4 – Unit Tests

Writing tests ensures your code works correctly and remains stable.

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_category() {
        assert_eq!(category_from_bmi(17.9), BmiCategory::Underweight);
        assert_eq!(category_from_bmi(18.5), BmiCategory::Normal);
        assert_eq!(category_from_bmi(24.9), BmiCategory::Normal);
        assert_eq!(category_from_bmi(25.0), BmiCategory::Overweight);
        assert_eq!(category_from_bmi(29.9), BmiCategory::Overweight);
        assert_eq!(category_from_bmi(30.0), BmiCategory::Obesity);
    }

    #[test]
    fn test_bmi_calculation() {
        let b = bmi(72.0, 1.80);
        assert!((b - 22.22).abs() < 0.01);
    }
}

Run tests:

cargo test

Step 5 – Extensions

  1. Height auto-conversion (cm → m):
fn height_to_m(v: f32) -> f32 {
    if v > 3.0 { v / 100.0 } else { v }
}
  1. Imperial units: Add a mode for pounds/inches (BMI = 703 * weight_lb / (height_in^2)).
  2. Batch mode: Read multiple weight,height lines from stdin.
  3. Colorized output using ANSI escape codes.
  4. Advice printing:
fn advice(cat: BmiCategory) -> &'static str {
    match cat {
        BmiCategory::Underweight => "Consult a nutrition professional.",
        BmiCategory::Normal => "Keep up your healthy habits!",
        BmiCategory::Overweight => "Exercise and balanced diet can help.",
        BmiCategory::Obesity => "Consider discussing options with your doctor.",
    }
}

Debug Tip

Use dbg!() for quick runtime inspection:

dbg!(weight, height, bmi);

Learning Checklist

  • Handle user input safely.
  • Apply if/else and match expressions.
  • Write and run unit tests.
  • Separate logic from I/O for cleaner design.

⚠️ Disclaimer (again): The BMI metric is used here purely as a programming exercise for learning conditional logic in Rust. It should not be interpreted as a health diagnostic tool.

Post Views: 348

Condividi:

  • Condividi su Facebook (Si apre in una nuova finestra) Facebook
  • Condividi su X (Si apre in una nuova finestra) X
Coding Rust beginner Rustbmi calculatorCLIconditional logicpattern matchingRust basics

Navigazione articoli

Previous post
Next post

Francesco

My name is Francesco Boschi, originally from Italy and currently based in the United States. For over twenty years, I’ve worked as a manager and consultant across diverse sectors — from education and cultural institutions to the food industry — developing skills in operational management, strategic consulting, and complex problem-solving. In recent years, I’ve combined this experience with a strong passion for software development, creating custom tools designed to simplify workflows and meet real business needs.

Relocating to the U.S. marks the beginning of a new chapter: a personal and professional decision driven by the desire to be close to my son and to embrace new challenges in a different environment. Today, my goal is to turn my experience into meaningful solutions, blending strategic vision with technical expertise to help people and organizations work more effectively.

I enjoy moving between different worlds, adapting tools and approaches to people and contexts. I bring leadership, flexibility, attention to detail, analytical thinking, and a strong problem-solving mindset — along with a deep curiosity to learn and grow. Above all, I believe in sharing: I’m always eager to offer my experience to support the growth of others.

Related Posts

Coding

Coding – Step 9.5 – JavaScript from Zero – Save & Restore Your List with localStorage

Posted on 17 Agosto 202517 Agosto 2025

Persist your To-Do list in the browser using localStorage. Save on each change, reload on startup, and keep the UI accessible with ARIA.

Condividi:

  • Condividi su Facebook (Si apre in una nuova finestra) Facebook
  • Condividi su X (Si apre in una nuova finestra) X
Read More
Coding

Coding – Step 13.4 – C++ – Safe File Movement and User Feedback

Posted on 12 Ottobre 202512 Ottobre 2025

Learn how to make file movement in C++ safe, reversible, and human-friendly — with dry runs, backups, duplicate handling, progress indicators, and clear feedback. Because true performance includes trust.

Condividi:

  • Condividi su Facebook (Si apre in una nuova finestra) Facebook
  • Condividi su X (Si apre in una nuova finestra) X
Read More
Coding

Coding – Step 13.1 – C++ from Zero to “WoW” – Why C++ for file organization?

Posted on 21 Settembre 202521 Settembre 2025

A console-based C++ project that scans and organizes files into subfolders by type. Built for speed, clarity, and educational value — no commercial intent.

Condividi:

  • Condividi su Facebook (Si apre in una nuova finestra) Facebook
  • Condividi su X (Si apre in una nuova finestra) X
Read More

Iscriviti alla nostra Newsletter

🤞 Let's keep in touch

We do not send spam! Read our Privacy policy for more information.

Controlla la tua casella di posta o la cartella spam per confermare la tua iscrizione

Cerca nel sito

©2026 This is my space, where experience meets the will to start over. | WordPress Theme by SuperbThemes