Cél és előfeltétel
Egy kétkönyves katalóguson kapcsolod össze az útvonal fogalmait. A könyvnek saját címe, azonosítója és kölcsönzési állapota lesz. A műveletek nézetet vagy módosítható nézetet kapnak a könyvekre. Nem készítünk adatbázist, felhasználói bejelentkezést vagy teljes könyvtári rendszert; a cél néhány kis, világos szerződésű memóriabeli művelet.
Előfeltétel az enumok és állapotok, valamint a szeletek és nézetek megértése. Minden megoldás külön edition 2024 főprogram. A példák saját beágyazott adatokat használnak, és semmit nem írnak külső tárolóba. A három feladatban fokozatosan építjük fel a keresés, kölcsönzés és visszavétel szabályát.
Az azonosító nem a tömb pozíciója
A katalógusban minden könyv külön nem nulla azonosítót kap, és a kezdő adatokban ezek egyediek. A kettes index és a kettes azonosító nem ugyanaz: egy könyv helye megváltozhat anélkül, hogy a könyv azonossága módosulna. A kereső ezért végigvizsgálja a rekordokat, nem közvetlen tömbindexként használja a kapott azonosítót. Két könyvnél ez egyszerű és jól követhető.
A lecke nem készít új rekordokat felvevő műveletet, ezért az azonosítók egyediségét a megadott kezdő adatok biztosítják. Ha bővítenéd a katalógust, a beszúrásnak is őriznie kellene ezt a szabályt. Nem elegendő remélni, hogy a hívó sosem ad duplikált számot. Ez jó példa arra, hogy a modell és a műveletek együtt hordozzák a rendszer ígéreteit.
Keresésnél a hiány szabályos eredmény
A kereső megosztott könyvszeletet kap, és találat esetén kölcsönzött könyvreferenciát ad vissza. A hiányt Option fejezi ki. A visszaadott referencia az eredeti katalógus könyvére mutat, nem új másolatot készít, ezért a forrásnak a használatáig érvényesnek kell maradnia. Az aláírásban szereplő egyetlen bemeneti referencia miatt a kapcsolódó élettartamot itt a fordító következteti.
A hívó a talált könyv címét megvizsgálhatja, majd később új műveletet végezhet a katalóguson, ha a korábbi olvasó nézetet már nem használja. A sorrend ugyanazt a kölcsönzési elvet követi, amelyet egyetlen String esetén tanultál. A gyűjtemény nem szünteti meg ezeket a szabályokat, csak több adatot fog össze.
Állapotváltás a megfelelő könyvön
Kölcsönözni csak szabad könyvet lehet, nem üres olvasónévvel. A név körüli szóközöket levágjuk a tárolás előtt, hogy egy tisztán szóközös név is elutasítható legyen. Nem próbálunk teljes névellenőrző rendszert építeni; itt ez az egy jól kimondott szabály szerepel. A könyv címe és azonosítója a kölcsönzés során nem változhat.
Az enum szabad változatában nincs olvasónév, a kölcsönzöttben van. Egy már foglalt könyv újabb kölcsönzését változtatás nélkül elutasítjuk. A visszavétel csak a kölcsönzött állapotot váltja szabadra. Egy valós rendszernek naplózásra és tartós adatokra is szüksége lenne, de itt a konkrét állapotváltás helyességét tanuljuk meg közvetlen állításokkal.
1. feladat: keresés azonosító alapján
Definiálj könyvtípust azonosítóval és saját címmel. Írj kereső függvényt, amely könyvszeletből találatot vagy hiányt ad. A könyvek azonosítója tíz és húsz legyen, hogy ne lehessen véletlenül pozíciónak nézni. Ellenőrizd a találat címét, egy nem létező számot és az üres katalógust is.
Megoldás
struct Konyv { id: u32, cim: String }
fn keres(konyvek: &[Konyv], id: u32) -> Option<&Konyv> {
for konyv in konyvek {
if konyv.id == id { return Some(konyv); }
}
None
}
fn main() {
let konyvek = [
Konyv { id: 10, cim: String::from("Abigél") },
Konyv { id: 20, cim: String::from("Tüskevár") },
];
assert_eq!(keres(&konyvek, 20).map(|k| k.cim.as_str()), Some("Tüskevár"));
assert!(keres(&konyvek, 99).is_none());
assert!(keres(&[], 10).is_none());
assert_eq!(konyvek[0].id, 10);
}
A map itt a találat esetén kiolvasott címet alakítja szövegnézetté; hiánynál None marad. Nem gyűjteményt térképezünk át, hanem egy opcionális eredményt.
2. feladat: kölcsönzés adatvesztés nélkül
Készíts szabad és kölcsönzött állapotot. Egy könyvön a kölcsönző metódus utasítsa el az üres nevet és a már kölcsönzött állapotot. A siker után őrizze meg az első olvasó nevét akkor is, ha második ember próbálkozik. Az állapotot teljes értékként hasonlítsd össze, ne csak a visszatérő igaz vagy hamis jelzést vizsgáld.
Megoldás
#[derive(Debug, PartialEq, Eq)]
enum Allapot { Szabad, Kolcsonozve(String) }
struct Konyv { allapot: Allapot }
impl Konyv {
fn kolcsonoz(&mut self, nev: &str) -> bool {
let nev = nev.trim();
if nev.is_empty() || !matches!(&self.allapot, Allapot::Szabad) {
return false;
}
self.allapot = Allapot::Kolcsonozve(nev.to_owned());
true
}
}
fn main() {
let mut konyv = Konyv { allapot: Allapot::Szabad };
assert!(!konyv.kolcsonoz(" "));
assert_eq!(konyv.allapot, Allapot::Szabad);
assert!(konyv.kolcsonoz(" Eszter "));
assert!(!konyv.kolcsonoz("Bence"));
assert_eq!(konyv.allapot, Allapot::Kolcsonozve(String::from("Eszter")));
}
A második név nem írja felül az elsőt. Ez a változatlan elutasítás legfontosabb ellenőrzése, nem csupán egy ismételten visszaadott hamis eredmény.
3. feladat: visszavétel a katalógusból
A teljes könyvtípushoz add vissza az azonosítót és címet. Írj katalógusszintű visszavételt: a megfelelő könyvet keresse, és csak kölcsönzött állapotból váltson szabadra. A második visszavétel és az ismeretlen azonosító legyen sikertelen. A végén ellenőrizd, hogy a könyv címe, azonosítója és a másik rekord állapota nem változott.
Megoldás
#[derive(Debug, PartialEq, Eq)]
enum Allapot { Szabad, Kolcsonozve(String) }
struct Konyv { id: u32, cim: String, allapot: Allapot }
fn visszavesz(konyvek: &mut [Konyv], id: u32) -> bool {
for konyv in konyvek {
if konyv.id == id {
if matches!(&konyv.allapot, Allapot::Szabad) { return false; }
konyv.allapot = Allapot::Szabad;
return true;
}
}
false
}
fn main() {
let mut konyvek = [
Konyv { id: 10, cim: String::from("Abigél"), allapot: Allapot::Kolcsonozve(String::from("Eszter")) },
Konyv { id: 20, cim: String::from("Tüskevár"), allapot: Allapot::Szabad },
];
assert!(visszavesz(&mut konyvek, 10));
assert!(!visszavesz(&mut konyvek, 10));
assert!(!visszavesz(&mut konyvek, 99));
assert_eq!(konyvek[0].allapot, Allapot::Szabad);
assert_eq!(konyvek[0].id, 10);
assert_eq!(konyvek[0].cim, "Abigél");
assert_eq!(konyvek[1].allapot, Allapot::Szabad);
}
A keresés és módosítás ugyanazon a bejárt könyvön történik. Nincs szükség a teljes rekord klónozására vagy a cím alapján való bizonytalan kiválasztásra.
Elfogadási feltételek
- A keresés azonosító alapján működik, ismeretlen számnál és üres katalógusnál hiányt ad.
- Az üres név nem kölcsönözhet, a második olvasó nem írhatja felül a már tárolt nevet.
- A visszavétel csak egyszer sikeres, és sem az azonosítót, sem a címet, sem a másik könyvet nem módosítja.
Továbblépés
A típusokkal és kölcsönzésekkel felépített szabályokat most már külvilágból érkező bemenetre is alkalmazhatod. Az argumentumok és használati útmutató leckében előbb a program hívási szerződését rögzíted, majd erre építesz kis parancssori eszközt.