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
- Change the comparison from
== 1to== 0. Now the body runs when the remainder is 0, which is for even numbers. - 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). - Leave the rest alone. The loop already visits every element, and
main_functionis 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 ofprintln!must be a string literal. Each{}in it is replaced by the next value you pass. - Zero is even.
0 % 2is 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 % 2is-1, not 1. A test written asnumber % 2 == 1misses negative odd numbers. Testing for evenness with== 0works for negative numbers too, since-4 % 2is 0. - Looping over a vector by value.
for number in numsmoves the vector into the loop, andnumberis ani32. This is fine here because the function does not usenumsafterwards.
Common mistakes
- Fixing only one of the two bugs. The output remains wrong, as described above.
- Using
= 0instead 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 wordnumber. - Adding a
returnor 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.
