PR2ET2: Loendid

Labori materjal

Labori ülesanded

Laboris on 2 ülesannet. Enamjaolt on tegu kordamisülesannetega meenutamaks Programmeerimine 1 ainet, kuid ülesandeid on rikastatud loendite kasutamisega ning mõlema ülesande puhul saame juba kasutada eelmise nädala viitade teemat enda elu lihtsustamiseks.

Ülesanne 1: Failide kategooriad

Selles ülesandes loome tööriista, mis suudab kategoriseerida ja loendada faile vastavalt faili nimes olevale faili laiendile. Näiteks saame leida mitu dokumendifaili asub määratud kaustas ja selle alamkaustades. Ülesande raames loome vaid osa programmist, mis tegeleb laiendite tuvastamise ja loendamisega.

Failide nimede leidmiseks kasutame eelmisel semestril Linuxi laboris õpitut. Kasutades tööriista find  otsime üles kõik failid rekursiivselt ning kasutades toru (pipe) suuname otsingu tulemused enda programmi loendamiseks.

NB! Lahenduse potentsiaali testimiseks on vaja Linuxit. Lihtsaim on testida seda kooli keskkonnast (st kasutades kooliarvutit, Horizongate’i või luues SSH tunneli kooli serveritesse / arvutitesse). 

Nõuded

Loo programm, mis täidab järgmised nõuded

  • Programm võtab vastu teadmata arvu faili nimesid standard sisendvoost ( stdin )
    • Eelnevalt sisendite arvu küsimine ega erilise sisuga sõne kasutamine lugemise peatamiseks pole lubatud
    • Lugemine tuleb peatada ja statistika kuvada pärast seda kui programm saab EOF  (end of file, faili lõpp) signaali.
  • Kategoriseeri failid vastavalt etteantud loetelule laienditest ja gruppidest.
  • Näita mitu faili igasse gruppi kuulus
  • Kategooriate tuvastamiseks koodis pead kasutama loendi andmetüüpi (enum)
  • Üks funktsioon on sulle ette määratud. Funktsioon saab parameetrina kaasa faili laiendi sõnena ning tagastab vastava loendi väärtuse millisesse kategooriasse fail kuulub. Kasuta järgnevat prototüüpi:
    enum FileCategory GetFileType(char *extension);
  • Programm tohib kasutajale anda informatsiooni programmi kohta (nt mida teha tuleb) pärast käivitamist. Programm ei tohi sisendite vahel ekraanile teksti väljastada (st nt kahe faili nime sisestamise vahel).
Kategooriad ja laiendid
  • Arhiivid: zip, rar, 7z, tar, gz
  • Andmed: csv, xls, xlsx, ods
  • Dokumendid: pdf, doc, docx, rtf, odt
  • Programmikood: c, h, cpp, hpp, py
  • Tekst: txt
  • Pildid: jpg, jpeg, png, svg,
  • Muu: Kõik teised failid, millel on laiend, kuid ei olnud eelnevas loetelus.
  • Laiend puudub
Koodi mall

Selleks, et sulle veidi aimdust anda kuidas lugemine ja töötlemine võiks välja näha pakun välja selleks sobiliku malli.

Soovituslikud sammud ülesande lahendamisel
  1. Lisa koodi funktsioon, mis parandab sõne lõpus oleva reavahetuse.
    Näiteks void FixTrailingNewline(char *str);
  2. Lisa koodi funktsioon, mis leiab viimase punkti asukoha sõnas, et hiljem tuvastada faili laiendi algus selle põhjal.
    Näiteks: int GetLastPointPos(char *str);
  3. Lisa koodi failikategooria loend ning loo vastav algväärtustatud loendurite massiiv.
  4. Lisa koodi funktsioon loendurite massiivi väljastamiseks
  5. Lisa koodi funktsioon, mis leiab laiendile vastava loendi väärtuse.
    Näiteks:  enum FileCategory GetFileType(char *extension);
