Aller au contenu

Les tableaux en Rust

Un tableau (array) est une liste de valeurs de taille fixe, toutes du même type. « Taille fixe » est le mot important : une fois le tableau créé, il ne peut ni grandir ni rétrécir. Si vous avez besoin de quelque chose qui change de taille, c’est le rôle du vecteur.

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

Le type [i32; 5] se lit « un tableau de 5 valeurs i32 ». Cette longueur fait partie du type : un [i32; 5] et un [i32; 3] sont considérés comme des types différents.

▶ Essayez par vous-même

Vous pouvez aussi laisser Rust deviner le type et écrire seulement les valeurs :

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

Pour remplir un tableau avec la même valeur N fois, utilisez ce raccourci :

fn main() {
let zeros = [0; 5]; // [0, 0, 0, 0, 0]
println!("{:?}", zeros);
}
▶ Essayez par vous-même

Les indices d’un tableau commencent à 0, et on les écrit entre crochets :

fn main() {
let fruits = ["pomme", "banane", "cerise"];
println!("{}", fruits[0]); // pomme
println!("{}", fruits[2]); // cerise
println!("Longueur : {}", fruits.len());
}
▶ Essayez par vous-même

Si vous essayez d’accéder à un indice qui n’existe pas, Rust arrête votre programme au lieu de lire en douce de la mémoire n’importe comment :

fn get_fruit(fruits: [&str; 3], index: usize) -> &str {
fruits[index]
}
fn main() {
let fruits = ["pomme", "banane", "cerise"];
println!("{}", get_fruit(fruits, 10)); // panique à l'exécution
}
thread 'main' (12345) panicked at src/main.rs:2:5:
index out of bounds: the len is 3 but the index is 10

Ce message vient de Rust lui-même, qui l’affiche toujours en anglais. Il dit que le thread main a paniqué (panic) à la ligne 2, car l’indice est hors limites (index out of bounds) : la longueur est 3, mais l’indice vaut 10.

fn main() {
let numbers = [10, 20, 30];
for n in numbers {
println!("{n}");
}
}
▶ Essayez par vous-même

Un tableau peut contenir d’autres tableaux. Vous obtenez alors une grille avec des lignes et des colonnes, comme un plateau de jeu ou une petite feuille de calcul. Le type de grid ci-dessous est [[i32; 3]; 2], qui se lit « 2 lignes, chacune étant un tableau de 3 valeurs i32 ».

fn main() {
// 2 lignes, 3 colonnes
let grid = [
[1, 2, 3],
[4, 5, 6],
];
println!("Ligne 1, colonne 2 : {}", grid[1][2]);
let mut total = 0;
for row in grid {
println!("{:?}", row);
for value in row {
total += value;
}
}
println!("Total : {total}");
}

Sortie :

Ligne 1, colonne 2 : 6
[1, 2, 3]
[4, 5, 6]
Total : 21
▶ Essayez par vous-même

grid[1][2] signifie « la ligne 1, puis la colonne 2 dans cette ligne ». Les deux comptent à partir de 0 : c’est donc la deuxième ligne, troisième valeur. Pour visiter chaque valeur, utilisez une boucle pour les lignes et, à l’intérieur, une deuxième boucle pour les valeurs de chaque ligne.

Toutes les lignes doivent avoir la même longueur, car la longueur d’une ligne fait partie du type. Si vous avez aussi besoin de la position pendant la boucle, .iter().enumerate() vous donne l’indice et la valeur ensemble. C’est expliqué à la page boucle for.

Utilisez un tableau quand la taille est fixe et connue à l’avance (comme les sept jours de la semaine). Utilisez un Vec quand vous devez ajouter ou retirer des éléments, ce qui, en pratique, arrive la plupart du temps. Dans le code Rust de tous les jours, on croise moins souvent des tableaux que des vecteurs.

Créez le tableau [4, 8, 15, 16, 23, 42]. Additionnez toutes les valeurs, puis affichez la somme et la moyenne avec deux décimales. Indice : parcourez-le avec for, gardez un total cumulé, et convertissez les deux nombres en f64 avec as avant de diviser.

Voir la solution
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!("Somme : {total}");
println!("Moyenne : {average:.2}");
}

Sortie :

Somme : 108
Moyenne : 18.00
▶ Essayez par vous-même

Sans as f64, total / numbers.len() serait une division entière, et Rust se plaindrait en plus que total (un i32) et len() (un usize) ne sont pas du même type.

Vous avez les températures d’une semaine : [18, 25, 12, 31, 22, 27, 19]. Trouvez la plus élevée et affichez-la. Indice : commencez par let mut hottest = temps[0];, puis parcourez le tableau et remplacez la valeur chaque fois que vous en trouvez une plus grande.

Voir la solution
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!("Jour le plus chaud : {hottest}");
}

Sortie :

Jour le plus chaud : 31
▶ Essayez par vous-même

Partir de temps[0] plutôt que de 0 a son importance : si toutes les températures étaient négatives, partir de 0 donnerait une mauvaise réponse.

  • Les tableaux ont une longueur fixe qui fait partie de leur type : [i32; 5].
  • On accède aux éléments avec tableau[indice], en commençant à 0.
  • Un accès hors limites provoque une panique à l’exécution au lieu d’un comportement indéfini.
  • Un tableau peut contenir des tableaux : [[i32; 3]; 2] est une grille qu’on lit avec grid[ligne][colonne].
  • Si vous devez changer la taille, utilisez plutôt un Vec.

Petit quiz

1. Qu'est-ce qui est vrai à propos de la longueur d'un tableau en Rust ?

2. Que se passe-t-il quand on accède, à l'exécution, à un indice hors des limites du tableau ?

3. Que crée let zeros = [0; 5]; ?

Score : 0 / 3