Loading s5obj_rust_main...
#[derive(Debug)] pub struct Sensor { name: String, min: f64, max: f64, samples: Vec<f64>, }
impl Sensor { pub fn new( name: String, mut min: f64, mut max: f64, ) -> Self { if max < min { std::mem::swap(&mut min, &mut max); } Self { name, min, max, samples: Vec::new(), } }
pub fn new_with_max( name: String, max: f64, ) -> Self { Self::new(name, 0.0, max) }
pub fn add( &mut self, sample: f64, ) { let clamped = sample.clamp(self.min, self.max); self.samples.push(clamped); }
pub fn name(&self) -> &str { &self.name }
pub fn count(&self) -> usize { self.samples.len() }
pub fn min_max(&self) -> (f64, f64) { (self.min, self.max) }
pub fn min( &mut self, min: f64, ) { self.min = min; for sample in self.samples.iter_mut() { *sample = (*sample).max(self.min); } }
pub fn mean(&self) -> f64 { let sum = self.samples.iter().sum::<f64>(); sum / self.count() as f64 }
pub fn sigma(&self) -> f64 { //sqrt(1/sz*sum[(xi-moy)²]) let m = self.mean(); let sigma = self.samples.iter().map(|s| (s - m) * (s - m)).sum::<f64>(); (sigma / self.count() as f64).sqrt() } }
fn main() { let mut sen = Sensor::new("Speed".to_string(), 0.0, 100.0); for i in 0..12 { sen.add(i as f64 * 10.0); } sen.min(28.0); println!("{:?}", sen); println!("mean: {} sigma: {}", sen.mean(), sen.sigma()); } /* Sensor { name: "Speed", min: 28.0, max: 100.0, samples: [28.0, 28.0, 28.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 100.0] } mean: 58.666666666666664 sigma: 27.46310656539464 */
mod banque { // pour le premier critère, il faut avoir déclaré correctement // la classe CompteBancaire avec ses données membres (ayant les bon types) // et il faut appliquer l'encapsulation pub struct CompteBancaire { solde: f64, nb_retraits: i32, max_retraits: i32, // ou simplement : // solde: f64, // max_retraits: i32, // mais max_retraits devra être initialisé à la valeur maximale }
// pour le deuxième critère il faut avoir le bloc impl avec les fonctions // requises. Il faut un constructeur (qui renvoie un Self) et des méthodes // qui reçoivent en paramètre le self par référence mutable ou // pas selon les besoins. Il faut que les fonctions renvoient une donnée, // si nécessaire, et que celle-ci soit du bon type. impl CompteBancaire { pub fn new( solde: f64, max_retraits: i32, ) -> Self { Self { solde, nb_retraits: 0, max_retraits, } }
pub fn retirer( &mut self, montant: f64, ) -> Result<(), String> { // Pour le critère 2, il faut une vérification avant retrait // Il n'est pas obligatoire d'utiliser un Result. L'utiliser // permet de dépasser la note de 15 (Au delà des attentes), mais // seulement si tout le reste est parfait : // Avoir des jolis rideaux dans une maison sans fondations ne // sert à rien if self.solde - montant < 0.0 { Err("Solde insuffisant".to_string()) } else if self.nb_retraits >= self.max_retraits { Err("Nombre maximal de retraits atteint".to_string()) } else { self.solde -= montant; self.nb_retraits += 1; Ok(()) } }
pub fn deposer( &mut self, montant: f64, ) { self.solde += montant; }
pub fn get_solde(&self) -> f64 { self.solde } } } // fin du module
use banque::CompteBancaire;
fn main() { // pour le troisième critère il faut instancier correctement // un objet de type CompteBancaire et il doit être mutable let mut compte = CompteBancaire::new(2000.0, 20);
// pour le quatrième critère, il faut invoquer correctement les // méthodes (toutes celles demandées pour avoir Bien) compte.deposer(1000.0);
if let Err(msg) = compte.retirer(500.0) { println!("Erreur: {}", msg); }
println!("Solde: {}", compte.get_solde()); } /* Solde: 2500 */
// EN GENERAL : il faut suivre le diagramme de classes à la lettre // et il faut écrire correctement les classes et leurs méthodes
mod house { // pour le première critère, il faut avoir la structure Room pub struct Room { name: String, }
// pour le troisième critère, il faut avoir la structure Parking pub struct Parking { square_meters: f32, } impl Parking { pub fn new(square_meters: f32) -> Self { Self { square_meters } } }
// pour le première critère, il faut que la classe House possède un vector de Room // pour le troisième critère, il faut que la classe House possède un Option de // référence mutable sur un Parking. Il faut utiliser correctement le lifetime pub struct House<'a> { address: String, rooms: Vec<Room>, parking: Option<&'a mut Parking>, }
// pour le première critère, il faut que le constructeur de House instancie // le vector de Room. il doit être vide initialement. // pour le troisième critère, il faut que le constructeur de House initialise // la référence parking avec None. Au début la maison n'a pas de parking. // Et il faut utiliser correctement le lifetime impl<'a> House<'a> { pub fn new(address: String) -> Self { Self { address, rooms: Vec::new(), parking: None, } }
// pour le première critère, il faut la fonction add_room. // Attention ! La pièce à ajouter doit être créée dans cette fonction et // pas passée en paramètre, si non le diagramme de classes n'est pas respecté. pub fn add_room( &mut self, name: String, ) { self.rooms.push(Room { name }); }
// pour le troisième critère, il faut la fonction set_parking // et il faut utiliser correctement le lifetime // Utiliser correctement le Option permet d'avoir plus de 15 // (Au delà des attentes) mais seulement si tout le reste est parfait. pub fn set_parking( &mut self, parking: &'a mut Parking, ) { self.parking = Some(parking); } } }
use house::*;
fn main() { // pour le deuxième critère, il faut instancier une maison mutable et lui // ajouter deux pièces à l'aide de la méthode add_room. // pour le quatrième critère, il faut instancier un parking mutable et // l'affecter à la maison intanciée auparavant à l'aide de la fonction // set_parking let mut h = House::new("rue de la Paix".to_string()); h.add_room("kitchen".to_string()); h.add_room("livingroom".to_string()); let mut p = Parking::new(9.0); h.set_parking(&mut p); }
pub trait SpeakBehavior { fn speak(&self); }
pub struct Animal { name: String, speak: Box<dyn SpeakBehavior>, }
impl Animal { pub fn new( name: String, speak: Box<dyn SpeakBehavior>, ) -> Self { Self { name, speak } }
pub fn speak(&self) { print!("{} says: ", self.name); self.speak.speak(); } }
pub struct Cat {}
impl SpeakBehavior for Cat { fn speak(&self) { println!("MEEEEEOOOOOOWWWWWWW!!!!!!",); } }
pub struct Dog {}
impl SpeakBehavior for Dog { fn speak(&self) { println!("WOOOOOOUUUUUUFFFFFF!!!!!!",); } }
fn main() { //Create a cat and a dog let cat = Animal::new("Hiccup".to_owned(), Box::new(Cat {})); let dog = Animal::new("Rex".to_owned(), Box::new(Dog {}));
println!("~~~~~~~ Cat and Dog speak ~~~~~~~"); cat.speak(); dog.speak(); } /* ~~~~~~~ Cat and Dog speak ~~~~~~~ Hiccup says: MEEEEEOOOOOOWWWWWWW!!!!!! Rex says: WOOOOOOUUUUUUFFFFFF!!!!!! */
// EN GENERAL, il faut suivre le diagramme de classes à la lettre // et il faut écrire correctement les classes et leurs méthodes
mod vehicle { // pour le première critère, il faut déclarer l'interface (trait) Drivable // et déclarer la fonction abstraite demandée pub trait Drivable { fn drive(&self) -> f64; }
// pour le deuxième critère, il faut déclarer la classe PetrolCar // et il faut qu'elle implémente l'interface Drivable pub struct PetrolCar { afc: f64, tank: f64, }
impl PetrolCar { pub fn new( afc: f64, tank: f64, ) -> Self { Self { afc, tank } } }
impl Drivable for PetrolCar { fn drive(&self) -> f64 { self.tank / self.afc } }
// pour le troisième critère, il faut que la classe Vehicle soit // composée d'un objet de type Drivable. Puisque Drivable est une // interface, le Box est obligatoire. // Il faut que cette composition soit correctement initialisée dans // le constructeur pub struct Vehicle { name: String, driving: Box<dyn Drivable>, }
impl Vehicle { pub fn new( name: String, driving: Box<dyn Drivable>, ) -> Self { Self { name, driving } }
pub fn name(&self) -> &str { &self.name }
// pour le troisième critère, il faut que la classe Vehicle fournisse // une implémentation pour la fonction drive() pub fn drive(&self) -> f64 { self.driving.drive() } } }
use vehicle::*;
fn main() { // pour le quatrième critère, il faut qu'un objet de type Vehicle soit // instancié correctement let car = Vehicle::new( "Sandero".to_string(), Box::new(PetrolCar::new(0.05, 60.0)), ); // pour le quatrième critère, il faut invoquer correctement la fonction // polymorphe println!( "La {} peut parcourir {} kilomètres.", car.name(), car.drive() ); } /* La Sandero peut parcourir 1200 kilomètres. */
trait ByteReader { fn next_byte(&mut self) -> Option<u8>; }
fn read_line<T: ByteReader>(src: &mut T) -> Option<String> { let mut bytes = Vec::new(); while let Some(b) = src.next_byte() { bytes.push(b); if b == b'\n' { break; } } if bytes.is_empty() { None } else { Some(String::from_utf8_lossy(&bytes).to_string()) } }
struct Buffer { data: Vec<u8>, pos: usize, } impl Buffer { fn new(data: Vec<u8>) -> Self { Self { data, pos: 0 } } } impl ByteReader for Buffer { fn next_byte(&mut self) -> Option<u8> { if self.pos < self.data.len() { let b = self.data[self.pos]; self.pos += 1; Some(b) } else { None } } }
impl ByteReader for std::fs::File { fn next_byte(&mut self) -> Option<u8> { use std::io::Read; let mut b = 0; match self.read_exact(std::slice::from_mut(&mut b)) { Ok(()) => Some(b), Err(_) => None, } } }
fn show_lines<T: ByteReader>(src: &mut T) { let mut count = 1; while let Some(l) = read_line(src) { println!("line {}: {:?}", count, l); count += 1; } }
fn main() { println!("~~~~ reading buffer ~~~~"); let mut buffer = Buffer::new(vec![65, 66, 67, 68, 10, 120, 121, 122, 10]); show_lines(&mut buffer); println!("~~~~ reading file ~~~~"); if let Ok(mut file) = std::fs::File::open("Cargo.toml") { show_lines(&mut file); } } /* ~~~~ reading buffer ~~~~ line 1: "ABCD\n" line 2: "xyz\n" ~~~~ reading file ~~~~ line 1: "[package]\n" line 2: "name = \"demo\"\n" line 3: "version = \"0.1.0\"\n" line 4: "edition = \"2021\"\n" line 5: "\n" line 6: "# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n" line 7: "\n" line 8: "[dependencies]\n" */