Vihjeid ja hoiatusi
  • Vaata läbi täiendav loendite näide. See on üsna sarnane praegusele ülesandele ja peaks sulle andma hea idee struktuurist ja kasutusest.
  • Ülesandes peaksid ära tundma tükke eelmisest semestrist – nt sõnede esimene ja teine tunnitöö, samuti vanuselise grupeerimise kodutöö.
  • Kui kasutad loendi elementide väärtusteks automaatset numeratsiooni ja lisad soovitud elementide lõppu veel ühe elemendi, siis selle väärtuseks saab elementide arv loendis ilma selle viimase elemendita.

    Sedasi saad lihtsustada näiteks massiivide deklareerimist mille pikkus on vastavate loendurite arv.

  • Kasutades viitade omadusi (nt viidaaritmeetika), saad punkti asukoha põhjal lihtsasti leida punktile järgneva tähemärgi aadressi, mis on samuti sõne ning saab olema olemuselt viit faili laiendile.
  • Lugemistsükli pikkus ei ole määratud. Saad näiteks kasutada funktsiooni fgets()  – see funktsioon tagastab  NULL -viida kui tuvastab faili lõppu tähistava  EOF  (end of file) signaali.
  • Meeldetuletuseks! fgets()  salvestab reavahetuse sümboli sõnesse. Selle pead likvideerima!
  • Kogu programmi sisend tuleb sulle läbi toru sinu programmi stdin standardvoogu.
  • Kiireks testimiseks saad klaviatuurilt saata EOF  signaali kasutades klahvikombinatsiooni  ctrl+d .
Käsitsi testimine

Programmi käsitsi testimiseks käivitame programmi tavapäraselt ja trükime seejärel failide nimesid, vajutades iga nime järel enter klahvi. Kui soovime sisestust lõpetada, vajutame klahvikombinatsiooni  ctrl+d  – see saadab EOF i ehk faili lõpu signaali.

Terviklik testimine

Selleks, et testida su programmi tööd kui terviklikult olen ette valmistanud ühe võrgukettal paikneva kausta. Sinu tulemused peaksid vastama 1:1 näitega.

Failide otsimiseks kasutame sisseehitatud tööriista find, mida kasutatakse kaustade ja failide leidmiseks. Esmalt määrame kust otsime, seejärel tüübiks failid (vältimaks kaustade nimesid) ning trükime välja vaid faili nimetuse ilma asukohata. Tulemused edastatakse toru abil sinu programmi.

Näide on käivitatud käsuga: find ~/M/risto.heinsar/lab_cat/ -type f -printf '%f\n' | ./task1_category

Vihje: Mängi sellega – vaata näiteks kuidas jaotuvad failid sinu P kettal, lisa täiendavaid kategooriaid, failitüüpe.

Varukoopia juhuks kui ülikool võrk maha läheb

Juhul kui sa ei saa demonstreerida ülesande toimivust kuna ülikooli võrgu või arvutitega on probleeme, saad kasutada järgnevat arhiivi. Tegu on täpse koopiaga M kettal asuvatest failidest ja kaustadest.

https://blue.pri.ee/ttu/files/iax0584/andmefailid/2_1_file_cat_directory_structure.zip

Ülesanne 2: Pikkuste teisendaja

Sulle on edastatud andmed rahvusvahelise ettevõtte töötajate liikumisaktiivsuse kohta. Sinu ülesandeks on kõik saadud andmed teisendada ühte kasutaja poolt soovitud mõõtühikusse, seejärel kuvada tulemused ja esmane statistika.

Nõuded
  • Programm võtab käsurealt 2 argumenti
    • Esimene argument on faili nimi
    • Teine argument on soovitud ühik milles väljundit näidata (sobilikud väljundid on  m  meetrites, ft  jalgades ja  km  kilomeetrites)
  • Sisendfail on lihtne tekstifail (antakse esimese käsurea argumendina)
    • Iga rida failis on üks kirje
    • Iga kirje koosneb kahest väljast, mis on tühikuga eraldatud: <distants> <ühik>
    • Distantsid on antud reaalarvuna
    • Ühikud on antud sõnena. Sisendfailis on distantsid antud ainult meetrites või jalgades.
  • Leia ja kuva ühel real algne distants ja distants mis on teisendatud soovitud ühikusse (antud käsurea teise argumendina)
  • Leia ja kuva kogu läbitud distants ja keskmine läbitud distants.
  • Kõik pikkused kuva kahe komakohaga.
  • Ühikud tuleb programmis kodeerida loendina (enum). Soovituslik loendi deklaratsioon on järgmine:
  • Teisenduse konstandid mida saad kasutada oma koodis:
