PR2ET6: Makefile ja logimine

Labori materjal

Laboriülesanded

Selles laboris on üks ülesanne, mis on jagatud kahte ossa. Ülesannet laiendab kaks edasijõudnute ülesannet.

NB! Kuigi arendada saad oma lahendused ükskõik mis platvormil, siis üks osa tõestusest vajab Valgrind tööriista kasutamist. Valgrind töötab kontrollitult vaid Linuxil (rakendus olemas ka MacOSil) – vajadusel saad rakenduse tõestuseks üles laadida kooliarvutisse.

Lae alla andmefailid: https://blue.pri.ee/ttu/files/iax0584/andmefailid/6_make_data.zip

Arhiiv sisaldab andmefaile nii baasülesandeks kui edasijõudnute ülesandeks!

Ülesande osa 1 / 2: Andmete lugemine, töötlemine

Esimeses osas on meie eesmärgiks saada programmi andmed sisse ning demonstreerida oma oskusi Makefile’i koostamiseks ja kasutamiseks ning mälus vigade puudumiseks.

Nõuded
  • Loe andmed sisendfailist
    • Andmefaili struktuur
      <õppeaine nimi> <hinnete arv> <hinded>
    • Loetud andmed salvesta struktuurimassiivi. Hinnete jaoks võid teha mõistliku pikkusega massiivi – näiteks max 20 hinnet aine kohta (lähtuvalt näitefaili struktuurist).
  • Kuva ekraanil
    • Õppeaine nimi
    • Õppeaines antud hinded
    • Õppeaine keskmine hinne
  • Hoia andmete lugemine, keskmise leidmine ja väljastus eraldi funktsioonides!
  • Kood peab olema tükeldatud vähemalt kahte koodifaili, millest mõlemal on oma päisefail. Tükeldus peab olema mõistlik, kuid on jäetud sinu otsustada.
  • Kood kompileeri programmiks kasutades Makefile’i
    • Makefile’is peab olema minimaalselt kirjeldatud retsept all , muutuja CFLAGS  ja lipud -Wall -Wextra -Wconversion -g
    • Ülejäänud Makefile’i keerukuse ja ülesehituse võid ise otsustada
  •  Kaitsmisel
    • Näita projekti kompileerimist kasutades Makefile’i
    • Näita programmi väljundit läbi Valgrindi tõestamaks, et puuduvad mäluvead.
Vihje

Hinnete arv aine kohta varieerub – st iga failis olev andmerida võib olla erineva pikkusega. Seetõttu andmefaili võimalik lugeda ühe ühte fscanf()  funktsiooni väljakutsega!

Lugemine on vaja teha pesastatud tsüklitega, kus

  • Välimine tsükkel loeb õppeaine nime ning hinnete arvu
  • Vastavalt välimisest tsüklist saadud hinnete arvule määratakse ära sisemise tsükli korduste arv, lugemaks sisse õppeaines antud hinded. Ära unusta sisemise tsükli fscanf()  funktsiooni tagastust kontrollida!
Testimine

Näide võimalikust koodi struktuurist.

NB! Failide nimed ei ole ette määratud, tegu on lihtsalt näidisega. Samuti piisab vaid ühest andmefailist ning see ei pea olema eraldi kaustas.

NB! Järgnevas näites ei ole kajastatud valgrindi väljundit! Ära unusta testida oma programmi korrektsust valgrindiga!

Ülesande osa 2 / 2: Logimine

Selle osa raames tuleb sul lisada oma programmi logimine.

Nõuded
  • Lisa oma programmi logimine
    • Üks logi rea kohta. Logi ei tohi olla kaherealine!
    • Iga logi rida algab ajatempliga. Ajatempel peab sisaldama kuupäeva (päev, kuu, aasta) ja kellaaega (tunnid, minutid, sekundid)
  • Programmi järgmine käivitus ei tohi kustutada eelneva käivituse logi
  • Logitavad sündmused
    • Programmi käivitamine ja sulgemine
    • Sisendfaili avamise seisund (edukas / ebaõnnestunud)
    • Faili lugemine lõpetatud. Logis kuva loetud ridade arv!
    • Faili lugemine katkestatud kuna massiivi maksimaalne piir on ületatud (maksimaalne piir kuvatakse logis).  NB! Sul on struktuuride massiiv ja struktuuri liikmena hinnete massiiv!
    • Viga aine keskmise hinde arvutamisel.
  • Logi terviklikkus peab olema garanteeritud ka programmi kokkujooksu korral
    • Võimalus 1: Väljundpuhvrist on võimalik sunniga andmed faili kirjutada kasutades funktsiooni fflush()
    • Võimalus 2: Sulge logifail pärast kirjutamist – faili sulgemise järel kirjutatakse puhvris olevad andmed faili.
  • Logifaili avamise ebaõnnestumisel peab programm jätkama tööd, mitte väljuma! Teavita kasutajat logimise ebaõnnestumisest.
Vihjeid
  • Valmista ette logitav sõne enne logimise funktsiooni väljakutsumist! Ära koorma logimise funktsiooni üle parameetritega. Sõne ettevalmistamiseks on hea funktsioon snprintf()
  • Logifunktsiooni lihtsustamiseks on soovitatav mitte failiviita ega nime sellele kaasa anda. Võimalike lahendusi:
    • Ava ja sulge fail logifunktsioonis järjest
    • See on üks võimalikest eranditest globaalmuutujale – soovi korral võid teha failiviida logifailile globaalmuutujana. (See ei ole hea lahendus, kuid aktsepteeritav – parem võimalus on kirjutatud lahti edasijõudnute ülesandena).
  • Näiteks võiks logimise väljakutsumine välja näha nii:
    Logger("Program started");

