Step 4 of 7
while loops
A while loop checks its condition before each iteration and stops as soon as the condition is false. It's the tidy way to write "keep going while this is true", instead of loop with an if and break inside:
fn main() {
let mut n = 1234;
let mut digits = 0;
while n > 0 {
n /= 10;
digits += 1;
}
println!("{digits} digits");
}
4 digits
Trace it: n goes 1234, 123, 12, 1, 0 while digits counts 1, 2, 3, 4. Then n > 0 is false and the loop ends. If the condition is false from the start, the body never runs at all: for n = 0 this program would print 0 digits (keep that in mind for the exercise).
Mutable parameters
Loops often change their inputs. A parameter is a variable like any other, so it's immutable unless you mark it mut:
fn digit_sum(mut n: u32) -> u32 {
let mut sum = 0;
while n > 0 {
sum += n % 10;
n /= 10;
}
sum
}
fn main() {
let number = 1234;
println!("{}", digit_sum(number));
println!("{number}");
}
10
1234
mut n: u32 only affects the function's own copy: number in main is unchanged. Shadowing does the same job: keep the parameter immutable and write let mut n = n; as the first line of the body.
while or loop?
while condition { ... }when you can say up front what keeps the loop going.loop { ... }withbreakwhen the exit is decided in the middle of the body, or when you needbreak value.
Common mistakes
- Off-by-one:
while i < 10andwhile i <= 10differ by one iteration. Check the last iteration by hand. - Forgetting the update:
while n > 0 { sum += n % 10; }never changesn, so it never ends. - A non-bool condition:
while n { ... }iserror[E0308]: mismatched types, just likeif.
Your task
Write fn count_digits(n: u32) -> u32 that returns how many digits n has, using a while loop. Careful: 0 has one digit.
Challenge 2
Write fn reverse_digits(n: u32) -> u32 that returns the number with its digits in reverse order: 1234 becomes 4321, and 120 becomes 21 (leading zeros disappear). Use a while loop: take the last digit with % 10, and append it to the result with result * 10 + digit.
Challenge 3
The Collatz rule: if n is even, halve it; if it's odd, triple it and add 1. Starting from any positive number, you always seem to end up at 1 (nobody has proved it). Write fn collatz_steps(n: u64) -> u32 that returns how many steps it takes to reach 1 (for 1 itself, that's 0). Use a while loop.