Start learning free

LESSON 135 OF 414 · LOOPS & CONDITIONALS

Print Even Numbers in Rust: Fixing the Buggy Code

Practice Read the full explanation

Inside the code editor we've tried to write a function that takes a vector nums as argument and prints to the console the even numbers from that vector.

So when we called print_even_numbers(vec![2, 1, 0, 4, 3]), we expected our code to print:

2
0
4

but it seems like we made some mistakes because when we run our code, it prints:

even
even

Assignment:

Your task is to fix our function such that it prints the even numbers from the array.

STEP 1 OF 1
    Ctrl + Enter to check

    RUST · LOOPS & CONDITIONALS

    Buggy Code Print Even Numbers in Rust, explained

    What the code is supposed to do

    The function print_even_numbers takes a vector nums and should print its even numbers, one per line. For vec![2, 1, 0, 4, 3] that means 2, 0 and 4. The code you start with prints the word even twice instead:

    fn print_even_numbers(nums: Vec<i32>) {
        for number in nums {
            if number % 2 == 1 {
                println!("even");
            }
        }
    }
    
    // Do not change this code:
    fn main_function() {
        print_even_numbers(vec![2, 1, 0, 4, 3]);
    }
    

    The function compiles and runs. It simply does the wrong thing, in two places.

    What goes wrong

    Bug 1: the condition tests for odd numbers

    The operator % gives the remainder of a division. Dividing by 2 leaves remainder 0 for even numbers and 1 for odd numbers: 4 % 2 is 0 and 3 % 2 is 1. The condition number % 2 == 1 is true for the odd numbers, 1 and 3, and false for 2, 0 and 4. The body runs for exactly the wrong elements.

    Bug 2: the print statement prints a fixed word

    Text between double quotes is a string literal, and it is printed exactly as written. println!("even") prints the letters e-v-e-n every time it runs, whatever number holds. That's why the output is the word even twice, once for the 1 and once for the 3, and never a number.

    The two bugs hide each other. Fixing only the condition would print the word even three times, and fixing only the print would print the odd numbers 1 and 3. Both changes are needed.

    Fixing it step by step

    1. Change the comparison from == 1 to == 0. Now the body runs when the remainder is 0, which is for even numbers.
    2. Change what is printed. To print a value, println! takes a format string with a {} placeholder, followed by the value to put there: println!("{}", number).
    3. Leave the rest alone. The loop already visits every element, and main_function is marked not to be changed.

    The fixed code in Rust

    fn print_even_numbers(nums: Vec<i32>) {
        for number in nums {
            if number % 2 == 0 {
                println!("{}", number);
            }
        }
    }
    
    fn main_function() {
        print_even_numbers(vec![2, 1, 0, 4, 3]);
    }
    

    Following the vector through the loop: 2 gives remainder 0 and is printed, 1 gives remainder 1 and is skipped, 0 gives remainder 0 and is printed, 4 is printed, and 3 is skipped. The output is 2, 0 and 4.

    Rust details

    • The format string comes first. println!(number) doesn't compile, because the first argument of println! must be a string literal. Each {} in it is replaced by the next value you pass.
    • Zero is even. 0 % 2 is 0, so 0 is printed. The expected output includes it.
    • Negative numbers. In Rust, the remainder takes the sign of the left operand, so -3 % 2 is -1, not 1. A test written as number % 2 == 1 misses negative odd numbers. Testing for evenness with == 0 works for negative numbers too, since -4 % 2 is 0.
    • Looping over a vector by value. for number in nums moves the vector into the loop, and number is an i32. This is fine here because the function does not use nums afterwards.

    Common mistakes

    • Fixing only one of the two bugs. The output remains wrong, as described above.
    • Using = 0 instead of == 0. A single = is assignment, and it is not allowed as a condition. The comparison needs two.
    • Printing the number with quotes. println!("number") prints the word number.
    • Adding a return or a second print. Each even number must produce exactly one line.

    Testing

    • vec![2, 1, 0, 4, 3] prints 2, 0 and 4.
    • vec![1, 3, 5] prints nothing.
    • vec![-4, -3, 6] prints -4 and 6.
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free