What the code is supposed to do
The function printOddNumbers takes a number n and should print the odd numbers below it, one per line. Called with 8, it should print 1, 3, 5 and 7. The code you start with prints nothing at all:
fn printOddNumbers(n: i32) {
for i in 0..n {
if n % 2 == 1 {
println!("{}", n);
}
}
}
// Do not change this code:
fn mainFunction() {
printOddNumbers(8);
}
The code compiles and runs without a crash. It just never reaches the println!.
What goes wrong
The loop for i in 0..n produces a new value of i on every pass: 0, 1, 2, up to 7. But the two lines inside the loop never look at i. They use n, the parameter, which is 8 on every pass and never changes.
So the test n % 2 == 1 asks the same question eight times: is 8 odd? The remainder of 8 divided by 2 is 0, so the answer is no each time, and nothing is printed.
The bug has a second face. If the function were called with an odd number, such as 9, the test would be true on every pass, and the function would print the number 9 nine times instead of the odd numbers below 9. The loop variable is the one that carries the changing value, and the code ignores it.
The compiler hints at the problem. It warns that the variable i is unused, because nothing in the loop body reads it. A loop variable that is never used is a strong sign that the loop body is checking the wrong variable.
Fixing it step by step
- Change the test from
n % 2 == 1toi % 2 == 1, so each pass checks the current number. - Change the print from
ntoi, so the odd number found is the one that gets printed. - Keep the loop range.
0..ncovers 0 ton - 1, which matches the expected output for 8: the numbers 1, 3, 5 and 7.
The fixed code in Rust
fn printOddNumbers(n: i32) {
for i in 0..n {
if i % 2 == 1 {
println!("{}", i);
}
}
}
fn mainFunction() {
printOddNumbers(8);
}
Now the loop goes through 0 to 7. The remainder of i divided by 2 is 1 for 1, 3, 5 and 7, so those four are printed, each on its own line.
Rust details
- Naming. Rust's style is snake case,
print_odd_numbers, and the compiler warns about a name likeprintOddNumbers. It is only a warning, so the program still builds. This lesson keeps the given names because the code around them depends on them. - The range excludes the end.
0..nstops beforen. If the task asked for the odd numbers up to and includingn, the range would be0..=n. Forn = 8the result is the same, because 8 is even. - Warnings are hints. The unused variable warning points straight at the bug here, so read warnings before hunting through the code.
- Parameters are values.
nis ani32copied into the function. Nothing in the loop changes it, which is why it keeps the value 8.
Common mistakes
- Fixing only one of the two lines. If only the test uses
i, the function prints8four times. If only the print usesi, nothing is printed. - Changing the loop instead. The range is already right. Starting at 1 or stepping by 2 would change the structure for no reason.
- Negative numbers. This is not a concern here, but note that
-3 % 2is-1in Rust, so== 1would miss negative odd numbers. The range here starts at 0.
Testing
printOddNumbers(8)prints 1, 3, 5 and 7.printOddNumbers(9)prints 1, 3, 5 and 7, because 9 itself is excluded.printOddNumbers(1)andprintOddNumbers(0)print nothing.
