Module 1 • Lesson 3

Your First Rust Program

📚 7 min read 💻 Free Course 🦀 nixus.pro

Hello, Rust!

Every programming journey begins with "Hello, World!" - but in Rust, even this simple program teaches you important concepts. Let us look at what Cargo generated for you:

fn main() {
    println!("Hello, world!");
}

Three things to notice immediately:

Making It More Interesting

Let us build a slightly more interesting first program to explore Rust's syntax:

fn main() {
    // This is a single-line comment

    /* This is a
       multi-line comment */

    // Variables
    let name = "Rustacean";
    let year = 2024;
    let pi = 3.14159;

    // println! with format strings
    println!("Hello, {}!", name);
    println!("It is {}", year);
    println!("Pi is approximately {:.2}", pi);

    // Named arguments (Rust 1.58+)
    println!("Hello, {name}! Pi = {pi:.3}");
}

The {} in format strings is a placeholder. {:.2} means format with 2 decimal places. {name} directly embeds the variable name.

Format String Specifiers

fn main() {
    let n = 42;
    let f = 3.14159;

    println!("{}", n);        // Default: 42
    println!("{:?}", n);      // Debug format: 42
    println!("{:b}", n);      // Binary: 101010
    println!("{:o}", n);      // Octal: 52
    println!("{:x}", n);      // Hex lowercase: 2a
    println!("{:X}", n);      // Hex uppercase: 2A
    println!("{:08b}", n);    // Zero-padded binary: 00101010
    println!("{:>10}", n);    // Right-align in 10 chars
    println!("{:<10}", n);    // Left-align in 10 chars
    println!("{:^10}", n);    // Center in 10 chars
    println!("{:.3}", f);     // 3 decimal places: 3.142
    println!("{:10.3}", f);   // Width 10, 3 decimals:      3.142
}

Your First Real Program: A Temperature Converter

Let us build something useful - a Celsius to Fahrenheit converter:

fn celsius_to_fahrenheit(celsius: f64) -> f64 {
    celsius * 9.0 / 5.0 + 32.0
}

fn fahrenheit_to_celsius(fahrenheit: f64) -> f64 {
    (fahrenheit - 32.0) * 5.0 / 9.0
}

fn main() {
    let boiling_c = 100.0;
    let freezing_c = 0.0;
    let body_temp_f = 98.6;

    println!("Temperature Converter");
    println!("====================");
    println!("{} C = {:.1} F", boiling_c, celsius_to_fahrenheit(boiling_c));
    println!("{} C = {:.1} F", freezing_c, celsius_to_fahrenheit(freezing_c));
    println!("{} F = {:.1} C", body_temp_f, fahrenheit_to_celsius(body_temp_f));
}

Key observations:

Reading User Input

To make interactive programs, we need to read from stdin:

use std::io;

fn main() {
    println!("Enter temperature in Celsius:");

    let mut input = String::new();

    io::stdin()
        .read_line(&mut input)
        .expect("Failed to read input");

    // Parse the string to a number
    let celsius: f64 = input
        .trim()            // Remove whitespace/newline
        .parse()           // Convert string to f64
        .expect("Please enter a valid number");

    let fahrenheit = celsius * 9.0 / 5.0 + 32.0;
    println!("{} C = {:.1} F", celsius, fahrenheit);
}

This introduces several important concepts:

Compiling Directly with rustc

While Cargo is the recommended way, you can compile single files directly:

# Compile a single file
rustc main.rs

# Run the output
./main    # On Linux/macOS
main.exe  # On Windows

For anything beyond a single file, use Cargo. But knowing rustc helps you understand what Cargo is doing under the hood.

🎯 Practice Exercise

  1. Modify the temperature converter to accept Fahrenheit as input and convert to Celsius
  2. Add a third function that converts Celsius to Kelvin (K = C + 273.15)
  3. Print all three: the input in C, its F equivalent, and its Kelvin equivalent
  4. Challenge: use format! macro (same as println! but returns a String) to build the output string before printing

🎉 Key Takeaways