RustArena

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?

Common mistakes

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.

Previous: loop and break Next: for loops and ranges