Bỏ qua để đến nội dung

Mảng trong Rust

Mảng (array) là một danh sách các giá trị có kích thước cố định, tất cả cùng một kiểu. “Kích thước cố định” là từ khóa quan trọng — một khi đã tạo mảng, nó không thể dài ra hay ngắn lại. Nếu bạn cần thứ gì đó đổi được kích thước, đó là việc của vector.

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

Kiểu [i32; 5] được đọc là “một mảng gồm 5 giá trị i32.” Độ dài đó là một phần của kiểu — [i32; 5] và [i32; 3] được coi là hai kiểu khác nhau.

▶ Tự chạy thử

Bạn cũng có thể để Rust tự suy ra kiểu và chỉ viết các giá trị:

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

Để lấp đầy mảng bằng cùng một giá trị N lần, hãy dùng cách viết tắt này:

fn main() {
let zeros = [0; 5]; // [0, 0, 0, 0, 0]
println!("{:?}", zeros);
}
▶ Tự chạy thử

Mảng được đánh chỉ số từ 0, dùng dấu ngoặc vuông:

fn main() {
let fruits = ["táo", "chuối", "anh đào"];
println!("{}", fruits[0]); // táo
println!("{}", fruits[2]); // anh đào
println!("Độ dài: {}", fruits.len());
}
▶ Tự chạy thử

Nếu bạn truy cập một chỉ số không tồn tại, Rust sẽ dừng chương trình thay vì âm thầm đọc vùng nhớ rác:

fn get_fruit(fruits: [&str; 3], index: usize) -> &str {
fruits[index]
}
fn main() {
let fruits = ["táo", "chuối", "anh đào"];
println!("{}", get_fruit(fruits, 10)); // panic lúc chạy
}
thread 'main' (12345) panicked at src/main.rs:2:5:
index out of bounds: the len is 3 but the index is 10

Thông báo panic này (Rust luôn in bằng tiếng Anh) nói rằng chỉ số nằm ngoài giới hạn: độ dài là 3 nhưng chỉ số là 10.

fn main() {
let numbers = [10, 20, 30];
for n in numbers {
println!("{n}");
}
}
▶ Tự chạy thử

Một mảng có thể chứa các mảng khác. Nhờ đó bạn có một lưới gồm hàng và cột, như bàn cờ hay một bảng tính nhỏ. Kiểu của grid dưới đây là [[i32; 3]; 2], đọc là “2 hàng, mỗi hàng là một mảng gồm 3 giá trị i32.”

fn main() {
// 2 hàng, 3 cột
let grid = [
[1, 2, 3],
[4, 5, 6],
];
println!("Hàng 1, cột 2: {}", grid[1][2]);
let mut total = 0;
for row in grid {
println!("{:?}", row);
for value in row {
total += value;
}
}
println!("Tổng: {total}");
}

Kết quả:

Hàng 1, cột 2: 6
[1, 2, 3]
[4, 5, 6]
Tổng: 21
▶ Tự chạy thử

grid[1][2] nghĩa là “hàng 1, rồi cột 2 bên trong hàng đó.” Cả hai đều đếm từ 0, nên đây là hàng thứ hai, giá trị thứ ba. Để đi qua mọi giá trị, dùng một vòng lặp cho các hàng và một vòng lặp thứ hai bên trong cho các giá trị của mỗi hàng.

Mọi hàng phải có cùng độ dài, vì độ dài hàng là một phần của kiểu. Nếu bạn cần cả vị trí khi duyệt, .iter().enumerate() cho bạn chỉ số và giá trị cùng lúc. Nó được giới thiệu trong bài vòng lặp for.

Dùng mảng khi kích thước cố định và biết trước (như bảy ngày trong tuần). Dùng Vec khi bạn cần thêm hoặc bớt phần tử — mà trong thực tế, đó là phần lớn trường hợp. Trong code Rust hằng ngày, mảng ít phổ biến hơn vector.

Tạo mảng [4, 8, 15, 16, 23, 42]. Cộng tất cả các giá trị, rồi in ra tổng và giá trị trung bình với hai chữ số thập phân. Gợi ý: duyệt bằng for, giữ một biến total cộng dồn, và đổi cả hai số sang f64 bằng as trước khi chia.

Xem lời giải
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!("Tổng: {total}");
println!("Trung bình: {average:.2}");
}

Kết quả:

Tổng: 108
Trung bình: 18.00
▶ Tự chạy thử

Nếu thiếu as f64, total / numbers.len() sẽ là phép chia nguyên, và Rust còn phàn nàn rằng total (một i32) và len() (một usize) là hai kiểu khác nhau.

Bạn có nhiệt độ của một tuần: [18, 25, 12, 31, 22, 27, 19]. Hãy tìm và in ra nhiệt độ cao nhất. Gợi ý: bắt đầu với let mut hottest = temps[0];, rồi duyệt và thay thế nó mỗi khi gặp giá trị lớn hơn.

Xem lời giải
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!("Ngày nóng nhất: {hottest}");
}

Kết quả:

Ngày nóng nhất: 31
▶ Tự chạy thử

Bắt đầu từ temps[0] thay vì 0 là quan trọng: nếu mọi nhiệt độ đều dưới 0, bắt đầu từ 0 sẽ cho đáp án sai.

  • Mảng có độ dài cố định, và độ dài là một phần của kiểu: [i32; 5].
  • Truy cập phần tử bằng array[index], bắt đầu từ 0.
  • Truy cập ngoài giới hạn sẽ panic lúc chạy thay vì gây ra hành vi không xác định.
  • Mảng có thể chứa mảng: [[i32; 3]; 2] là một lưới mà bạn đọc bằng grid[row][column].
  • Nếu cần đổi kích thước, hãy dùng Vec.

Kiểm tra nhanh

1. Điều gì đúng về độ dài của mảng trong Rust?

2. Điều gì xảy ra khi bạn truy cập một chỉ số mảng nằm ngoài giới hạn lúc chạy?

3. let zeros = [0; 5]; tạo ra gì?

Điểm: 0 / 3