PR2ET8: Dünaamiline mälu 2

Labori materjal

Laboriülesanded

Selles laboris on üks ülesanne, mida laiendab kaks lisaülesannet

Ülesanne [W08-1]: Faili lugemine kasutades dünaamilist mälu

Selle ülesande eesmärgiks on tutvuda kuidas lugeda teadmata pikkusega faile sedasi, et me kasutame täpselt nii palju mälu kui failis olevate andmete hoiustamiseks vaja on.

Andmefail

Andmefaili struktuur on järgnev:  <indeks> <perenimi> <eesnimi> <õppekava kood> <punktide arv>

  • Indeks (täisarv)
  • Ees- ja perenimi – erineva pikkusega sõned
  • Õppekava kood – 4-tähemärgi pikkune sõne
  • Punktide arv – kümnendmurd vahemikus 10,0 kuni 30,0 täpsusega 0,1.

Võid kasutada andmefailide loomiseks oma eelmise nädala laboriülesande lahendust. Testimiseks on antud siiski kindlad failid, et saaksid oma väljundit võrrelda.

Andmefailid mille väljundi näited on ka testimine osas: https://blue.pri.ee/ttu/files/iax0584/andmefailid/8_scholarship_data.zip

Nõuded
  • Loe teadmata pikkusega andmefaili sisu mällu
    • Lugemiseks kasuta realloc()  funktsiooni, laiendades mäluala suurust jooksvalt lugemise käigus.
    • Andmed salvesta dünaamiliselt loodud struktuurimassiivi
    • Lugemise lõpuks peab küsitud mälumaht olema täpselt nii suur kui on vaja failis olevate andmete hoiustamiseks.
    • Faili tohib vaid ühel korral lugeda (korduv lugemine keelatud! Ka lihtsalt reavahetuste arvu lugemine ei ole lubatud!)
    • Arvesta, et faili pikkus võib muutuda! St faili pikkus selgub lugemise käigus!
  • Kõik muutuva pikkusega sõned tuleb mälus hoida täpse pikkusega.
    • Lugemise ajal kasuta staatilist puhvrit, struktuuris hoidmiseks kasuta dünaamilist mälu!
  • Failis on stipendiumile kandideerivate tudengite loetelu. Stipendiumi saavad:
    • Igast järgnevast erialast kuni 7 kõige kõrgema punktisummaga tudengit: IACB, EARB ja MVEB.
  • Kuva stipendiumi saajate nimekiri ning näita mitu tudengit igalt erialalt stipendiumi sai.
  • Veendu, et programm ei tekita mälulekkeid!
Andmestruktuur ülesandele

Selles ülesandes läheme üle dünaamilisele mälule struktuuri liikmete hulgas mille pikkus on muutuv (sõned ja teised massiivid) – see säästab meil mälu ja suurendab paindlikkust. Struktuur võtab järgneva kuju:

Märkused:

  • Soovi korral võid nimetusi endale sobilikumaks muuta
  • fName  ja lName  on nüüd viidad, mis vajavad dünaamilist mälu enne kui nendesse midagi salvestada saab – seda kuna nime pikkus on muutuv inimeselt inimesele.
  • Õppekava koodi massiiv on staatiline sest see on alati täpselt sama pikk – dünaamiline mälu siin oleks raiskav.
  • Üksikud täisarvud, murdarvud jne jäävad samuti staatiliseks – jällegi, dünaamiline mälu siin teeks programmi põhjendamatult aeglasemaks ja keerukamaks.
Soovituslik loetelu funktsioonidest

NB! Funktsioonide tegelik kuju sõltub kuidas otsustad ülesannet lahendada ja struktureerida.

Minimaalselt on sul vaja kolme funktsiooni:

  • Andmete lugemise funktsioon failist (vali välja järgmisest peatükist).
  • Vastuste väljastamise funktsiooni.
  • Andmete vabastamise funktsiooni

