🦀 Rust

Массивы (списки) в Rust 1.75: подробное руководство

Массивы (списки) в Rust

Что такое массив и зачем он нужен?

Представь, что ты собираешь коллекцию наклеек. Вместо того чтобы записывать каждую наклейку на отдельном листочке, ты можешь взять один альбом и сложить все наклейки в него по порядку. В программировании такой «альбом» называется массивом (или списком).

Массив — это контейнер, который хранит несколько значений одного типа подряд. Например, список чисел (количество порций супа), список названий фруктов или список высот, которые покорил альпинист.

В Rust есть два основных вида массивов: массив фиксированной длины (просто массив) и вектор (динамический список). Для начинающих удобнее всего использовать вектор — он может расти и уменьшаться, как настоящий список в твоей тетради.

Основной синтаксис

Создание массива (вектора)

Чтобы создать пустой список, используй Vec::new(). Если список уже есть, используй квадратные скобки и макрос vec!:

fn main() {
    // Пустой список фруктов
    let mut fruits: Vec<String> = Vec::new();

    // Список с числами (количество порций супа)
    let portions = vec![15, 20, 18, 22, 25];

    println!("{:?}", portions); // [15, 20, 18, 22, 25]
}

Добавление элементов

Метод push добавляет элемент в конец списка. Обрати внимание на слово mut — оно означает, что список можно менять:

fn main() {
    let mut fruits = Vec::new();

    fruits.push("яблоко".to_string());
    fruits.push("банан".to_string());
    fruits.push("груша".to_string());

    println!("{:?}", fruits); // ["яблоко", "банан", "груша"]
}

Доступ к элементам по индексу

Каждый элемент в списке стоит на своем месте — это индекс. Нумерация начинается с нуля! Первый элемент — индекс 0, второй — индекс 1 и так далее.

fn main() {
    let portions = vec![15, 20, 18, 22, 25];

    // Получаем первый элемент (индекс 0)
    let first = portions[0];
    println!("Первый день: {}", first); // 15

    // Получаем третий элемент (индекс 2)
    let third = portions[2];
    println!("Третий день: {}", third); // 18
}

Изменение элемента

Чтобы изменить элемент, просто присвой новое значение по индексу:

fn main() {
    let mut materials = vec![10, 5, 8, 3]; // количество хлеба, молока, масла, яиц

    println!("Было: {:?}", materials);

    // Удваиваем количество хлеба (второй элемент, индекс 1)
    materials[1] = materials[1] * 2;

    println!("Стало: {:?}", materials); // [10, 10, 8, 3]
}

Разбор типичных задач

Задача «Фрукты» (сбор списка)

Нужно собрать список фруктов, которые привозят каждый день. Используем цикл и ввод с клавиатуры:

use std::io;

fn main() {
    let mut fruits: Vec<String> = Vec::new();

    println!("Введи фрукты, которые привезли (по одному на строке).");
    println!("Когда закончишь, напиши 'стоп'.");

    loop {
        let mut input = String::new();
        io::stdin().read_line(&mut input).expect("Ошибка чтения");
        let input = input.trim().to_string();

        if input == "стоп" {
            break;
        }

        fruits.push(input);
    }

    println!("Список всех фруктов за неделю:");
    println!("{:?}", fruits);
}

Задача «Запас материалов» (изменение элемента)

Повар заметил ошибку: во втором пункте списка записано неправильное количество хлеба. Нужно его удвоить:

fn main() {
    // Индекс 0: мука, индекс 1: хлеб, индекс 2: молоко
    let mut storage = vec![12, 5, 8];

    println!("До исправления: {:?}", storage);

    // Удваиваем значение хлеба (индекс 1)
    storage[1] = storage[1] * 2;

    println!("После исправления: {:?}", storage);
}

Задача «Юный альпинист» (поиск по условию)

Нужно найти все высоты, которые больше 1000 метров:

fn main() {
    let heights = vec![500, 1200, 800, 1500, 950, 1100];

    println!("Высоты больше 1000 метров:");

    for height in &heights {
        if *height > 1000 {
            println!("{}", height);
        }
    }
}

Частые ошибки новичков

  1. Забыть добавить mut — если ты хочешь менять список (добавлять, удалять, изменять элементы), обязательно пиши let mut. Без mut список нельзя изменить.
  2. Выход за границы массива — если в списке 5 элементов (индексы 0-4), а ты обращаешься к индексу 5, программа упадет с ошибкой. Всегда проверяй длину списка методом .len().
  3. Путать массивы и векторы — в Rust есть массивы фиксированной длины ([1, 2, 3]) и векторы (vec![1, 2, 3]). Для большинства задач используй векторы, они гибче.
  4. Забыть to_string() — строки в Rust нужно явно преобразовывать. Если ты пишешь "яблоко".to_string(), это правильно. Просто "яблоко" — это текст, а не строка.

Итоговый пример: «Робот-сортировщик»

На заводе робот сортирует детали. С конвейера поступают серийные номера. Нужно отобрать все детали с номерами, которые больше 100, и вывести их на экран.

use std::io;

fn main() {
    let mut details: Vec<i32> = Vec::new();

    println!("Введи серийные номера деталей (по одному на строке).");
    println!("Для завершения введи 0.");

    loop {
        let mut input = String::new();
        io::stdin().read_line(&mut input).expect("Ошибка чтения");
        let number: i32 = input.trim().parse().expect("Ошибка! Введи число");

        if number == 0 {
            break;
        }

        details.push(number);
    }

    println!("Все детали: {:?}", details);

    // Отбираем детали с номером больше 100
    let mut selected: Vec<i32> = Vec::new();

    for detail in &details {
        if *detail > 100 {
            selected.push(*detail);
        }
    }

    println!("Детали для следующего этапа (номер > 100): {:?}", selected);
    println!("Всего отобрано: {} деталей", selected.len());
}

Что дальше?

Массивы (списки) — это основа для хранения данных. Ты научился:

  • Создавать списки
  • Добавлять элементы
  • Читать и изменять элементы по индексу
  • Перебирать элементы в цикле
  • Отбирать нужные элементы по условию

Попробуй решить задачи из этого раздела — они помогут закрепить навыки. Помни: практика — лучший способ научиться программировать!