Introduction : pourquoi Rust ne permet-il pas de convertir simplement une chaîne en nombre ?
Si vous venez de Python ou JavaScript, vous êtes habitué à la magie comme int("42") ou parseInt("42"). En Rust, cette astuce ne fonctionnera pas — le compilateur exigera que vous spécifiiez clairement en quel type vous souhaitez transformer la chaîne. Pourquoi ? Parce que Rust est un langage qui ne pardonne pas la négligence. Il vous oblige à réfléchir aux cas limites : que faire si la chaîne ne contient pas un nombre ? Que faire si le nombre est trop grand pour le type choisi ?
Dans cet article, nous allons aborder la question la plus populaire sur Stack Overflow parmi les débutants en Rust : comment convertir String en int. Vous obtiendrez non seulement un code prêt à l'emploi, mais aussi une compréhension complète de ce qui se passe sous le capot.
La méthode parse() — l'outil principal de conversion
La principale façon de convertir une chaîne en nombre en Rust est la méthode parse(), disponible pour les types String et &str. Elle est implémentée via le trait FromStr et retourne un Result<T, E>.
Exemple de base : String → i32
fn main() { let number_string = String::from("42"); let number: i32 = number_string.parse().unwrap(); println!("Nombre : {}", number); // Affichage : Nombre : 42}Notez l'utilisation de unwrap(). C'est un moyen rapide d'« extraire » la valeur d'un Result, mais il est dangereux : si la chaîne n'est pas un nombre, le programme paniquera et plantera.
Gestion correcte des erreurs
Dans du code réel, vous ne devriez jamais utiliser unwrap() sans réfléchir. Voici comment faire correctement :
use std::num::ParseIntError;
fn main() { let input = String::from("hello"); match input.parse::<i32>() { Ok(number) => println!("Succès : {}", number), Err(e) => println!("Erreur de conversion : {}", e), }}Ou une version plus concise avec if let :
fn main() { let input = String::from("2024"); if let Ok(year) = input.parse::<i32>() { println!("Année : {}", year); } else { println!("Impossible d'analyser la chaîne"); }}Types entiers disponibles pour la conversion
Rust offre un large choix de types entiers. Vous pouvez convertir une chaîne en n'importe lequel d'entre eux :
i8,i16,i32,i64,i128— entiers signésu8,u16,u32,u64,u128— entiers non signésisize,usize— taille dépendante de l'architecture
Exemple de conversion en différents types :
fn main() { let val = "255"; let a: u8 = val.parse().unwrap(); // 255 let b: i16 = val.parse().unwrap(); // 255 let c: u32 = val.parse().unwrap(); // 255 // Mais cela générera une erreur — 255 ne tient pas dans i8 // let d: i8 = val.parse().unwrap(); // PANIC!}Techniques avancées : from_str et types personnalisés
La méthode parse() appelle en interne from_str() du trait FromStr. Vous pouvez implémenter ce trait pour vos propres structures :
use std::str::FromStr;use std::num::ParseIntError;
#[derive(Debug)]struct Version { major: u32, minor: u32,}
impl FromStr for Version { type Err = ParseIntError; fn from_str(s: &str) -> Result<Self, Self::Err> { let parts: Vec<&str> = s.split('.').collect(); if parts.len() != 2 { // Créons notre propre erreur, mais pour l'exemple utilisons ParseIntError return Err("1.0".parse::<u32>().unwrap_err()); } let major = parts[0].p