Edasijõudnute ülesanne 1: Logimise teek

Selle ülesande raames lood sa endale logimise teegi. Vihje: seda saad ära kasutada kodutöö 2 juures!

Nõuded
  • Lisa programmile eraldi .c ja .h fail ja tõsta sinna logimine
  • Lisa 4 logimise taset – OFF, ERROR, WARNING ja INFO – need on loendi tüüpi (enum).
    • Iga logifaili rea juures on kirjeldatud selle logi tase.
    • Logi kirjutatakse faili vaid siis, kui määratud tase seda lubab. Näiteks:
      INFO taseme korral kirjutatakse kõigi tasemete logid;
      WARNING taseme korral kirjutatakse ainult WARNING ja ERROR tasemega logid;
      ERROR taseme korral kirjutatakse ainult ERROR tasemega logid;
      OFF korral logisid ei kirjutata;
  • Iga kutse logi kirjutamiseks peab nüüd sisaldama selle logi olulisuse taset (ERROR, WARNING või INFO)
    Näiteks: Logger(LOG_INFO, "Program started");
  • Teek peab toetama logi väljundfaili nime andmist
    Näiteks: LoggerSetOutputName("log.txt");
  • Teek peab toetama programmi logitaseme sättimist
    Näiteks: LoggerSetLoggingLevel(LOG_INFO);
  • Logimise seadistused tuleb hoida logimise teegi sisemiselt. Selleks on logifaili nimi ja logi tase (võid ka lisada täiendavaid). Need hoiusta logi koodifailis globaalmuutujatena.
  • Logifaili seadistustel peavad olema vaikeväärtused – näiteks kui kasutaja unustab või ei soovi neid seadistada, siis programm ei läheks katki.
  • Iga logi peab sisaldama kellaaega nii nagu oli kirjeldatud ülesande teises osas.

Edasijõudnute ülesanne 2: Lihtsustatud CSV failist lugemine

Selle edasijõudnute ülesande eesmärgiks on võimaldada mitmest sõnast koosnevaid õppeainete nimesid.

Nõuded
  • Kasuta sisendfailina CSV versiooni sisendfailist
  • Andmeväljad on üksteisest eraldatud komaga. Andmeväljad ise komasid ei sisalda.
Lahenduskäik

NB! Kasutame lihtsustatud metoodikat CSV lugemiseks. Sellega ei ole võimalik lugeda ükskõik missugust CSV faili! St kui andmeväli võib sisaldada ka komasid, siis seda metoodikat kasutada ei saa!

Kui vajad täielikku CSV tuge, kasuta kas vastavat teeki (nt libcsv) või kirjuta näiteks olekumasina-põhine töötlemine (loed tähemärk-haaval ja otsustad mida teha lähtuvalt loetud tähemärgist ja hetkeolekust olekumasinas)


scanf() funktsioonide perekond võimaldab lisaks andmeformaadi kirjeldamisele ka kirjeldada oodatavat sisendit ning lihtsamaid regulaaravaldisi.

Näiteks lugemaks kasutajalt kellaaega, saame kasutada formaati scanf("%d:%d", &hours, &minutes);  – sellisel juhul saab kasutaja sisestada kellaaja formaadiga 14:35 . Muutuja hours  saab väärtuseks 14 ja minutes  väärtuseks 35 . Kui aga kasutaja sisestab 14 35 , siis hours  saab ikka väärtuseks 14 , kuid kuna tühik polnud oodatud formaat, siis sealt edasi ei loeta ning minutes  jääb väärtustamata.

Lähtuvalt sellest teadmisest saame koostada faili lugemiseks formaadi fscanf(fp, "%[^,],%d", ...)  . Asenda failiviida nimi enda kasutatud viidaga ning kolme punkti asemele pane oma muutujad kuhu andmeid salvestad.

  • Esimene väli loetakse tekstina kuniks komani (koma ei loeta). See salvestatakse tekstimassiivi (õppeaine nimi)
  • Seejärel loetakse puhvrist välja koma (ja visatakse ära)
  • Siis loetakse sisse üks täisarv (hinnete arv aines)

Sedasi saad loetud esimesed 2 välja. Edasi pead juba formaadi koostama hinnete lugemiseks (ära komasid unusta!).

Pärast seda tundi peaksid

  • Teadma erinevate ehitussüsteemide kohta
  • Oskama koostada lihtsat Makefile’i
    • Teadma kuidas deklareerida muutujaid ja neid kasutada
    • Teadma kuidas koostada retsepti, sh mitut retsepti ühes failis
    • Teadma mis retsepti sees käib
    • Teadma varjatud reeglitest ja oskama neid vajadusel kasutada
  • Oskama kasutada Makefile’i programmi kompileerimiseks
  • Oskama kasutada valgrindi programmist vigade leidmiseks ja korrektsuse kontrollimiseks
  • Oskama programmi siseselt hetke kellaaega leida ning seda kujundada
  • Teadma logimise põhitõdesid ja olulisust

Täiendav materjal