Home Rust Tutorial: Loops in Rust Programming Language

Tutorial: Loops in Rust Programming Language

Loops are an essential part of any programming language, allowing repetitive execution of code until a condition is met.

Rust offers powerful and flexible loop constructs, including loop, while, and for.

Each type of loop is designed for specific scenarios, ensuring both performance and safety.

What You’ll Learn

  1. Types of Loops in Rust
  2. The loop Keyword
  3. The while Loop
  4. The for Loop
  5. Breaking and Continuing Loops
  6. Nested Loops
  7. Using Loops with Collections
  8. Practical Examples

1. Types of Loops in Rust

Rust provides three main looping constructs:

  1. loop: Infinite loop with manual exit.
  2. while: Conditional loop that runs while a condition is true.
  3. for: Iterates over a collection or range.

2. The loop Keyword

The loop keyword creates an infinite loop, which runs indefinitely until explicitly exited using break.

Example: Basic Infinite Loop

fn main() {
    let mut counter = 0;

    loop {
        println!("Counter: {}", counter);
        counter += 1;

        if counter == 5 {
            break; // Exit the loop when counter reaches 5
        }
    }
}

Example: Returning a Value from a Loop

You can return a value from a loop using break.

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2; // Return double the counter when it reaches 10
        }
    };

    println!("Result: {}", result);
}

3. The while Loop

The while loop runs as long as a specified condition evaluates to true.

Example: Basic while Loop

fn main() {
    let mut n = 1;

    while n <= 5 {
        println!("Number: {}", n);
        n += 1;
    }
}

Example: Using while with a Condition

fn main() {
    let mut sum = 0;

    while sum < 20 {
        println!("Sum: {}", sum);
        sum += 3;
    }
}

4. The for Loop

The for loop is commonly used for iterating over ranges, collections, or iterators.

Example: Iterating Over a Range

fn main() {
    for i in 1..5 { // Exclusive range: 1, 2, 3, 4
        println!("i: {}", i);
    }

    for i in 1..=5 { // Inclusive range: 1, 2, 3, 4, 5
        println!("i: {}", i);
    }
}

Example: Iterating Over a Collection

fn main() {
    let names = ["Alice", "Bob", "Charlie"];

    for name in names.iter() {
        println!("Name: {}", name);
    }
}

5. Breaking and Continuing Loops

You can control the flow of loops using break and continue.

Example: Breaking a Loop

fn main() {
    for i in 1..10 {
        if i == 5 {
            break; // Exit the loop when i is 5
        }
        println!("i: {}", i);
    }
}

Example: Continuing to the Next Iteration

fn main() {
    for i in 1..10 {
        if i % 2 == 0 {
            continue; // Skip even numbers
        }
        println!("Odd number: {}", i);
    }
}

6. Nested Loops

Rust supports loops inside loops, often used for iterating over multidimensional data.

Example: Nested for Loops

fn main() {
    for i in 1..=3 {
        for j in 1..=3 {
            println!("i: {}, j: {}", i, j);
        }
    }
}

Example: Breaking Out of Nested Loops

Use labeled loops to exit a specific loop.

fn main() {
    'outer: for i in 1..=3 {
        for j in 1..=3 {
            if i == 2 && j == 2 {
                break 'outer; // Exit the outer loop
            }
            println!("i: {}, j: {}", i, j);
        }
    }
}

7. Using Loops with Collections

Rust loops are powerful for working with collections.

Example: Iterating Over a Vector

fn main() {
    let numbers = vec![10, 20, 30, 40];

    for num in numbers.iter() {
        println!("Number: {}", num);
    }
}

Example: Enumerating Indices and Values

fn main() {
    let fruits = vec!["Apple", "Banana", "Cherry"];

    for (index, fruit) in fruits.iter().enumerate() {
        println!("Index: {}, Fruit: {}", index, fruit);
    }
}

8. Practical Examples

8.1 Finding the Sum of a Range

fn main() {
    let sum: i32 = (1..=10).sum();
    println!("Sum: {}", sum);
}

8.2 Printing Multiplication Table

fn main() {
    for i in 1..=5 {
        for j in 1..=5 {
            print!("{:4}", i * j);
        }
        println!();
    }
}

8.3 Reversing a String

fn main() {
    let s = "Rust";
    let reversed: String = s.chars().rev().collect();

    println!("Reversed: {}", reversed);
}

8.4 Finding Prime Numbers

fn is_prime(num: u32) -> bool {
    if num < 2 {
        return false;
    }
    for i in 2..=(num as f64).sqrt() as u32 {
        if num % i == 0 {
            return false;
        }
    }
    true
}

fn main() {
    for n in 2..50 {
        if is_prime(n) {
            println!("Prime: {}", n);
        }
    }
}

8.5 Looping Until User Input Matches

use std::io;

fn main() {
    let secret = "rustacean";

    loop {
        println!("Guess the word:");
        let mut guess = String::new();

        io::stdin().read_line(&mut guess).unwrap();
        let guess = guess.trim();

        if guess == secret {
            println!("Correct!");
            break;
        } else {
            println!("Try again.");
        }
    }
}

9. Summary

Key Features

  • loop: Infinite loop, exit with break.
  • while: Conditional loop.
  • for: Iterates over ranges, collections, or iterators.
  • Control flow can be managed with break and continue.

Use Cases

  • Infinite loops for event-driven programs.
  • Conditional loops for dynamic termination.
  • Iterating over collections like arrays, vectors, or ranges.

You may also like