Andmefailid

Selle ülesande testimiseks on kolm andmefaili. Loe täpsemalt Testimine peatüki alt mida tähele panna ning veendu tulemuste korrektsuses.

Lae andmefailid alla siit: https://blue.pri.ee/ttu/files/iax0584/andmefailid/2_2_converter_data.zip

Vihjeid

Selles ülesandes on korraga kolm erinevat ühikut (võiks olla ka rohkem!) ning nende trükkimine sedasi, et kood loetavaks jääb võib muutuda keerukaks. Kaks ideed kuidas seda lahendada.

Valik 1: Loo funktsioon ning kutsu see välja iga kord kui on vaja ühikut trükkida ekraanile. Ühik anna kaasa loendi väärtusena.

Valik 2: Loo funktsioon, mis tagastab viite sõnele, mis omakorda sisaldab sobilikku ühikut. Kuna ühik on kirjutatud funktsioonis konstandina, siis funktsiooni eluiga probleemiks ei osutu. Sellise funktsiooni eelis on see, et saad väga mugavalt printida ühikut keerulisema printf lause sees – nt  printf("%.2f %s\n, distance, ReturnPrintableUnit(unit));

Testimine

Selle programmiga on palju erinevaid asju mis võivad valesti minna. Testi kõiki järgnevaid olukordi!

Testid 1 – 3: Vale argumentide arv

Siin on kombineerituna näha kolm erinevat testi, kõigi nende käigus testime probleeme käivitamisel (vale argumentide arv)

Testid 4, 5: Probleemsed argumendid

Järgneva kahe testi vältel vaatame antud argumentide sisse. Veendume, et ühik on toetatud ning fail eksisteerib.

Test 6: tühi fail

Olukorras kus sisendfail on tühi on meie programmis samuti ohukohti. Veendume, et programm ei jookseks kokku tühja faili puhul!

task2_data1.txt sisu:

Võimalik väljund:

Testid 7 – 9: Teisendused

Selles testis käime läbi kõik võimalikud sisendi ja väljundi kombinatsioonid mis on meil toetatud. Kasutame lihtsat andmefaili, et vastuseid parem jälgida oleks.

task2_data2.txt sisu:

Oodatav väljund:

Test 10: Pikem fail

Selle testi puhul on peamiseks eesmärgiks proovida tulemusi pikema andmefaili korral ja veenduda, et midagi kahe silma vahele ei jäänud.

task2_data3.txt sisu:

Oodatav väljund:

Märkus! Kas panid tähele mida me ei testinud?

Edasijõudnutele: laiendatud teisendaja

Edasijõudnute ülesanne on teise laboriülesande laiendus. Mõtle ülesandest kui pikkuste teisendajast mis väljastab ka lihtlabase statistika

Nõuded
  • Lisa tugi täiendavatele ühikutele
    • Jard (yard, yd)
    • Toll (inch, in)
    • Detsimeetrid (dm, decimeter)
  • Teisendused kuue toetatud ühiku vahel peavad olema toetatud mõlemas suunas (st mõlemad kõik nendest võivad olla nii sisendiks kui väljundiks)
  • Lahenduse disain peab olema lihtsasti laiendatav. St täiendavate ühikute lisamine ei tohiks vajada suuremahulisi koodi ümberkirjutamisi. Teisenduse kood täiendavate ühikute lisamisel ei tohi kasvada eksponentsiaalselt!

Hoiatus: Kuigi antud ülesande oodatav lahendus on lihtsasti hallatav, tekitab see täiendavaid vigu ühikute teisenduskordajate ümardamise tõttu. Ole sellega ettevaatlik suurt täpsust nõudvates probleemides.

Pärast seda tundi peaksid

  • Oskama töötada loenditega, sh
    • Deklareerida uusi loendi tüüpe
    • Deklareerida loendi tüüpi muutujaid
    • Edastada funktsiooni ja tagastada funktsioonist loendeid.

Täiendav materjal

NB! Ettevaatust koodimisstiiliga järgnevate viidete puhul. Mitte ükski neist ei suuda isegi ühel leheküljel sama koodimisstiili reegleid jälgida!