Перейти к содержимому

Массивы в Rust

Массив (array) — это список значений одного типа фиксированного размера. Главное здесь — «фиксированного»: после создания массив не может ни вырасти, ни уменьшиться. Если нужно что-то, что меняет размер, для этого есть вектор.

fn main() {
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
println!("{:?}", numbers);
}

Тип [i32; 5] читается как «массив из 5 значений i32». Длина — часть типа: [i32; 5] и [i32; 3] считаются разными типами.

▶ Попробуй сам

Можно и просто перечислить значения, а тип Rust выведет сам:

let numbers = [1, 2, 3, 4, 5];

Чтобы заполнить массив одним и тем же значением N раз, есть сокращённая запись:

fn main() {
let zeros = [0; 5]; // [0, 0, 0, 0, 0]
println!("{:?}", zeros);
}
▶ Попробуй сам

К элементам массива обращаются по индексу в квадратных скобках, отсчёт начинается с 0:

fn main() {
let fruits = ["яблоко", "банан", "вишня"];
println!("{}", fruits[0]); // яблоко
println!("{}", fruits[2]); // вишня
println!("Длина: {}", fruits.len());
}
▶ Попробуй сам

Если обратиться к несуществующему индексу, Rust остановит программу, а не станет молча читать мусор из памяти:

fn get_fruit(fruits: [&str; 3], index: usize) -> &str {
fruits[index]
}
fn main() {
let fruits = ["яблоко", "банан", "вишня"];
println!("{}", get_fruit(fruits, 10)); // паника во время работы
}
thread 'main' (12345) panicked at src/main.rs:2:5:
index out of bounds: the len is 3 but the index is 10

Поток main запаниковал в строке 2: индекс вышел за границы — длина 3, а индекс 10.

fn main() {
let numbers = [10, 20, 30];
for n in numbers {
println!("{n}");
}
}
▶ Попробуй сам

Массив может содержать другие массивы. Так получается сетка из строк и столбцов — как игровое поле или маленькая таблица. Тип grid ниже — [[i32; 3]; 2], то есть «2 строки, каждая — массив из 3 значений i32».

fn main() {
// 2 строки, 3 столбца
let grid = [
[1, 2, 3],
[4, 5, 6],
];
println!("Строка 1, столбец 2: {}", grid[1][2]);
let mut total = 0;
for row in grid {
println!("{:?}", row);
for value in row {
total += value;
}
}
println!("Сумма: {total}");
}

Вывод:

Строка 1, столбец 2: 6
[1, 2, 3]
[4, 5, 6]
Сумма: 21
▶ Попробуй сам

grid[1][2] значит «строка 1, а в ней столбец 2». Оба счёта начинаются с 0, так что это вторая строка, третье значение. Чтобы обойти все значения, нужен один цикл по строкам и второй, вложенный, — по значениям каждой строки.

Все строки должны быть одной длины, потому что длина строки — часть типа. Если при переборе нужна ещё и позиция, .iter().enumerate() даёт индекс и значение вместе. Это показано в уроке Цикл for.

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

Создай массив [4, 8, 15, 16, 23, 42]. Сложи все значения, а потом выведи сумму и среднее с двумя знаками после запятой. Подсказка: перебери массив через for, копи сумму в total, а перед делением преврати оба числа в f64 через as.

Показать решение
fn main() {
let numbers = [4, 8, 15, 16, 23, 42];
let mut total = 0;
for n in numbers {
total += n;
}
let average = total as f64 / numbers.len() as f64;
println!("Сумма: {total}");
println!("Среднее: {average:.2}");
}

Вывод:

Сумма: 108
Среднее: 18.00
▶ Попробуй сам

Без as f64 выражение total / numbers.len() было бы целочисленным делением, и вдобавок Rust пожаловался бы, что total (i32) и len() (usize) — разные типы.

У тебя есть температуры за неделю: [18, 25, 12, 31, 22, 27, 19]. Найди и выведи самую высокую. Подсказка: начни с let mut hottest = temps[0];, затем перебирай и заменяй значение, как только найдёшь большее.

Показать решение
fn main() {
let temps = [18, 25, 12, 31, 22, 27, 19];
let mut hottest = temps[0];
for t in temps {
if t > hottest {
hottest = t;
}
}
println!("Самый жаркий день: {hottest}");
}

Вывод:

Самый жаркий день: 31
▶ Попробуй сам

Важно начинать с temps[0], а не с 0: если бы все температуры были ниже нуля, старт с 0 дал бы неверный ответ.

  • У массива фиксированная длина, и она — часть типа: [i32; 5].
  • К элементам обращаются через массив[индекс], отсчёт с 0.
  • Выход за границы вызывает панику во время работы, а не неопределённое поведение.
  • Массивы могут содержать массивы: [[i32; 3]; 2] — это сетка, к которой обращаются как grid[строка][столбец].
  • Если размер нужно менять, используй Vec.

Проверь себя

1. Что верно о длине массива в Rust?

2. Что произойдёт при обращении к индексу за границами массива во время работы?

3. Что создаёт let zeros = [0; 5];?

Результат: 0 / 3