Soovituslikud funktsioonid enda elu lihtsamaks tegemiseks

  • qsordi võrdlusfunktsioon
  • Ühe tudengi andmete printimise funktsioon (kasulik kui prindid tudengi andmeid, kes stipendiumi saab.
  • Kaitsva programmeerimisstiili jaoks kulub ära ka slaididel näidatud vabastamisfunktsioon

Lugemise kontrollimiseks võib olla mõistlik luua ka funktsioon, mis trükib kõigi tudengite andmed välja mis failist kätte saadi. See aga pole ülesande osa.

Funktsioon andmete lugemiseks

Sel korral võtab andmete lugemise funktsioon veidi teistsuguse kuju.  Funktsioonist on meil vaja saada kätte 2 uut väärtust – dünaamilise massiivi asukoht ja failist loetud ridade arv. Selleks pakun välja kolm erinevat funktsiooni kuju, mille hulgast saad valida endale meelepärase!

Variant 1 on kõige sarnasem varasemalt tuttavale faili lugemise funktsiooni kujule. Funktsiooni tagastuseks on ridade arv ning mäluviida saame kätte kasutades topeltviita.

Variant 2 vahetab andmete liikumise ümber – ridade arv tuleb nüüd kasutades viita ning tagastusena anname mäluaadressi dünaamilisele massiivile. Sedasi saab vältida topeltviida kasutamist, kui see liiga keerukaks osutub.

Variant 3 liigutab kogu andmevahetuse viitadele. See lubab meil funktsioonist tagastada funktsiooni töö oleku – st kas lugemine töötas edukalt või ebaõnnestus. See on ka kõige lähedasem suurele osale C keelsetele funktsioonidele – suur osa neist tagastab nulli kui töö oli edukas ning mittenullise väärtuse kui juhtus viga.

NB! Kasutades lisaülesandes 2 tutvustatud ümbrisstruktuuri ideed saab parameetrite loetelu veelgi puhtamaks!

Variant 1Variant 2Variant 3
Testimine

Esimeses näites kasutame pikemat andmefaili, kus kõik loetelud said täis.

Teises näites on andmefail lühem.

Lisaülesanne 1 [W08-2]: Optimaalne mäluhõive

Selles ülesandes muudame oma dünaamilise mälu hõivamise mõistlikumaks kasutades optimaalsemat mälu laiendamise strateegiat.

Nõuded
  • Muuda oma faili lugemist sedasi, et lugemisek kasutaksid (n * 2) strateegiat
    • St iga kord kui küsitud mälumaht saab otsa, laiendatakse mäluala 2x võrreldes olemasolevaga
  • Alustamiseks vali n mis on suurem kui 1 (vali siiski vähemalt 3x väiksem kui pikima faili pikkus

Lisaülesanne 2 [W08-3]: ümbris-struktuur

Selles ülesandes muudame oma koodi veelgi loetavamaks ja seotumaks, pannes oma andmestruktuuri ja selle omadused ühte ümbritsevasse struktuuri.

Nõuded
  • Pane oma struktuurimassiiv teise struktuuri ehk ümbrise sisse (wrapper struct),
  • Ümbrises peaks olema 3 muutujat – viide struktuurile, struktuuri suurus ja struktuuri kasutatud liikmete arv.
  • Muuda oma funktsioonide parameetreid nii, et nüüd need kasutaksid uut vastloodud ümbrisstruktuuri.
  • NB! Mõtle läbi mis funktsiooni on mõistlik viit ümbrisele anda, millisesse pole seda mõtet teha!

Vihje: Kuna nüüd on iga välja poole pöördumisel vaja ümbrisstrukuturist valida välja õige liige, siis võib loetavuse huvides olla see mõistlik “lahti pakkida” eraldi muutujasse vastava funktsiooni või tsükli sees. Näiteks

Pärast seda tundi peaksid

  • teadma erinevaid võimalusi kuidas struktureerida ja lugeda faile mille pikkus võib erineda
  • oskama dünaamiliselt oma massiivide suurust muuta
  • oskama lugeda faile dünaamilist mälu kasutades jooksvalt ja täpselt
  • teadma kõiki võimalike realloci tagastuste võimalus
  • teadma kahte laiendamise strateegiat (n + 1) ja (n * 2) ning oskama neid kahte võrrelda
  • oskama struktuuri liikmetele mälu küsida
  • teadma ja oskama rakendada ohutu programmeerimise tehnikat mälu vabastamisel.
  • teadma kõiki samme mida strdup() funktsioon taustal teeb

Täiendav materjal