II. Spécificités de Rust
1. Le formatage des flux
Nous allons commencer cette deuxième partie par un chapitre relativement simple : le formatage des flux.
Exemple de print! et println!
Pour le moment, nous nous sommes contentés de faire de l'affichage sans y mettre de forme. Sachez toutefois qu'il est possible de modifier l'ordre dans lequel sont affichés les arguments sans pour autant changer l'ordre dans lesquels vous les passez à la macro. Démonstration :
Runprintln!("{} {} {}", "Bonjour", "à", "tous !");
println!("{1} {0} {2}", "à", "Bonjour", "tous !");
Le code que je vous ai montré n'a pas un grand intérêt mais il sert au moins à montrer que c'est possible. Cependant on peut faire des choses nettement plus intéressantes comme limiter le nombre de chiffres après la virgule.
Runlet nombre_decimal: f64 = 0.56545874854551248754;
println!("{:.3}", nombre_decimal);
Pas mal, hein ? Hé bien sachez qu'il y a un grand nombre d'autres possibilités comme :
Runlet nombre = 6i32;
let nombre2 = 16i32;
println!("{:b}", nombre); // affiche le nombre en binaire
println!("{:o}", nombre); // affiche le nombre en octal (base 8)
println!("{:x}", nombre); // affiche le nombre en "petit" hexadecimal (base 16)
println!("{:X}", nombre); // affiche le nombre en "grand" hexadecimal (base 16)
println!("{:08}", nombre); // affiche "00000006"
println!("{:08}", nombre2); // affiche "00000016"
Vous pouvez aussi faire en sorte que l'affichage s'aligne sur une colonne et pleins d'autres choses encore. Comme vous vous en rendrez compte par vous-même, il y a beaucoup de possibilités. Vous pourrez trouver tout ce que vous voulez à ce sujet ici (la doc officielle !).
À partir de la version 1.58 de Rust, il est aussi possible d'utiliser des arguments nommés :
Runlet nombre = 6i32;
println!("{nombre}");
// Qui revient au même qu'écrire :
println!("{}", nombre);
Tous les formattages vus juste au-dessus fonctionnent bien évidemment avec les arguments nommés :
Runlet nombre = 6i32;
println!("{nombre:b}"); // affiche le nombre en binaire
println!("{nombre:08}"); // affiche "00000006"
format!
Comme vous vous en doutez, c'est aussi une macro. Elle fonctionne de la même façon que print! et println!, mais au lieu d'écrire sur la sortie standard (votre console la majorité du temps), elle renvoie une String. Plus d'infos ici (oui, encore la doc !).
Runlet entier = 6i32;
let s_entier = format!("{}", entier);
Une façon simple (mais pas très efficace) de convertir un nombre en String.
Toujours plus loin !
Sachez que vous pouvez vous servir du formatage de la même façon pour écrire dans des fichiers ou sur tout autre type implémentant le trait Write (et il y en a pas mal !). Vous pouvez même faire ceci si vous le voulez :
Run// On importe le trait Write...
use std::io::Write;
let mut w = Vec::new();
// ... et on l'utilise sur notre Vec !
write!(&mut w, "test");
Et oui, encore une autre macro ! Ne vous en faites pas, c'est la dernière... en tout cas pour l'instant ! C'était juste pour vous montrer à quel point le formatage des flux pouvait aller loin.
Je présume que vous vous dites aussi : "c'est quoi cette histoire de trait ?!". Hé bien voyons ça de suite dans le prochain chapitre !