Structure de compte utilisateur
On souhaite écrire un programme qui vérifie certaines propriétés sur un ensemble de comptes utilisateur. On dispose des identifiants (login) et des mots de passe (password) de ces comptes.
Nous allons commencer par créer la structure permettant de décrire un compte utilisateur :
- Créez un nouveau module
account
dans le projetpwdchk
. Le corps du module devra se trouver soit danssrc/account.rs
, soit danssrc/account/mod.rs
. - Référencez le module
account
depuissrc/main.rs
pour qu'il soit compilé lors d'uncargo build
. - Créez une structure
Account
contenant deux champs de typeString
:login
etpassword
. - Ajoutez dans l'implémentation de
Account
une méthode de classenew()
qui reçoit le login et le password en paramètres de type&str
et renvoie un nouvelAccount
reprenant ces informations.
struct Account { /* Ajouter les champs ici */ }
impl Account {
fn new(login: &str, password: &str) -> Self {
todo!() // À implémenter
}
}
- Créez une variable de type
Account
depuismain()
en utilisantAccount::new()
. À quel endroit faut-il augmenter la visibilité en ajoutantpub
pour pouvoir créer une variable de typeAccount
et appeler la méthodenew()
? - Depuis
main()
, affichez le compte nouvellement créé :
fn main() {
let account = Account::new("johndoe", "super:complex:password");
println!("{account:?}");
}
qui devra afficher
Account { login: "johndoe", password: "super:complex:password" }
On notera qu'on demande à utiliser le trait Debug
de Account
grâce à l'utilisation de {:?}
. Ce trait peut être dérivé automatiquement en précédant la définition de la structure par #derive(Debug)
:
#![allow(unused)] fn main() { #[derive(Debug)] struct Account { /* Ajouter les champs ici */ } }
On aurait pu utiliser {}
mais cela aurait nécessité d'implémenter le trait Display
pour Account
. Contrairement à Debug
, Display
ne peut pas être dérivé automatiquement.
Différentes écritures possibles
Les macros de type format!
(dont println!
, write!
, panic!
, etc.) possèdent plusieurs méthodes pour désigner leurs arguments. Toutes les formes ci-dessous sont équivalentes :
fn main() {
let account = Account::new("johndoe", "super:complex:password");
println!("{:?}", account); // Each {} uses a new argument
println!("{0:?}", account); // Use the first argument (0)
println!("{a:?}", a = account); // Use the `a` named argument
println!("{account:?}"); // Take argument from named arguments or context
}
La dernière forme ne permet pas de mettre des expressions complexes entre accolades, seules des variables peuvent être utilisées.
Forme alternative et arguments
Il est également possible d'opter pour une forme mieux formattée mais moins compacte d'affichage de la structure en utilisant {:#?}
, le modificateur #
signifiant ici l'utilisation de la forme alternative :
fn main() {
let account = Account::new("johndoe", "super:complex:password");
println!("account = {account:#?}");
}
On obtiendra alors la sortie :
Account {
login: "johndoe",
password: "super:complex:password",
}
Cette forme alternative est disponible pour un certain nombre de formats. Par exemple, le programme suivant
fn main() { println!("forme normale hexa = {0:x}, forme alternative = {0:#x}", 42); }
affichera
forme normale hexa = 2a, forme alternative = 0x2a
On notera que l'utilisation d'un argument positionnel (0) évite de répéter l'argument.