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:
fn main()- the entry point of every Rust program. Like C'smain()println!- that exclamation mark means this is a macro, not a regular function. We will cover macros later, butprintln!prints to standard output with a newline- Curly braces
{}delimit code blocks, no colons like Python
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:
fn celsius_to_fahrenheit(celsius: f64) -> f64- functions declare parameter types and return typef64is a 64-bit floating point number (likedoublein C)- The last expression in a function without a semicolon is the return value
- We could also write
return celsius * 9.0 / 5.0 + 32.0;but the implicit return is idiomatic Rust
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:
use std::io- importing from the standard librarylet mut- mutable variable (we will cover this next lesson)String::new()- creating a new empty String&mut input- mutable reference to input (we will cover references in Module 2).expect()- handling errors simply for now (we will do proper error handling in Module 6).trim()and.parse()- method chaining
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 WindowsFor anything beyond a single file, use Cargo. But knowing rustc helps you understand what Cargo is doing under the hood.
🎯 Practice Exercise
- Modify the temperature converter to accept Fahrenheit as input and convert to Celsius
- Add a third function that converts Celsius to Kelvin (K = C + 273.15)
- Print all three: the input in C, its F equivalent, and its Kelvin equivalent
- Challenge: use
format!macro (same as println! but returns a String) to build the output string before printing
🎉 Key Takeaways
fn main()is the entry point;println!is a macro for formatted output- Format strings use
{}placeholders with optional formatting specs like{:.2} - Functions declare parameter and return types explicitly
- The last expression without a semicolon is the implicit return value
- Reading input requires
String::new(),read_line, and.parse()to convert types