Aucune carte ne correspond. Essaie un autre mot-clé.
⌨️ Entrées / sorties (I/O)📘 Module 4
Lire une ligne au clavier (stdin)
use std::io::{self, Write};
let mut ligne = String::new();
io::stdin().read_line(&mut ligne).unwrap();
let ligne = ligne.trim(); // enlève le \n final
Lire un nombre
let n: i32 = ligne.trim().parse().expect("pas un nombre");
Lire plusieurs valeurs sur une ligne
let nums: Vec<i32> = ligne.split_whitespace()
.map(|x| x.parse().unwrap())
.collect();
Écrire (sortie)
println!("avec saut de ligne");
print!("sans saut "); io::stdout().flush().unwrap(); // force l'affichage
eprintln!("erreur sur stderr");
Piègesread_line garde le \n → toujours .trim(). read_line renvoie un Result (nb d'octets lus). Pour print! sans \n, pense à flush().
Arguments CLI & variables d'env.std::env::args() (itérateur d'arguments) · std::env::var("CLE") (variable d'environnement → Result).
let x = 5; // immuable
let mut y = 10; // mutable
const MAX: u32 = 100; // constante (MAJ)
let z: i64 = 42; // type explicite
let x = x + 1; // shadowing (re-déclare)
★ À retenirImmuable par défaut. mut pour modifier, const pour une vraie constante (type obligatoire), shadowing = redéclarer avec let.
| Catégorie | Types |
| Entiers signés | i8 i16 i32 i64 i128 isize |
| Entiers non signés | u8 u16 u32 u64 u128 usize |
| Flottants | f32 f64 |
| Booléen / caractère | bool · char (Unicode) |
| Texte | &str (vue) · String (possédé) |
| Composés | (i32, f64) tuple · [i32; 3] tableau |
let t = (1, "a", 3.0); // tuple
let (a, b, c) = t; // déstructuration
let arr = [0; 5]; // [0,0,0,0,0]
if n > 0 { … } else if n < 0 { … } else { … }
let s = if ok { 1 } else { 0 }; // if = expression
loop { break; } // boucle infinie
while cond { … }
for i in 0..5 { … } // 0..5 exclusif, 0..=5 inclus
for x in &vec { … } // itère par référence
Valeur depuis looplet v = loop { break 42; };
fn add(a: i32, b: i32) -> i32 {
a + b // PAS de ; = valeur de retour
}
fn log(msg: &str) { println!("{}", msg); }
Piège n°1a + b renvoie la valeur ; a + b; renvoie (). Le point-virgule final change tout.
| Règle | Détail |
| 1 propriétaire | Chaque valeur a un seul owner ; drop en fin de portée. |
| Move | Types tas (String,Vec) : let b=a; invalide a. |
| Copy | Types pile (i32,bool,char) : copiés, pas déplacés. |
&T | Emprunt lecture : plusieurs simultanés OK. |
&mut T | Emprunt écriture : un seul, et aucun &T en même temps. |
fn len(s: &String) -> usize { s.len() } // emprunte
fn push(s: &mut String) { s.push_str("!"); }
★ La règle d'orÀ tout instant : soit N lecteurs, soit 1 écrivain. Jamais les deux.
🔤 String & &str — méthodes📘 Module 9
| Méthode | Effet |
.len() | Taille en octets |
.push_str("x") / .push('c') | Ajoute |
.contains("a") | Sous-chaîne présente ? |
.replace("a","b") | Remplace |
.to_uppercase() / .to_lowercase() | Casse |
.trim() | Enlève espaces aux bords |
.split(',') | Itérateur de morceaux |
.chars() / .bytes() | Itère caractères / octets |
.parse::<i32>() | Texte → nombre (Result) |
.starts_with/.ends_with | Test de préfixe/suffixe |
let n: i32 = "42".parse().unwrap();
let s = format!("{}-{}", a, b); // construit une String
| Méthode | Effet |
vec![1,2,3] | Crée un vecteur |
.push(x) / .pop() | Ajoute en fin / retire (Option) |
.get(i) | Accès sûr → Option<&T> |
v[i] | Accès direct (panique si hors bornes) |
.len() / .is_empty() | Taille / vide ? |
.contains(&x) | Présence |
.sort() / .reverse() | Trie / inverse (en place) |
.iter() | Itérateur de références |
.remove(i) / .insert(i,x) | Retire / insère à l'index |
.dedup() | Supprime doublons consécutifs |
use std::collections::HashMap;
let mut m = HashMap::new();
m.insert("a", 1);
m.get("a"); // Option<&V>
*m.entry("a").or_insert(0) += 1; // compteur
for (k, v) in &m { … }
| Méthode | Effet |
.insert(k,v) | Ajoute / remplace |
.get(&k) | Option<&V> |
.contains_key(&k) | Clé présente ? |
.entry(k).or_insert(d) | Valeur ou défaut (patron compteur) |
.remove(&k) | Retire |
Remplace null : Some(v) ou None.
| Méthode | Effet |
.is_some()/.is_none() | Tests |
.unwrap() | Valeur ou panique |
.unwrap_or(d) | Valeur ou défaut |
.unwrap_or_else(||…) | Défaut calculé |
.map(|x| …) | Transforme si Some |
.and_then(|x| …) | Chaîne qui renvoie une Option |
.ok_or(e) | Convertit en Result |
if let Some(v) = opt { println!("{}", v); }
let n = opt.unwrap_or(0);
✅ Result<T,E> & erreurs📘 Module 10
Ok(v) ou Err(e). L'opérateur ? propage l'erreur.
fn lire() -> Result<String, io::Error> {
let s = std::fs::read_to_string("f.txt")?; // propage si Err
Ok(s)
}
| Méthode | Effet |
? | Renvoie l'Err immédiatement, sinon déballe |
.unwrap()/.expect("msg") | Valeur ou panique (+ message) |
.unwrap_or(d) | Valeur ou défaut |
.map_err(|e|…) | Transforme l'erreur |
.is_ok()/.is_err() | Tests |
match n {
0 => "zéro",
1 | 2 => "petit",
3..=9 => "moyen", // intervalle
n if n < 0 => "négatif", // garde
_ => "autre", // obligatoire si non exhaustif
}
ExhaustivitéUn match doit couvrir tous les cas : ajoute _ pour le reste.
if let Some(x) = opt { … } // un seul cas
while let Some(x) = it.next() { … }
🏗️ Structs & méthodes📘 Module 7
struct Point { x: f64, y: f64 }
impl Point {
fn new(x: f64, y: f64) -> Self { Point{x, y} } // assoc.
fn norme(&self) -> f64 { (self.x*self.x + self.y*self.y).sqrt() }
}
let p = Point::new(3.0, 4.0);
p.norme(); // 5.0
self&self lecture · &mut self modifie · self consomme · sans self = fonction associée (Type::fn()).
enum Forme {
Cercle(f64), // porte des données
Rect(f64, f64),
Vide,
}
fn aire(f: &Forme) -> f64 {
match f {
Forme::Cercle(r) => 3.14 * r * r,
Forme::Rect(w, h) => w * h,
Forme::Vide => 0.0,
}
}
trait Decrire { fn desc(&self) -> String; }
impl Decrire for Point {
fn desc(&self) -> String { format!("({},{})", self.x, self.y) }
}
Derive automatique#[derive(Debug, Clone, PartialEq)] au-dessus d'un type génère ces traits. Debug → affichage {:?}.
fn afficher(x: &impl Decrire) { … } // trait en paramètre
🧬 Génériques & lifetimes📘 Module 12
fn max<T: PartialOrd>(a: T, b: T) -> T {
if a > b { a } else { b }
}
// lifetime : la sortie vit aussi longtemps que les entrées
fn plus_long<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
★ LifetimesDes étiquettes ('a) qui garantissent qu'une référence ne survit jamais à la donnée pointée. Vérifié à la compilation, zéro coût à l'exécution.
| Adaptateur | Effet |
.map(|x| …) | Transforme chaque élément |
.filter(|x| …) | Garde si vrai |
.enumerate() | Paires (index, val) |
.zip(autre) | Associe deux itérateurs |
.take(n)/.skip(n) | Prend / saute n |
.rev() | Inverse |
.flatten() | Aplatit les niveaux |
| Consommateur | Effet |
.collect() | Construit Vec/String/HashMap… |
.sum()/.product() | Somme / produit |
.count()/.max()/.min() | Compte / extrêmes |
.fold(init,|a,x| …) | Accumulation générale |
.any(…)/.all(…) | Au moins un / tous |
.find(…)/.position(…) | Premier qui matche |
.for_each(…) | Effet de bord |
let somme: i32 = v.iter().filter(|&&x| x > 0).sum();
let carres: Vec<_> = (1..=5).map(|x| x*x).collect();
LazyRien ne s'exécute avant un consommateur (collect, sum, for…).
let ajoute = |a, b| a + b; // infère les types
let x = 10;
let incr = |n| n + x; // capture x (environnement)
let conso = move || println!("{}", x); // move = prend possession
| Trait | Capture |
Fn | Par référence (lecture) |
FnMut | Par référence mutable |
FnOnce | Par valeur (une seule fois) |
| Type | Usage |
Box<T> | Sur le tas ; types récursifs (arbres) |
Rc<T> | Plusieurs propriétaires (lecture, mono-thread) |
RefCell<T> | Mutabilité intérieure (vérif. runtime) |
Arc<T> | Rc thread-safe (atomique) |
Mutex<T> | Verrou pour partage mutable entre threads |
CombosRc<RefCell<T>> (graphe mono-thread) · Arc<Mutex<T>> (partage multi-thread).
use std::thread;
let h = thread::spawn(|| { /* travail */ });
h.join().unwrap(); // attend la fin
use std::sync::mpsc; // canal (channel)
let (tx, rx) = mpsc::channel();
thread::spawn(move || tx.send(42).unwrap());
rx.recv().unwrap(); // 42
★ Fearless concurrencyLes data races sont bloquées à la compilation. Partage : Arc<Mutex<T>> · communication : channels.
🖨️ Affichage & format!📘 Module 2
| Motif | Effet |
{} | Affichage « Display » |
{:?} / {:#?} | Debug / Debug joli |
{:5} / {:<5} / {:^5} | Largeur, alignement |
{:.2} | 2 décimales |
{:08.2} | Largeur 8, zéros, 2 déc. |
{:b} / {:x} / {:o} | Binaire / hexa / octal |
{name} | Argument nommé / capturé |
println!("{:.2}", 3.14159); // 3.14
println!("{x} = {x:b}"); // capture la variable x
| Commande | Rôle |
cargo new projet | Crée un projet |
cargo check | Vérifie sans compiler (rapide) |
cargo build | Compile (debug) |
cargo build --release | Compile optimisé |
cargo run | Compile + exécute |
cargo test | Lance les tests |
cargo add crate | Ajoute une dépendance |
cargo fmt / cargo clippy | Formate / lint |
cargo doc --open | Génère & ouvre la doc |
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ca_marche() {
assert_eq!(add(2, 2), 4);
assert!(1 < 2);
}
}
Macros d'assertionassert! · assert_eq! · assert_ne!. Lancer : cargo test.
🗂️ Modules & visibilité📘 Module 16
mod math {
pub fn carre(x: i32) -> i32 { x * x } // pub = public
}
use crate::math::carre; // importe
carre(4);
| Mot-clé | Sens |
mod | Déclare un module |
pub | Rend public |
use | Importe un chemin |
crate/super/self | Racine / parent / module courant |
⚠️ Pièges fréquents
- Le
; final transforme une valeur de retour en ().
- Move : réutiliser une
String/Vec après let b=a; → erreur.
- & vs &mut : pas de mutable tant qu'un immuable vit.
match non exhaustif : ajoute _.
- Oubli de
mut : « cannot assign twice ».
unwrap() sur None/Err → panique.
- Référence pendante : renvoyer
& vers une variable locale.