Environnement de travail¶
Sur votre machine perso, il est conseillé d'installer rust avec rustup et d'utiliser vscode pour éditer le code. Il y a une extension vscode
appellée rust-analyzer qui est très bien.
Sur les machines du département, recopiez le script /usr/local/Rust/var-env.sh à la fin de votre .profile pour configurer cargo et rustc, puis
installez l'extension rust-analyzer dans vscode.
En dépannage, si rien ne marche, vous pouvez travailler avec Rust Playground.
Exercice 1¶
- Créez un répertoire
TPs-Paradigmes-2et un sous répertoireTP1, puis créez un projethello_worlddansTP1avec la commandecargo. Exécutez votre programme. - En vous aidant du Rust book Chapitre 12.1, modifiez votre programme pour qu'il prenne en argument de ligne de commande un nom, et affiche
"hello, {nom}!"plutôt que "hello, world!". Indication: vous pourrez utiliser la méthode collect des itérateurs pour obtenir unVeccontenant tous les arguments de la ligne de commande. - Que se passe-t-il si vous lancez le programme sans fournir le nom en argument? Générez un message d'erreur plus explicite avec
panic!. - On veut maintenant ajouter une option
-gà ce petit programme. Lorsque l'option est activée, le tableau des arguments de la ligne de commande est affiché sur la sortie d'erreur avec la macrodbg!. Ensuite, on le programme affiche "hello {nom}" pour chaque nom apparaissant sur la ligne de commande, cf exemples ci-dessous
cargo run
[pas d'affichage]
cargo run alice bob
bonjour, alice!
bonjour, bob!
cargo run alice -g bob
[src/main.rs:25:9] &args = [
"target/debug/hello_world",
"alice",
"-g",
"bob",
]
bonjour, alice!
bonjour, bob!
Exercice 2¶
- Écrivez une fonction:
fn concat(v1: Vec<i32>, v2: Vec<i32>) -> Vec<i32>qui renvoie la concaténation dev1etv2. - Écrivez une fonction
concat2similaire àconcatsauf que ses paramètres sont empruntés, etv1est modifié en place. - Pourquoi n'est-il pas possible d'écrire une fonction
fn dup<T>(x: T) -> (T, T)? Pour quels typesTest-ce possible? - Même question pour
fn return_dangling_ptr<'a, T>(x: T) -> &'a T(rappel: les paramètres de fonction sont stockés dans la pile). Écrivez la fonctionreturn_dangling_ptren C, et regardez ce que ditgcc. - Écrivez une fonction
fn push_ampersand<T>(v: &Vec<T>) -> Vec<&T> - Écrivez une fonction
fn concat3<T>(v1: &Vec<T>, v2: &Vec<T>) -> Vec<&T>(en ajoutant les annotations de durées de vies nécessaires).
Exercice 3¶
- Créez un nouveau projet
exo3. Dansmain.rs, déclarez un typeMoneycorrespondant à un enregistrement avec deux champs:
centsqui est un entier non signé de la taille d'un mot machinecurrencyqui est une chaîne de caractères
- Implémentez une méthode
to_string()pourMoney(indication: utilisez la macroformat!, similaire àprint!, cf doc complète). On aura par exemple
let m = Money { cents: 3703, currency: "$".to_string() }
let s = m.to_string() // "37,03 $"
Testez votre code en modifiant la fonction main pour qu'elle affiche la variable s définie ci-dessus.
- Insérez le test ci-dessous dans
main.rs, et vérifiez qu'il passe. Vous pouvez soit lancer le test depuis vscode, soit en ligne de commande aveccargo test test_money_to_string(voir documentation).
#[cfg(test)]
mod tests {
#[test]
fn test_money_to_string() {
let m = Money { cents: 3703, currency: "$".to_string() }
let s = m.to_string() // "37,03 $"
assert_eq!(s, "37,43 $");
}
}
- Écrivez une fonction
convertà trois arguments:
- une valeur de type
Argent - une monnaie représentée par une chaîne de caractères ("$", "€", "£", "¥", etc)
- une liste associative qui donne la valeur d'un dollars dans chacune des monnaies listées, par exemple
vec![(0.93, "€"), (0.79,"£"),(150.0,"¥")]La fonction modifie son premier argument en place: elle remplace le champscurrencypar le second argument de la fonction, et met à jour le champscentsselon les taux de conversion passés en troisième argument. Vous utiliserez le dollars comme monnaie pivot, il faudra donc en général d'abord convertir en dollars puis dans la monnaie souhaitée.
Écrivez une fonction
convert_hidentique à celle de la question précèdente, sauf que son troisième argument est unHashMap.Écrivez une méthode
withdraw(&mut self, amount: &Argent, rates: HashMap<String,fsize>) -> Result<(),Argent>dans un blocimpl Argent. La méthode a pour effet de déduire deself.cents, lorsque c'est possible, la quantitée représentée paramount, une fois celle-ci convertie à la même unité queself; la méthode ne modifie pas le champscurrencydeself. La méthode utilisera la fonctionconvert_hde la fonction précédente sur l'argumentamount, qu'il vous faudra cloner (pourquoi?). Par exemple, sans se préoccuper de la conversion de monnaie:- en supposant que self vaut initialement 100 € et amount vaut 10 €, la méthode met self à 90 € et termine sans erreur.
- en supposant que self vaut initialement 100 € et amount vaut 1000 € , la méthode laisse self intact et termine avec une erreur qui contient la valeur
1000 €.
[Très facile] Écrivez une méthode
repeat_withdraw(&mut self, amounts: &Vec<Argent>, rates: &HashMap<String,fsize>) -> Result<(),Argent>qui appelle withdraw successivement sur chacun des montants de la listeamounts, tant qu'il est possible de retirer. Vous utiliserez?.