Autori risto postitused

PR2ET5: Qsort ja tükeldus

Labori materjal

Laboriülesanded

Selles laboris on kaks ülesannet.

  • Esimene ülesanne koosneb kahest baasosast ja edasijõudnute lisast.
  • Teine ülesanne koosneb baasülesandest ja edasijõudnute lisast.

Ülesanne 1: Quicksort

Selle ülesande eesmärk on harjutada qsort()  funktsiooni kasutamist ning koodi tükeldamist erinevate koodifailide vahel, sealjuures alustad oma esimese kergesti lisatava teegifaili loomist. Aluskoodis on juba koodi tükeldus failidesse sinu eest juba tehtud.

Lae alla aluskood: https://blue.pri.ee/ttu/files/iax0584/aluskoodid/5_1_qsort_task_basecode.zip

NB! Aluskood sisaldab tükke mõlema baasosa ja edasijõudnute osa jaoks!

Nõuded
  • Realiseeri vajalikud funktsioonid mis on ette antud sulle erinevates päisefailides prototüüpidena. Funktsiooni realisatsioon peab olema päisefailiga samanimelises .c koodifailis
  • Kutsu välja vajalikud funktsioonid andmete sorteerimiseks ja ekraanile kuvamiseks main funktsiooni switch lausest.
  • Kompileeri programm kokku mitmest koodifailist – vastavalt struktuurile mis oli antud aluskoodis. Kasuta kompileerimiseks käsurida (võid kasutada ka Makefile’i kui oskad).
Ülesande hinnatavad alamosad

Esimese hinnatava osa jaoks peavad töötama menüüst valikud 1 ja 2. Selle sooritamiseks pead sa

  • Realiseerima qsort võrdlusfunktsioonid täisarvudest ja murdarvudest koosneva massiivi jaoks
  • Kutsuma välja qsort funktsiooni mõlema eelnimetatud massiivi sorteerimiseks ning väljatrükiks menüüs

Teise hinnatava osa jaoks peavad töötama menüüst valikud 3 ja 4. Selle sooritamiseks pead sa

  • Realiseerima qsort võrdlusfunktsioonid struktuurimassiivi sorteerimiseks eesnime ja töösuhte pikkuse järgi
  • Realiseerima struktuurimassiivi väljatrüki funktsiooni.
  • Kutsuma välja qsort funktsiooni struktuurimassiivi sorteerimiseks vastavalt menüü valikule ning seejärel massiivi väljatrüki funktsiooni

Edasijõudnute ülesande hinnatava osa jaoks peab töötama menüüst valikud 5. Selle sooritamiseks pead sa

  • Realiseerima qsort võrdlusfunktsioonid struktuurimassiivi sorteerimiseks perenime järgi. Kui perenimed on samad, tuleb teha täiendav otsus sorteerimiseks eesnime alusel.
  • Kutsuma välja qsort funktsiooni struktuurimassiivi sorteerimiseks vastavalt menüü valikule ning seejärel massiivi väljatrüki funktsiooni
  • Kutsuma välja qsort funktsiooni struktuurimassiivi sorteerimiseks vastavalt menüü valikule ning seejärel massiivi väljatrüki funktsiooni
Testimine

Järgnev näide sisaldab kõiki kolme hinnatavat osa (1 ja 2 baasosa ning edasijõudnute osa)

Ava mind väljundi nägemiseks
 

Ülesanne 2: Teekide kasutamine (covid-data)

Selles ülesandes tutvume esimest välise teegi (libcurl) lisamisest oma programmi, mille abil on võimalik näiteks kasutada internetis olevaid APIsid ja faile internetist alla laadida. Kasutame neid Eesti riigi avaandmete alla laadimiseks. Jätkame programmi tükeldamise harjutamisega.

NB! Ülesande lahendamine on kordades lihtsam UNIX põhistel süsteemidel (Nt Linux). Windowsil ülesande lahendamiseks on vaja teha täiendav seadistus ning muuta osa ette antud lähtekoodist!

Lae alla aluskood: https://blue.pri.ee/ttu/files/iax0584/aluskoodid/5_2_covid_starter.zip

Nõuded
  • Kasuta põhjana sulle antud aluskoodi
  • Lae alla Eesti Covid-19 avaandmed (ette antud aluskoodis)
    NB! Avaandmeid uuendatakse korra nädalas! 
  • Avaandmete spetsifikatsioon
  • Kuva viimase 14 päeva kinnitatud nakatumised (päev ja nakatumiste arv)
  • Kuva top10 kõige suurema nakatumiste arvuga päeva (päev ja nakatunute arv)
  • Minimaalselt peab olema kood tükeldatud kolme koodi ja päisefaili
    • file_helper.c  ja file_helper.h  on faili allalaadimiseks ja ettevalmistuseks  (ette antud, muudatusi pole vaja teha)
    • data_processor.c  ja data_processor.h  on failist andmete lugemiseks ja töötlemiseks
    • main.c  ja main.h  on programmi töövoo juhtimiseks ja üldisteks makroteks
    • Soovi korral võid näiteks faili lugemise lüüa lahku andmete töötlemisest
  • Kompileeri kõik koodifailid kokku kas käsurealt või kasutades Makefile’i
Soovituslik töövoog
  1. Tutvu etteantud koodifaiide struktuuri ja sisuga
  2. Kommenteeri sisse enda eelistatud andmefaili formaat (kas tühikute või komadega eraldatud andmed)
  3. Kompileeri ja proovi kas allalaadimine töötab. Kompileerimiseks on vajalik lipp -lcurl
  4. Lisa main.h  faili struktuuri kirjeldus andmete mälus hoidmiseks ning teised vajalikud makrod suurustele
    Vihje: sul ei ole vaja kõike failist loetut mälus hoida! Vali välja vaid olulised väljad!
  5. Kodeeri data_process.c  faili andmefailist andmete lugemise funktsioon. Lisa selle funktsiooni prototüüp data_process.h  päisefaili ning väljakutse main funktsiooni.
    NB! Kas märkasid, et CSV failil oli esimene rida päis!?
    Vihje: konkreetse andmevälja ignoreerimiseks saad scanf  funktsioonis kasutada formaati %*s  – tärn tähistab,  andmeid sellele formaadile vastavale osale ei salvestata. St ignoreeritakse kõike kuni järgmise tühiku või reavahetuseni. Kui kasutad tärni formaadis ei tohi selle kohta muutujat scanf  parameetrina anda.
    Kompileeri ja testi kas andmed loetakse edukalt sisse
  6. Loo funktsioon andmete väljatrükiks, et kuvada viimase 14 päeva statistika.
    Vihje: Kasuta ära oma teadmist massiividest ja viida-aritmeetikast mida rakendasime esimesel nädalal viitade tunnis (ülesanne 1, osa 2)! Nii jääb väljatrüki funktsioon lihtsaks ja korduvkasutatavaks järgmise punkti jaoks.
  7. Loo qsort  jaoks võrdlusfunktsioon ning kutsu qsort  välja andmete sorteerimiseks. Kuva top 10 kõrgeima nakatunute arvuga päeva.
    Vihje: Kui kasutasid eelmise punkti juures viida-aritmeetika ja jätsid väljatrüki funktsiooni lihtsaks, siis nüüd saad seda sama funktsiooni ka siin ära kasutada!
Testimine

NB! Väljundis on koos baasülesande ja edasijõudnute ülesande lahendused!

Edasijõudnute ülesanne
  • Leia nakatumiste arv viimase 7 päeva jooksu
  • Leia nakatumiste arv sellele eelneva 7 päeva jooksul
  • Väljasta perioodi vahemikud ja nakatunute koguarv neil perioodidel
  • Leia ja kuva kas nakatumine kahe võrreldava perioodi vahel on vähenenud, kasvanud või jäänud samaks. Näita protsenti kahe komakohaga.

Vihje: Baasülesande raames sorteerimise andmemassiivi terviklikult ära ja neid andmeid me kasutada ei saa ilma uuesti sorteerimata. Küll aga saame enne sorteerimist teha osalise koopia andmetest. Koopia saad teha (enne kui qsort välja kutsutakse) kasutades funktsiooni memcpy() . Uuri parameetreid ja meenuta viida-aritmeetikat alguspunkti määramiseks!

MS Windows

Antud ülesannet on võimalik lahendada ka Windowsil, kuid selleks tuleb teha mõned täiendavad liigutused. Sammud on testitud ja töötasid kevadel 2022 kasutades chocolatey kaudu installeeritud 64 bitist MinGW-d (see oli osa lihtsast tarkvara paigaldamise juhendist Windowsil kasutades käsurida). Väljavõte eelmise aasta vestlusest, kus sammud kirja said (inglise keeles)

1. Install libcurl on Windows. Uses chocolatey package manager

choco install curl

2. Make the library (dll file) available to the compiled program. Copy libcurl-x64.dll from libcurl installation directory to your program directory (assumes 64-bit compiler).

3. You need to download CA certificate so cURL can verify the certificate on the opendata website https://curl.se/ca/cacert.pem.

4. You need to specify the certificate authority file location to the code. Add this to the setup of the download in the file_helper.c, replacing the path\\to\\file with the path to the downloaded .pem file.

curl_easy_setopt(curl_handle, CURLOPT_CAINFO, "path\\to\\file");

5. You need to rewrite the check if a file is already downloaded because that uses POSIX library available on UNIX systems – unistd.h. You should rewrite it with windows solution of that. Haven’t tested, but you’ll likely find the function BOOL FileExists(LPCTSTR szPath) in the library io.h. You may need to add additional Windows-specific libraries.

6. You can only download as CSV with the code provided. To download space delimited, you need to rewrite the ReplaceChars function. Easy option would be to open up a second file pointer for writing to a different file and remove the fseek, Simplest would be to do getchar -> putchar with a check in between for commas to be replaced with spaces.

7. You need to add -I and -L flags to your compiler command line arguments. Mine were:

-I C:\ProgramData\chocolatey\lib\curl\tools\curl-7.81.0-win64-mingw\include\ -L C:\ProgramData\chocolatey\lib\curl\tools\curl-7.81.0-win64-mingw\lib\

Pärast seda tundi peaksid

  • Oskama tükeldada oma programmi mitme koodifaili vahel mitmest koodifailist koosnevat programmi kompileerida
  • Oskama kasutada qsort funktsiooni
  • Mõistma qsort funktsiooni võrdlusfunktsiooni nõudeid ning suutma kirjutada võrdlusfunktsiooni lihtsatele massiividele ning ka struktuurimassiividele
  • Teadma viitade eksisteerimisest funktsioonidele ning oskama funktsiooni edastada viita teisele funktsioonile
  • Teadma üldistatult samme mis on vajalikud kolmandate osapoolte teekide kasutamiseks ning oskama neid oma programmi kompileerida

Täiendav materjal

PR2ET4: Struktuurid 2 ja lihtne päis

Labori materjal

Laboriülesanded

Selleks laboriks on ülesanne mis on jaotatud kahte ossa.

Laboriülesande 1. osa: Seostatud andmete väljastamine

Selles osas trükime välja failidest loetud andmed. Selleks on oluline õigel hetkel teha vajalikud seostamised kahe struktuuri vahel.

Andmefailid

Andmed on sulle antud kahes eraldi failis, mille kirjeldamiseks kasutame olemi-suhte diagrammi (ERD ehk entity-relationship diagram).

NB! Selliseid suhteid näidatakse sageli ka UMLi klassidiagrammina. Vaata all viidet selle kohta!

Olemi-suhte diagrammi kardinaalsus

  • Ühel isikul võib olla 0 või enam sõidukit
  • Iga sõiduk peab kuuluma täpselt ühele isikule

Andmed kahes failis on seostatud Eesti isikukoodi (person_id) abil.

Lae andmefailid alla siit: https://blue.pri.ee/ttu/files/iax0584/andmefailid/4_data.zip

Nõuded
  • Kasuta programmi programmis päisefaili. Paiguta sinna struktuuride deklaratsioonid, makrod ja funktsioonide prototüübid, vajadusel ka loendid.
  • Loe kahest antud failist andmed eraldiseisvatesse struktuurimassiividesse.
    • Väldi keerukaid lahendusi (pesastatud struktuurid või struktuuriviidad) selle laboriülesande lahendamisel.
    • Isikukoodi pead hoiustama 64-bitise täisarvuna. Sedasi vähendad protsessoritsüklite arvu mis kulub väljade võrdlemiseks!
      Kasuta inttypes.h !
  • Harjuta viidaaritmeetikat
    • Kasuta nooleoperaatorit (->) struktuuri liikmete poole pöördumiseks
    • Väldi nurksulgude [] kasutamist massiivide indekseerimisel.
  • Sorteeri isikute andmed eesnime alusel tähestikulises järjekorras kasvavalt.
  • Trüki välja isikuandmed, millele järgnevad kõik nendega seotud sõidukid.
    • Omaniku andmed tohid trükkida ühekordselt.
    • Omaniku info järel loetle kõik nendega seotud sõidukid
    • Kui isikul puuduvad sõidukid, anna sellekohane teavitus.
Soovituslikud funktsioonid

NB! Tegu on soovitusliku loeteluga. Sinu loodavad funktsioonid ning nende parameetrid võivad sellest erineda.

Testimine

Järgnev on ülesande esimese osa oodatav väljund

Laboriülesande 2. osa: Maksude arvutamine

Teises osas kirjutame laienduse esimesele osale. Kõik esimeses osas olnud nõuded kehtivad ka siin.

Nõuded
  • Leia ja kuva palju iga omanik makse maksma peab
    • Kuvada tuleb nii summa kui protsendina sissetulekust
    • Lisa hoiatus kui maksud ületavad 10% isiku aastasest sissetulekust.
    • Väljasta veateade kui inimesel puuduvad sissetuleku kohta andmed.
    • NB! Meenuta, et funktsioonid peaksid vaid ühte asja tegema. Ära pane arvutamist samase funktsiooni kus andmeid väljastad või faile loed! Tee eraldi funktsioon maksude leidmiseks.
  • Vihje: Lisa struktuuri täiendav liige või liikmed, et saaksid hoiustada ja kuvada maksuandmeid. Struktuuri liikmed ei pea olema 1:1 vastavuses sellega mis on hoiustatud failis, täiendavate väljade lisamine või isegi andmete töötlemine ja teises formaadis hoidmine mälus on OK.
Soovituslikud funktsioonid

NB! Tegu on soovitusliku loeteluga. Sinu loodavad funktsioonid ning nende parameetrid võivad sellest erineda.

Testimine

Järgnev on ülesande teise osa oodatav väljund

Pärast seda tundi peaksid

  • Oskama luua ja seostada päisefaili oma koodifailiga
  • Teadma mida pannakse ja mida ei panda päisefaili sisse
  • Teadma tüüpilisi kasutusjuhte päisefailidesse
  • Teadma erinevaid mis vahet on noolsulgudel ja ümarsulgudel päisefaili lisamisel ning kust siis neid faile otsima hakatakse
  • Teadma kuidas makrotena luua tingimuslauseid eelprotsessori jaoks
  • Teadma miks on vajalikud ning oskama kasutada kaitseid päisefailidel
  • Oskama silumislauseid koodi põimida erinevatel viisidel
  • Oskama algväärtustada struktuure
  • Oskama struktuure pesastada (st ühe struktuuri liikmeks on teine struktuur või struktuuri viit)
  • Oskama struktuure tagastada
  • Oskama kasutada struktuuri ligipääsuoperaatorina noolt ning teadma millal seda teha tuleb
  • Oskama viidaaritmeetikat kasutada struktuurimassiivide peal
  • Oskama lugeda lihtsamaid ERD diagramme ja teadma, et neid kasutatakse andmemudelite modelleerimiseks.
  • Teadma, et UMLis on ka olemas klassidiagrammid ning klassidiagramme kasutatakse andmemudelite modelleerimiseks.

Täiendav materjal

PR2ET3: Struktuurid

Labori materjal

Laboris lahendatakse kommenteeritult koos läbi failist struktuuridesse lugemise näide. Neile kes ei osale laboris on see avaldatud koodinäitena: Failist struktuurimassiivi lugemise näide

Laboriülesanded

Selles laboris on üks ülesanne, millele lisandub 4 edasijõudnute ülesannet.

Ülesanne [W03-1]: töötajate otsing

Selles programmis matkime töötajate andmebaasi, kust on võimalik filtreerida välja töötajate andmeid vastavalt etteantud otsinguparameetrile.

Andmefail

Lae alla testandmed järgnevalt lingilt: https://blue.pri.ee/ttu/files/iax0584/andmefailid/3_data_short.zip

Andmefail koosneb juhugeneraatoriga loodud andmetest.

Nõuded

  • Loe failist ettevõtte töötajate andmed
    • Failis on iga rea kohta üks kirje
    • Iga andmeväli on eraldatud tühikuga. Andmeväljad on ühesõnalised.
    • Andmete struktuur failis
      <eID> <first_name> <last_name> <city>
  • Programmis tuleb andmeid hoida struktuuridest koosnevas massiivis.
  • Programm peab töötama olukorras kus andmete täpne arv pole teada ning see võib ajas muutuda (näiteks mõni rida lisatakse või kustutatakse).
    • Loo programmile mõistlik limiit ning veendu, et sellest üle ei mindaks!
  • Luba programmi kasutajal teostada otsingut linna nime järgi
    • Programm väljastab kõik töötajad, kes sisestatud linnas elavad
    • Näita mitu vastet mitmest leiti (nt [0 / 91])
    • Otsingut peab saama sooritada korduvalt ilma programmist väljumata
    • Baasülesandes väljasta kõik andmed – isikukood, perenimi, eesnimi, linn
  • Kasutajal peab olema võimalus programm sulgeda, loo selle jaoks eraldi võimekus (näiteks sisestades kindel käsk)
  • Korduv faili lugemine programmi sees ei ole lubatud.
  • Struktuuri sisu ei pea olema üks-ühele faili sisuga! Väljade lisamine on kasulik eelkõige lisaülesannete lahendamisel.

Programmi näidisväljund

Järgnevalt on pakutud kaks väljundi näidist. Esimeses näidises kuvatud tulemused vastavad baasülesande nõuetele, teises näidises kuvatav väljund sisaldab kõigi nelja lisaülesande sisu.

Kliki mind, et näha baasülesande näidet
Kliki mind, et näha lisaülesande näidet

Lisaülesanne 1 [W03-2]: struktuuride sorteerimine

Nõuded

  • Leitud töötajate loetelu peab olema sorteeritud perekonnanime järgi tähestikulises järjekorras kasvavalt.
  • Väljastuse nime formaat peab olema perenimi, eesnimi

Lisaülesanne 2 [W03-3]: linnade nimistu

Nõuded

  • Kuva kasutajale kõik failis olevad linnad
  • Linnade nimistu peab olema järjestatud tähestiku alusel
  • Linnade nimekiri koostatakse programmi poolt töö ajal, vastavalt sisendfailis esinevatele linna nimedele
  • Kasutaja peab saama linnade nimekirja kuvada sisestades selleks vastava käsu. Käsk tuleb lisada menüüsse
  • Linnade nimekirja peab saama kuvada korduvalt
  • Linnade nimekirja tohib koostada programmi töö vältel vaid ühe korra.

Lisaülesanne 3 [W03-4]:  Mugavam otsing

Nõuded

  • Otsing ei tohi olla tõstutundlik. Näiteks otsides otsides linna TALLINN  või tallinn , tuleb kuvada kõik töötajad, kes elavad Tallinnas.
  • Otsing peab toetama osalist vastet. Näiteks otsides all  leitakse nii need, kes elavad Kallastel, kui ka need, kes elavad Tallinnas.
  • Mõlemad peavad töötama ka korraga. St eelnev tulemus peab olema leitav ka otsides ALL  või aLL

Lisaülesanne 4 [W03-5]: Töödeldud isikukood

Nõuded

  • Ära kuva vastuste hulgas enam isikukoodi
  • Kuva töötaja sünniaeg formaadiga d. MMMM yyyy

Isikukoodi formaadi kohta saad lugeda: https://www.riigiteataja.ee/akt/114022017005

Vajuta mind, et näha selgitusi kuupäeva ja kellaaja vormingu kohta

m – Minutid vahemikus 0 – 59.
mm – Minutid vahemikus 00 – 59. Minutitele 0 – 9 lisatakse ette number null.

h – Tunnid vahemikus 1 – 12.
hh – Tunnid vahemikus 01 to 12. Tundidele 1 – 9 lisatakse ette number null.
H – Tunnid vahemikus 0 – 23
HH – Tunnid vahemikus 00 – 23. Tundidele 0 . 9 lisatakse ette number null.

d – Päevad vahemikus 1 – 31
dd – Päevad vahemikus 01 – 31. Päevadele 1 – 9 lisatakse ette number null.
ddd – Päevad lühinimega ( E / Mon; T / Tue; K / Wed; …)
dddd – Päevad täispika nimega (esmaspäev / Monday; teisipäev / Tuesday; kolmapäev / Wednesday; …)

M – Kuud vahemikus 1 – 12
MM – Kuud vahemikus 01 – 12. Kuudele 1 – 9 lisatakse ette number null.
MMM – Kuu lühinimi (jaan / Jan; veebr / Feb; märts / Mar; apr / Apr; …)
MMMM – Kuu täispika nimega (jaanuar / January; veebruar / February; Märts / March; …)

y – Aasta vahemikus 0 – 99
yy – Aasta vahemikus 00 – 99
yyy – Aasta, minimaalselt kolme numbriga (1 -> 001; 15 -> 015; 145 -> 145; 1949 -> 1949)
yyyy – Aasta nelja numbriga

Pärast seda tundi peaksid

  • Teadma kuidas deklareerida uusi struktuure – st uus andmetüüp, milleks on struktuur
  • Oskama valida struktuuri liikmeid
  • Teadma mis on struktuuri polsterdamine ja joondamine ning kuidas see mõjutab struktuuri suurust mälus
  • Teadma mis mõjutab struktuuri suurust
  • Teadma millised operaatorid on kasutusel struktuuri liikmete poole pöördumiseks ja oskama kasutama punkt-operaatorit
  • Teadma kuidas luua struktuuridest koosnevat massiivi ja lugeda andmeid failist struktuurimassiivi
  • Teadma kuidas omistada terviklikku struktuuri
  • Teadma kuidas defineerida andmetüüpe ümber, andes neile uue nime (typedef)

Täiendav materjal

PR2ET2: Loendid

Labori materjal

Labori ülesanded

Laboris on kaks ü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 [W02-1]: Failide kategooriad

Selles ülesandes loome tööriista, mis suudab kategoriseerida ja loendada faile vastavalt faili nime lõpus paiknevale 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 Programmeerimine 1 Linuxi laboris õpitut. Kasutades tööriista find  otsime rekursiivselt üles kõik failid ning kasutades toru (pipe) kahe rakenduse standard sisend-väljundvoogude sidumiseks suuname otsingu tulemused enda loodud programmi analüüsimiseks.

NB! Lahenduse potentsiaali testimiseks on vaja Bash keskkonda. Lihtsaim on testida seda kooli keskkonnast (st kasutades kooliarvutit, kaughaldust kooliarvutisse 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 faililaiendile etteantud laiendite loetelu ja kategooriate põhjal. Loetelu leiad kohe pärast nõudeid.
  • Näita mitu faili igasse kategooriasse kuulub
  • Kategooriate tuvastamiseks koodis pead kasutama loendi andmetüüpi (enum)
  • Üks funktsioon on juba 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 veidi lihtsustada kuidas ja mis järjekorras lugemine ja töötlemine võiks välja näha pakun välja ülesande lahendamiseks 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õnes, et seejärel selle alusel määrata faili laiendi alguse (esimese tähe) mäluaadress.
    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
    Näiteks  void PrintFileCntPerCategory(int *categoryCounters, int numOfCategories);
  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 (lehekülje alguses viide koodinäidetele). 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. Kasutades laboriarvutit või kaughaldust saad kävitada käsu 1:1. Kui kasutad enda arvutit, lae alla testimiseks mõeldud arhiiv ja määra otsingu asukohaks lahtipakitud arhiivi asukoht. Sinu tulemused peaksid vastama 1:1 näitega.

Faili nimede saamiseks kasutame sisseehitatud tööriista find , mida kasutatakse kaustade ja failide otsimiseks. Esmalt määrame kust otsime, seejärel tüübiks failid (vältimaks kaustade nimesid) ning trükime välja vaid faili nimetuse ilma asukohata. find väljastab otsingutulemused oma standard väljundvoogu ( stdout ), mille suuname ümber kasutades toru (pipe) meie loodud rakenduse standard sisendvoogu ( stdin ).

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 testfailidest

Juhul kui sa ei saa demonstreerida ülesande toimivust võrguprobleemide tõttu või soovid testida seda enda arvutil, saad selleks 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 [W02-2]: Pikkuste teisendaja

Sulle on edastatud andmed rahvusvahelise ettevõtte töötajate liikumisaktiivsuse kohta. Andmefailid leiad kohe pärast nõuete peatükki. Sinu ülesandeks on teisendada erinevatest pikkusühikutest koosnevas failis olevad andmed teisendada ühte, kasutaja poolt määratud, mõõtühikusse. Selle käigus tuleb näidata nii teisenduse tulemused kui ka lihtne statistika kogu faili kohta.

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:
  • Soovitusi funktsiooni kujude kohta leiad vihjete alt
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
Vihje 1: Teisenduse funktsioon

Meenuta, et funktsioonid pidid olema lühikesed ja tegema vaid ühte asja ning seda hästi. Teisendamise funktsioon peaks tegelema ainult pikkuse teisendamisega ühest andmetüübist teise, mitte üritama samal ajal ka teisendada sõnest andmetüüpi. Edasta teisenduse funktsiooni juba dekodeeritud andmetüübid koos teisendatava pikkusega.

Näiteks võiks kaaluda järgneivad ideid funktsiooni kujule.

Vihje 2: Pikkusühiku dekodeerimine

Nii failist tulevad sisendühikud kui käsurea argumendina tulev väljundühik on mõlemad sõne kujul. Seega selle teisendamiseks piisab ühest funktsioonist, mis tagastab tüübi.

Nt: enum Unit GetDistanceUnitType(char *unit);

Vihje 3: Ühikute väljastamine teksti kujul

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?

Lisaülesanne [W02-3]: laiendatud teisendaja

Lisaülesandeks 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
    • Mõistma kuidas käib automaatne numbrite andmine loendi elementidele
    • 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!

PR2ET1: Viidad

Labori materjal

Meeldetuletuseks koodimisstiilist

  • Su kood peaks olema lihtsasti loetav
  • Stiil peab üle kõigi koodifailide olema samasugune
  • Eelista lihtsust – lihtsad lühikesed funktsioonid, arusaadavad algoritmid, väldi keerukuse tekitamist koodi “uhkemaks” tegemiseks
  • Kommenteeri oma koodi!
  • Planeeri oma kood modulaarsena (lühikesed lihtsad funktsioonid, mis on universaalsed ja mida saad kergesti kopeerida ühest programmist teise, sh tulevikus ka eksamil või kontrolltööl).
  • Kasuta kiireid algoritme ja andmestruktuure (minimaalselt seni õpitute hulgast)
  • Väldi globaalmuutujaid (selles aines näeme ka olukordi kus globaalmuutujad on OK)

Ülesanded

Selles laboris on kaks ülesannet. Teine ülesanne on tükeldatud kahte ossa. Edasijõudnute ülesanne on ehitatud teise ülesande põhjal.

Ülesanne 1 [W01-1]: viidad ja muutujad

Tegu on klassikalise muutuja väärtuse vahetamise ülesandega.

Lae alla ülesande aluskood: https://blue.pri.ee/ttu/files/iax0584/aluskoodid/t1_swap_template.c

Nõuded
  • Ehita oma lahendus aluskoodile
  • Aluskoodis on koodilõigud, mille lõpetamine on jäetud sinu ülesandeks. Need on märgitud koodis kommentaariga TODO .
  • Loo 2 funktsiooni vastavalt aluskoodis olevatele kommentaaridele. Ühest neist tuleb väärtused sisse lugeda ja teises nende väärtused omavahel vahetada. Mõlemate puhul kasuta viitade võimalusi.
  • Trüki välja muutujate mäluaadressid kolmes erinevas kohas
    • Esiteks main funktsioonis, näita kus kohas väärtused asuvad mälus
    • Teiseks lugemise funktsioonis – näita kuhu kohta loetavad väärtused salvestatakse
    • Kolmandaks vahetamise funktsioonis – näita kus asuvad need väärtused mida parasjagu vahetad.
  • Kaitsmisel selgita mis on kuvatud väärtuste puhul oluline!
Testimine

Ülesanne 2 osa 1 [W01-2]: Viidad ja massiivid

Teises ülesandes vaatleme täisarvudest koosneva massiivi liikmete mäluaadresse ja kasutame viitade võimalusi, et funktsioonist mitu väärtust korraga välja saada. Samuti harjutame viidaaritmeetika kasutamist.

Nõuded

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

  • Selles ülesandes ei tohi sa kasutada nurksulge [] massiivi indekseerimiseks, vaid pead rakendama viida-aritmeetikat. Nurgsulge tohib kasutada vaid massiivi deklareerimiseks.
  • Kogu selle ülesande vältel ei tohi sa kasutada nurksulge massiivide indekseerimiseks. Kasutada tuleb viida-aritmeetikat.
  • Loo funktsioon, mis loeb sisse 10 numbrit. Salvesta need kõik massiivi.
    Meeldetuletus: Massiiviga koos tuleb edastada funktsioonile ka selle pikkus.
    Vihje: loe need kas failist või kasuta voo suunamist, et säästa enda aega programmi testimisel!
  • Loo funktsioon, kus trükid välja kõik loetud arvud ning nende asukoha mälus.
  • Loo funktsioon, mis leiab korraga nii minimaalse kui maksimaalse arvu massiivist
    • Seda funktsiooni tohid välja kutsuda vaid ühe korra, mõlemad tulemused tuleb leida selle käigus.
    • Funktsiooni ei tohi tagastada midagi (st tagastuse tüüp on  void ).
    • Võid eeldada, et eksisteerib vaid üks vähim ja üks suurim arv.
    • Kasuta viitade võimalusi kahe väärtuse funktsioonist kätte saamiseks.
      • Ära kasuta massiive min/max väärtuse salvestamiseks!
      • Ära väljasta tulemusi loodava funktsiooni sees!
  • Kõik funktsioonid tuleb kutsuda välja main() funktsioonist. Minimaalne ja maksimaalne väärtus väljasta samuti main() funktsioonis.
Testimine

Esimese osa oodatav väljund

Ülesanne 2 osa 2 [W01-3]: massiiv on viit esimesele liikmele

Selle ülesande eesmärk on veenduda, et mõistad korrektselt ideed “massiiv on käsitletav kui viit esimesele massiivi liikmele”.

Nõuded
  • Loo (või korduvkasuta) funktsioon, mis suudaks massiivist välja trükkida n numbrit ja mäluaadressi.
  • Funktsioonil tohib olla vaid 2 parameetrit.
  • Funktsioon peab olema ehitatud sedasi, et see suudaks väljastada ükskõik millise etteantud massiivi
  • Näitamaks, et su funktsioon on tehtud õigesti (ning veelgi enam, tõestamaks, et mõistsid teemat õigesti), kutsu loodavat funktsiooni välja 3 korda sedasi, et
    • esimene kord trükitakse välja kogu massiiv
    • teine kord trükitakse välja vaid elemendid 0 – 4
    • kolmas kord trükitakse välja elemendid 3- 7

Vihje: Mõtle enne hoolikalt kui hakkad funktsiooni koostama! Ülesande eesmärk on veenduda, et sa massiivi ja viida omavahelisest seosest õigesti aru.  Ülesande eesmärk ei ole luua ülimalt keerulist või kavalat lahendust!

Testimine

Oodatav väljund pärast teise osa lahendamist

Lisaülesanne [W01-4]: MinMax koos aadressidega

Selles ülesandes taasloome teise ülesande esimeses osas loodud ekstreemväärtuste leidmise funktsiooni. Teeme muudatuse mis lubab meil lisaks väärtusele saada ka asukoha, jällegi kasutades viitade omadusi

Nõuded
  • Loo uus funktsioon või muuda olemasolevat sedasi, et leida minimaalse ja maksimaalse arvu asukoht. Funktsioon peab leidma mõlema asukoha ühe käivitusega.
  • Funktsiooni ei tohi tagastada midagi (st tagastuse tüüp on  void ).
  • Funktsioonil tohib olla täpselt 4 parameetrit
    • Massiiv arvudega
    • Massiivi pikkus
    • 2 viita või topeltviita – mõtle välja mis nendes hoida sobiks!
  • Trüki välja järgnevad tulemused main funktsioonis
    • Minimaalne ja maksimaalne arv
    • Minimaalse ja maksimaalse arvu aadressid massiivis
    • Minimaalse ja maksimaalse arvu indeksid massiivis
    • NB! Aadressi ja indeksi leidmiseks ei tohi sa täiendavalt massiivi uuesti läbi käia! Tulemused saamiseks tuleb kasutada viitade omadusi ja arvutada vastused funktsioonist saadavate tulemuste põhjal!
Testimine

Lisaülesande lahendusena oodatav väljund

Pärast seda tundi peaksid

  • mõistma aine nõudeid, sh kuidas hinne kujuneb
  • teadma mis on viit
  • oskama mõista mäluaadressi iseloomu
  • tegema vahet virtuaalsel ja füüsilisel aadressil
  • teadma mis mõjutab mäluaadressi suurust
  • teadma täiendavast mäluvajadusest ja keerukusest mis tuleb viitade otsese kasutamisega
  • oskama viitmuutujat deklareerida
  • teadma kuidas viitadega koodi kirjutada lähtuvalt koodimisstiilist
  • teadma mis tähtsus on viida andmetüübil
  • teadma mis on  NULL-viit ja kus seda kasutatakse
  • teadma mõningaid valdkondi kus viitasid kasutatakse
  • teadma ja oskama kasutada viida-aritmeetikat
  • mõistma scanf argumente ja kuidas viidad ning aadressid siin mängu tulevad
  • mõistma miks me eelmine semester ütlesime, et massiivi edastamisel manipuleerime originaalandmeid ning muutujate puhul mitte
  • osksama muutujate mäluaadresse funktsioonidesse edastada
  • oskama mitme muutuja väärtust ühe funktsiooni sees manipuleerida kasutades viitasid
  • mõistma topeltviida ideed
  • oskama kasutada tingimuslausete koostamiseks kolmikoperaatorit

Täiendavat materjali

PR1ET15: Failid

Labori materjal

Esitamisele kuuluvad ülesanded

Selles laboris on 2 ülesannet, millest mõlemale on edasijõudnute ülesanded laiendusena.

Ülesanne 1: paaris/paaritu

Selle ülesande peamiseks eesmärgiks on harjutada mitme faili korraga käsitlemist ning selle korrektselt tegemist.

Nõuded
  • Sisendfailist loetakse teadmata kogus täisarve, mis on eraldatud tühiku või reavahetusega. Arve võib olla lõpmata palju.
    • Näiteks: 5 3 -6 0 25 955 -1024
  • Arvud jaotatakse lähtuvalt järgnevatele põhimõtetele:
    • Nulliga võrdsed või väiksemaid arve ignoreeritakse.
    • Positiivsed paarisarvud salvestatakse faili paaris.txt
    • Positiivsed paaritud arvud salvestatakse faili paaritud.txt
  • Jälgida tuleb elementaarseid failide käitlemise reegleid
    • Faili avamist kontrollitakse alati
    • Kui fail ei avane siis sellest teavitatakse kasutajat, sealjuures täpsustatakse ka milline fail ei avanenud.
    • Failid sulgetakse enne programmi lõppu
  • Kui sisendfailis on vales formaadis sisend peab programm töö katkestama.
    • Näiteks 9 -5 hey 14
Hoiatused ja vihjed!
  • Ole väga ettevaatlik lõpmatute tsüklitega olukorras kus toimub ka faili kirjutamine – võid oma kettaruumi mõne sekundiga täis kirjutada.
  • Jäta vähemalt testimise ajaks ekraanile väljatrükk iga loetud numbri kohta ning millisesse faili see kirjutatakse. Sedasi on lihtsam aru saada kui midagi läheb valesti ja saad kiiresti katkestada programmi ( ctrl+c ) kui tekib lõpmatu tsükkel).
  • Kui esimene fail õnnestus avada, kuid teine mitte, siis enne väljumist tuleb esimene kinni panna!
Edasijõudnute ülesanne 1: statistikute leidmine

Leia järgnevad statistikud:

  • Täisarvude summa ja aritmeetiline keskmine
  • Vähim ja suurim arv
  • Kõik tulemused tuleb leida terve sisendfaili ulatuses olenemata arvust (sh negatiivsetest arvudest!).
  • Korduv faili lugemine pole lubatud selle ülesande lahendamiseks.
  • Programm peab jätkuvalt töötama lõpmata paljude arvudega.
Edasijõudnute ülesanne 2: käsurea argumendid

Lisa programmile käsurea argumentide tugi. Muuda programmi järgnevalt

  • Sisendfaili nimetus loetakse alati käsurealt.
    • Kui faili nimetust ei anta kuvatakse veateade ning programm sulgeb end
    • Faili nimetus on alati esimene argument programmile
  • Verbose ehk jutukas
    • Programm peab tuvastama argumendina -v  ehk verbose
    • Programm kuvab iga faili avamise järel mis fail avati (nimeliselt)
    • Programm kuvab iga sisendist loetud numbri ning millisesse väljundfaili see kirjutati
    • Programm kuvab iga faili sulgemise
    • Kui verbose ei ole aktiivne, ei tohi programm ühtegi rida teksti kuvada (välja arvatud veateated ja edasijõudnute ülesanne 1 väljund)

Mõlemad argumendid on laialtlevinud praktikad käsureaprogrammide puhul, kuid leiavad sageli kasutamist ka graafilistes programmides.

Programmi käivitamise näited mis peavad olema toetatud:

  • ./parity input_nums.txt
  • ./parity input_nums.txt -v

Ülesanne 2: Hoiatustrahvide menetlemine

Ülesande eesmärgiks on luua programm, mis menetleb kiiruskaamerate poolt mõõdetud kiiruseületamisi.

Taustteave

Ülesanne on koostatud avaliku informatsiooni põhjal

Trahvi koostamise põhimõtted
  • Seadme mõõtemääramatus on 4 km/h (50 – 90 km/h alad).
  • Menetlust alustatakse, kui kiirust ületati vähemalt 3 km/h.
  • Iga piirkiirust ületatud km/h eest tuleb tasuda 5€.
  • Maksimaalne trahvisumma on 300€.
  • Kui lubatud kiirust ületati 50 km/h tuleb alustada üldmenetlust.
  • Näiteks: sõites 90 km/h alas kaamerasse 99 km/h tuleb määrata hoiatustrahviks 25€.
Sisendfail

Lae alla testandmetega sisendfail: 14_2_speeds.txt

Sisendfailis on üks mõõtetulemus rea kohta. Sisendfaili struktuur: <auto registreerimisnumber> <mõõdetud kiirus> <piirkiirus>

  • Auto registreerimismärk – kuni 9 tähemärki pikk sõne
  • Mõõdetud kiirus – positiivne täisarv
  • Piirkiirus – positiivne täisarv.
Loodavad väljundfailid

Programmi tulemusena luuakse 2 väljundfaili – hoiatustrahvid ja üldmenetluse teated.

Esimese loodava väljundfaili sisuks on hoiatustrahvid. St sinna faili tohib kirjutada vaid trahviteatised, mis tuleks sõidukiomanikel tasuda. Iga hoiatustrahv kirjutatakse eraldi reale. Iga rea kohta on  kolm andmevälja:

  • Numbrimärk
  • Kiiruseületus ilma mõõtemääramatuseta (mitu km/h üle piirkiiruse sõideti)
  • Trahvisumma (kiiruseületamisele vastav hoiatustrahv)

Oodatav tulemus:

Teise loodava väljundfaili sisuks on üldmenetluse teated. St sinna tohib vaid kirjutada need, kelle suhtes alustatakse üldmenetlust. Üldmenetluse teated kirjutatakse järgneva formaadiga:

Oodatav tulemus:

Edasijõudnute ülesanne: seadistatavus

Kuna seadused on pidevas muutumises, siis trahvimäärade koostamiseks kasutatavad väärtused peavad olema lihtsasti seadistatavad. Mõtle välja kõige lihtsam lahendus järgnevate nõuete realiseerimiseks

1. Kiiruseületamise menetlemine peab olema seadistatav:

  • Iga ületatud km/h eest makstav summa (nt 3€, 5€, 10€)
  • Maksimaalne hoiatustrahvi summa (nt 100€, 190€, 300€)
  • Üldmenetluse alustamiseks vajalik kiiruseületus (nt 40 km/h, 61 km/h, 100 km/h)

2. Seadistamine peab olema lihtne aga igapäevaelus nähtamatu

Leia sobiv lahendus programmi seadistatavaks muutmiseks lähtuvalt järgnevatest nõuetest:

  • Seadistusvõimaluse lisamine ei tohi muuta programmi igapäevast kasutamist aegavõtvamaks.
    Mõte: Igapäevasel kasutamisel ei soovi politseiametnik aega raisata asjade ümberseadistamisega ega isegi nt olemasoleva seadistuse kinnitamisega.
  • Seadistusvõimaluse muudatus peab kehtima senikaua kuniks seda uuesti tehakse.
    Mõte: Olles näiteks pärast seadusemuudatust tarkvara ära seadistanud uutele väärtustele ei soovi sa seda iga päev uuesti teha.
  • Seadistuste muutmine ei tohi vajada programmi ümberkompileerimist.
    Mõte: Keegi ei kujutaks ette, et politseiametnik hakkab programme ümber kompileerima keset tööpäeva.

Pärast seda tundi

  • peaksid oskama faile avada ja sulgeda
  • peaksid oskama kontrollida faili avanemist
  • teadma mis vahet on erinevatel faili avamise režiimidel ning kuidas need käituvad vastavalt kas fail eksisteerib või ei eksisteeri
  • teadma mis olukordades failid ei avane kui neid avada lugemiseks või kirjutamiseks
  • teadma erinevaid failide adresseerimise võimalusi
  • teadma mida tähendab failide juures puhverdamine ning mis ohte see võib kaasa tuua
  • oskama faile lugeda ja kirjutada

Täiendav materjal

PR1ET13: Sõned

Labori materjal

Esitamisele kuuluvad ülesanded

Selles tunnis on 2 ülesannet, millest esimeses õpime tundma string.h teeki ning teises manipuleerime tähemärke käsitsi.

Ülesanne 1: string.h teegiga tutvumine

Selle ülesande käigus loome ühe programmi, mille käigus tutvume peamiselt erinevate string.h teegis olevate funktsioonidega.

Nõuded
  • Programmi koostamiseks liigu samm-sammult juhendis antud järjekorras.
  • Programmi käivitades küsitakse kasutajalt parooli. Enne õige parooli sisestamist ei tohi programm edasi minna.
  • Kasutajalt loetakse lause. Programm kuvab mitu tähemärki lauses oli (sh tühikud, kirjavahemärgid).
  • Kasutajalt loetakse otsingufraas. Seejärel väljastatakse kas eelnevalt sisestatud lauses see fraas esines või mite (jah/ei vastus).
  • Kasutajalt küsitakse 2 sõna, mida kasutatakse lause moodustamisel.
    • Sõnade tüübid võid ise valida (nt nimi, ese, omadussõna, tegusõna, …)
    • Kleebi kasutaja poolt sisestatud sõnad kokku, lisades enda poolt täiendavaid sõnu moodustamaks vähemalt neljast sõnast koosneva lihtlause.
    • Üks kasutaja sisestatud sõnadest peab olema selle lauses esimene sõna.
    • Moodustatav lause tuleb salvestada täiesti uude tähemärgimassiivi, mis peab mahutama selle lause ka siis, kui loetud 2 sõna olid maksimaalse lubatud pikkusega.
Abifunktsioon

Kui sul tekib ühel või teisel hetkel probleeme aru saamisega mis sul tekstimassiivi sisuna salvestatud on, siis võid seda funktsiooni kasutada. Antud funktsioon trükib välja tervikliku sõne, misjärel trükitakse kõik tähemärgid ja selle vastavad ASCII tabeli täisarvulised väärtused. Nii on hea lihtne tuvastada kui näiteks mõni reavahetus või muu imelik sümbol jääb massiivi sisse.

Juhend
1. samm: kasutaja sisestuse lugemine

Esimese sammu teeme tunnis koos läbi! Selle käigus loome me 2 vajalikku funktsiooni oma programmi.

Alustame esimesest mida kasutame sõne lugemiseks. Lahenduses on oluline, et me suudaksime lugeda mitmetest sõnadest koosnevaid sõnesid ehk tühik ei tohiks meil lugemist ära lõpetada! Selleks on mitmeid viise, kuid meie läheneme ülesandele kasutades funktsiooni fgets() . Soovi korral võid ise teist teed minna.

Funktsiooni fgets()  eripäradeks on, et ta on mõeldud lugemaks failist. Küll aga kõik asjad on failid, sh ka klaviatuurilt tulev andmevoog, seega saame kasutada failina stdin  nimelist faili. Teine keerukus antud funktsiooni juures on see, et ta vajab endale pikkust palju tohib lugeda – see on tegelikult ohutuse tagamiseks, et puhvri pikkusest üle ei loetaks. Kolmas ja kõige probleemsem on see, et kui me vajutame klaviatuurilt enter klahvi, siis see reavahetus \n  salvestatakse samuti sinna massiivi.

Lähenemises kasutame põhimõtet, et loome funktsioonidele wrapperid ehk ümbritseme need täiendavate lausetega, mis funktsiooni kasutamise meeldivamaks või mugavamaks muudavad meie jaoks.

Meie ümbrisel on vaja kahte sisendit – sõnet ehk tähemärgimassiivi kuhu loetava teksti salvestame ning kui suur see tekstimassiiv loomise hetkel oli, et me lubatud pikkusest üle ei kirjutaks ja programmi rünnata sedasi ei lubaks.

Antud lahenduses olen jätnud kolme kohta küsimärgid sisse, kus pead ise lüngad täitma! Vihjeks: kui loetud stringi pikkus on 10 tähemärki, siis indeksiga 8 on meie jaoks viimane oluline tähemärk mille kasutaja sisestas. Sellele järgneb meile ebasoovitav reavahetus, millest peame lahti saada, asendades selle sõne lõpu sümboliga.

Vajadusel kasuta varasemalt välja toodud abifunktsiooni!

Selleks, et funktsioon ka kompileeruks olen need 2 täiendavalt vajalikku rida välja kommenteerinud. Olles küsimärgid asendanud kommenteeri need sisse.

Kui lugemine on valmis, loome järgmise ümbrise oma vastloodud GetString()  funktsioonile. Nii saame mugavalt sisestust küsida!

Nüüd kui soovime mõnda sõnet lugeda, saame oma väljakutse luua üsna mugavalt. Näiteks kui meil on tähemärgimassiiv sentence[]  mille pikkus on defineeritud makroga MAX_STR , saame väljakutse luua

2. samm: lause lugemine ja selle pikkus

Loe kasutajalt sisse lause. Seejärel leia ja väljasta sisestatud lause pikkus.

3. samm: fraasi otsimine

Lisa programmi funktsioon, milles küsitakse kasutajalt otsingufraas. Programm väljastab seepeale kas see fraas eksisteeris varasemalt sisestatud lauses või mitte.

Jah-ei vastuseks piisab kui kontrollida tagastust järgneval kujul

4. samm: parooli küsimine

Lisa programmi funktsioon, mis küsib kasutajalt parooli. Näiteks:

Parooli küsimine peab olema tsüklis ja küsima kasutajalt parooli senikaua, kuniks kasutaja sisestab korrektse parooli. Parooli kontroll peab olema tõstutundlik (st suuri ja väiketähti ei võrdsustata). Soovi korral võid panna programmi vale parooli puhul vihjeid andma või end sulgema pärast korduvalt parooli valesti sisestamist.

5. samm: lause moodustamine

Lisa programmi funktsioon, mille käigus moodustad lihtlause. Kuna funktsioonile meil head sisendit ega tagastust anda ei ole, võiksid alustada funktsiooni sedasi (void-void funktsioonid on erandlikud ja enamasti tuleb neid vältida!):

Mõttekoht: kui pikk peaks olema sentence  massiivi pikkus, et see mahutaks halvimal juhul ära mõlemad kasutaja sisestatud sõnad ning sinu lisatavad sõnad, tühikud ja kirjavahemärgid, et moodustada lauset? Suurus võib olla liigkaudne aga peab olema piisav!

Edasi mõtle välja millist lauset moodustada soovid. Oluline on, et selles lauses oleks kaks lünka, kuhu kasutaja sisestab enda soovitud sõnad (ise otsustad millised – nt inimese nimi, ese, nimisõna, tegusõna, …). Üks nendest sõnadest peab olema lause esimene sõna, teise asukoht on sinu enda otsustada. Näiteks <sõna1> on <sõna2> nimi! .

Olles kasutajalt sõnad pärinud ja programmi sisse lugenud tuleb sul need sõnad lauseks kokku kleepida. Kokku kleebitav lause peab olema salvestatud täiesti uude tühja tähemärgimassiivi. Oluline on arvestada, et mis iganes kasutaja sisestab (lubatud pikkuste raames) peab ära mahtuma sinna koostatavasse massiivi ka sellisel juhul, kui kasutaja otsustas maksimaalselt pikad sõnad sisestada.

Näide
Lisaülesanne: Tähtede loendus

Loo käsitsi uus loendamise funktsioon ning väljasta statistika

  • Loenda ja kuva mitu tähte [a-zA-Z] oli lauses. Ära loenda kirjavahemärke, tühikuid jne.
  • Leia ja kuva mitu protsenti kogu lausest moodustasid tühikud, kirjavahemärgid ja muud sümbolid.
  • Näita protsent ühe komakohaga.

Näide

Ülesanne 2: CSV-st meiliaadresside genereerimine

Selle ülesande eesmärk on sulle tutvustada laialtlevinud andmeformaati CSV (comma separated value). Ülesande lahendamise käigus saad harjutada üksikute tähemärkide tuvastamist ja töötlemist.

Lae alla ülesande aluskood: 12_2_csv_starter.c

CSV formaat

CSV on struktuursete andmete hoiustamise formaat, kus iga andmeväli on eraldatud eelnevast ja järgnevast komaga. Tegu on tõenäoliselt kõige levinuma andmete varundamiseks ja hoiustamiseks  kasutatava formaadiga väljaspool andmebaasisüsteeme. Tema peamisteks eelisteks on lihtne struktuur ning sellest tingitult on CSV toetatud praktiliselt kõigis rakendustes, mis vähekegi andmetega töötlevad.

Kõige lihtsamal kujul nagu öeldud on kõik väljad eraldatud üksteisest komaga. Näiteks:

Täpselt sellise keerukusega andmeid vaatame ka selles tunnitöös. Nägemaks keerulisemaid formaate ja reegleid kuidas hoiustada väljasid, mis peavad sisaldama komasid, jutumärke ning kuidas lisada pealkirju võid lugeda siit: https://en.wikipedia.org/wiki/Comma-separated_values#Basic_rules

Nõuded
  • Ülesande lahendus on ehitatud antud aluskoodile
  • Programm loob igale aluskoodis antud inimesele e-postiaadressi.
    • e-postiaadressi nimeosa koosneb kolmest eesnimetähest ja kolmest perenimetähest.
    • Nimeosale järgneb sinu valitud domeen.
    • E-postiaadressi nimi ja domeen peavad koosnema vaid väiketähtedest.
    • E-postiaadress tuleb salvestada terviklikult tekstimassiivi (loo uus muutuja seal kus vaja) ja väljastada selle kaudu. Jooksvalt tähemärkhaaval väljastus pole lubatud.
  • Programm väljastab:
    • Inimese täisnime. Eesnime ja perenime osa peavad olema eraldatud tühikuga
    • Genereeritud e-postiaadressi.
  • Aluskoodis juba olevat koodi ülesande lahendamiseks muuta ei tohi ilma juhendaja poolse nõusolekuta. Sinu poolt kirjutatava lahenduse alguspunkt peaks asuma  ProcessPerson()   funktsiooni sees. Soovi korral võid julgelt funktsioone juurde lisada.
Näide
Vihjed
  • Teades koma asukohta, tead ka mis indeksilt algab perenime esimene täht
  • ASCII suur- ja väiketäht erinevad üksteisest ühe biti võtta, mille järgu väärtuseks on 32 (nt A 65, a 97)
  • Kõik toimingud peale e-mailiaadressi lõpu lisamise on kõige lihtsam teha selles ülesandes tähemärk-haaval. Saab ka kasutada string.h  teegi funktsioone, kuid need võivad olla asjatult keerukad.
  • Kõige tüüpilisem viga selles ülesandes on unustada sõnele null-baidi ehk terminaatori lõppu lisamist pärast nimeosa koostamist!
Lisaülesanne 1: lühikesed nimed

Muuda oma e-postiaadresside genereerimise algoritmi sedasi, et see tuleks toime ka lühemate nimede puhul.

Näiteks: Ly Kask -> lykask@ttu.ee

Lisaülesanne 2: unikaalsed e-postiaadressid

Muuda oma e-postiaadresside genereerimise algoritmi sedasi, et see genereeriks unikaalseid postiaadresse ka siis kui nimel on sarnane algus.

Muuda oma data massiiv järgnevaks:

Nõuded

  • Loodavad e-postiaadressid peavad olema unikaalsed
  • Aadressi nimeosa peab jätkuvalt olema 6 tähemärki
  • Aadressid peavad jätkuvalt viitama nime omanikule nii palju kui võimalik
  • Täpne algoritm ja seega saavutatav nimekuju on sinu enda valida. Põhjenda valitud lahendust kaitsmisel.

Pärast tundi peaksid

  • Teadma, et tähemärkide jaoks kasutatakse erinevaid kodeeringuid, muuhulgas ASCII ja Unicode
  • Teadma mis on ASCII tabel ning kuidas seda kasutada.
  • Teadma kuidas töötavad sõned C keeles.
  • Teadma kuidas lõpetatakse sõnet C keeles (null-terminaator/null-bait).
  • Seostama C keelseid sõnesid baidijadadega.
  • Teadma mis on CSV.
  • Oskama kasutada string.h teeki sõnede manipuleerimiseks.
  • Oskama ka ise kirjutada sõnede manipulatsioone (tähemärkhaaval lähenemine).
  • Teadma mis asi on puhvri ületäitumine ning selle kaudu tehtavatest rünnakutest.

Täiendav materjal

PR1ET8: Voo suunamine ja pseudo-juhuarvud

Labori materjal

Esitamisele kuuluvad ülesanded

Selles laboris on kaks ülesannet, millest mõlemale on laiendusena pakutud välja lisaülesanne.

Ülesanne 1: kuupäeva kontroll

Ülesande eesmärgiks on tuvastada kas sisestatud kuupäev on tõene või vigane. Ülesande raames tutvume ka voo suunamisega.

Lae alla ülesande aluskood: https://blue.pri.ee/ttu/files/iax0583/aluskoodid/8_1_date_base.c

Nõuded
  • Programm kuvab iga kuupäeva puhul kas tegu on reaalse või vigase kuupäeva.
  • Aastate vahemik on piiratud 1900 – 2099
  • Programmis on rakendatud liigaasta kontroll
  • Maksimaalselt töötleb 100 kuupäeva
  • Kuupäevad vastavad kõik formaadile DDMMYYYY .
  • Baasülesande raames tuleb lahendada funktsioonid sellisel kujul nagu nad antud on.  Kohustuslike funktsioonide loetelu ja kommentaarid leiad aluskoodist.
  • Programmi esitades pead seda tegema kasutades sisendvoo ümbersuunamist. Sisendiks on fail, mis sisaldab endas sellel lehel antud testkuupäevasid.
Algoritm

NB! Algoritm näitab meile üldisemat ideed ülesande lahenduskäigust ning on eelkõige informatiivse väärtusega. Algoritmis ei kajastu kuidas võiks toimida andmevahetus funktsioonidega. Samuti on funktsioonide kasutamisest tulenevalt mõningad järjestusest teistmoodi.

Samm-sammuline lahendamisjuhend

Alususeks peame tegema andmefaili. Sinna kirjutame samad andmed, mida muidu trükiksime klaviatuurilt iga kord programmi testides. Teisisõnu kirjutame oma testandmed ühekordselt ära ja hiljem lihtsustame oma testimist sedasi. Mõnel ülesandel võib taolisi testfaile olla mitu, mõnel piisab ühest.

Lähtefaili kirjutades tuleks arvestada kõikvõimalike erinevate juhtudega,  mis programmis esineda võivad. Kindlasti tuleb testida nii sobilike kui ka mittesobivaid kuupäevi. Näiteks võib siin olla tavapäraseid kuupäevi – 11. detsember 1981, kuid samuti ka ebareaalseid kuupäevi – 51. detsember, kuu nr 22 jne. Eriti olulised on piirjuhud – nt 29. veebruar liigaastal ja tavapärasel aastal. Järgnevalt on välja pakutud üks võimalik loetelu kuupäevi (võid julgelt kuupäevi lisada loetelu lõppu, kuid need peavad kindlasti sisalduma testis).

Siin on sinu testsisend. Salvesta see tekstifailina samasse kausta kuhu oma programmi paned!

Järgmiseks oleks meil vaja programmi, mis neid kontrollima hakkaks.

Nüüd hakkame töötama ette antud aluskoodiga. Esimesed kaks funktsiooni teeme tunnis koos ära! Kui tunnis polnud, vaata loengusalvestust!

Nüüd peaks meil olema 2 faili, mõlemad samas kaustas:

  1. Programmikood (nt date.c )
  2. Tekstifail sisendandmetega (nt input või input.txt )

Järgmisena on meil vaja programmi. Üks valik programmi loomiseks on see kompileerida läbi Geany või mõne teise rakenduse mida oled senimaani kasutanud. Võid seda julgelt teha kui end sedasi mugavamalt tunned. Ära vaid unusta iga kord uuesti kompileerimast pärast muudatusi!

Ava mind, et näha kuidas seda teha käsurealt

Kompileerida võid ka käsurealt. Täpselt sama asi juhtub tegelikult kui nt Geany sees vajutad build nuppu. Selleks on üldine struktuur kompilaatori_nimi -o programmi_nimi koodifaili_nimi.c . Oluline on, et -o järel on alati soovitav programmi nimi (väljund). Kõige lõppu paneme me aga oma programmi koodi sisaldava faili nime. Lisaks kasutame tavaliselt täiendavaid lippusid, et meile ka rohkem veateateid kuvatakse. Näiteks -Wall  ja -Wextra .

Nüüd paneme selle kõik kokku. Olles saanud käsuakna õigesse kausta kus asuvad su teised failid saad teha järgmist:

gcc -o date -Wall -Wextra date.c

Selle reaga kompileeritakse lähtekoodi fail date.c  programmiks nimega date .

Veendume, et failid on kõik seal, kus peaks kasutades käsku ls -l :

Kui varem oli meil 2 faili, siis nüüd peaks neid olema 3:

  • date  – nn binaarfail ehk programm, mis loodi lähtekoodi kompileerimise tulemusena. Käivitatav!
  • date.c  – lähtekoodi fail. Siia kirjutame me tekstiredaktoriga koodi, ei ole käivitatav programmina!
  • input.txt  – tekstifail, mis sisaldab kuupäevi ehk testandmed.

Nüüd käivitame programmi sedasi, et klaviatuurilt trükkimise asemel loetakse andmed ette söödetud failist (kasutades voo ümbersuunamist). Selleks saame kasutada järgmist struktuuri, asendades failid õigete nimedega: ./programminimi < andmefailinimi

./programminimi – sedasi saad programmi käima Linuxis käsurealt
< – tähistab, et programmi klaviatuurilt tulevad sisestused juhitakse ümber
andmefailinimi – siit hakatakse lugema mida programmile ette sööta ehk siis kust sisestus tuleb

Siin lõppeb tunnis koos tehtav osa ning algab iseseisev töö. Selleks hetkeks peaks programmi väljund olema järgmine

Testimine: valmislahendus

Pärast programmi valmimist peaks su väljund nägema välja samasugune nagu siin.

Ülesanne 2: loto

Lae alla ülesande aluskood:

Nõuded
  • Tunnitöö tuleb ehitada ette antud aluskoodile.  Aluskood on sulle antud ning sisaldab juba funktsioonide loetelu funktsioonidest koos kommentaaridega mis tuleb sul realiseerida ja kasutusele võtta.
  • Lotonumbrid genereeritakse vahemikus 1 … 25 (otspunktid kaasaarvatud).
  • Kasutajalt küsitakse 6 arvu (lotonumbrid).
  • Programm genereerib juhuarvudena 10 arvu (võidunumbrid).
  • Programm kuvab genereeritud võidunumbrid
  • Kontrolli ja näita mitu ja millised numbrid kattusid.
    • Baasülesandes pole nõutud numbrite unikaalsus
    • Iga lotonumber saab kattuda võidunumbriga vaid ühel korral.
  • Kui kõik numbrid kattusid, õnnitle peavõidu korral. Kui ükski ei kattunud, avalda kaastunnet.
Testimine

NB! Kuna loterii nagu nimigi ütleb on juhuslik, siis selle testimisel tuleks juhuarvu seeme (srand funktsiooni argument) määrata konstandiks. Genereeri ühe korral lototroni numbrid ära ja jäta need meelde, et saaksid testi tulemusi kergelt korrata!

Test 1: Juhuslikud arvud, mõni võidunumber, sisestus OK.

Test 2: Võidunumbrid puuduvad

Test 3: Jackpot

Test 4: Vigane sisestus

Test 5: Iga number võidab vaid korra (absurdsed olukorrad – sanity check)

Antud testis teeme muudatuse oma lähtenõuetes, et testida mitu korda üks lotonumber võita saab. Kaine mõistus ütleb, et iga number saab võita vaid korra.

NB! See test töötab selliselt vaid siis kui unikaalsuse nõue ei ole täidetud (st pole tehtud lisaülesanne). Korduvad numbrid on seega lubatud.

Antud testi juures saame jälgida kusjuures kahte erinevat asja

  1. Jälgi võitude arvu! St Matched 6 out of 6!)
  2. Jälgi lototroni genereeritud numbreid. Need tohivad olla vaid ühed! (0 või 2 esinemine tähendab, et sul on viga juharvude valemi koostamisel!)
Märkus: Tunnitöö baasülesandes vaatleme vai lihtsalt juhtu, kus kasutaja arv saab võita ühekordselt. Näiteks kui kasutaja sisestab numbrid “1, 1, 1, 1, 1, 1” ja lototron genereerib “1, 2, 3, 4, 5, 6, 7, 8, 9, 10”, siis baasülesande raames piisab, kui loeme, et iga kokku tuli 6 tabamust. Kui aga kasutaja numbrid oleksid “1, 2, 3, 4, 5, 6” ja lototron genereeriks “1, 1, 1, 1, 1, 1, 1, 1, 1, 1”, siis oleks olnud vaid 1 tabamus.

Lisaülesanne 1: mittekorrektse kuupäeva põhjendus

Algse lahenduse puudujäägiks oli ebaselgus miks üks või teine kuupäev ei valideerunud. Täiendame oma programmi sedasi, et ka põhjus oleks arusaadav.

Nõuded
  • Laienda oma programmi nii, et programm põhjendaks miks kuupäev reaalseks ei osutu
  • Minimaalselt pead eristama
    • Ebasobivat aasta väärtust
    • Ebasobivat kuu väärtust
    • Ebasobivat päevade arvu, eristades sealjuures väiksemat ja suuremat kui lubatud väärtust
    • Mitte-liigaastal olevat 29ndat veebruari
  • Lahenduses võid lisada täiendavaid funktsioone ja muuta mõistuse piires ka olemasolevat programmi struktuuri.
  • Meeldetuletus! Väldi maagilisi arve!
Testimine

Lisaülesanne 2: lototronile unikaalsed numbrid

Selle ülesande eesmärk on muuta ülesanne täisväärtuslikuks. Selleks on meil vaja lahendada vaid üks funktsioon FindMatchCount()  ning seda õigetes kohtades kasutusele võtta.

Nõuded
  • Kasutaja poolt sisestatavatele numbritele tuleb rakendada unikaalsuse nõue. Kui kasutaja sisestab korduva numbri, tuleb see sama number uuesti küsida.
  • Lototronile tuleb rakendada unikaalsuse nõue. Lototroni poolt genereeritavad võidunumbrid ei tohi korduda.
  • Lahenduse käigus ei tohiks muuta GetUserNumbInRange()  ja GenerateRandomNum()  funktsioone, otsi selleks sobilikum koht.
  • Kommenteeri sisse ja lahenda ära funktsioon CheckIfNumInArray() . Võta see funktsioon kasutusele kolmes kohas
    1. Kasutaja lotonumbrite unikaalsuse kontrolliks
    2. Lototroni genereeritud võidunumbrite unikaalsuse kontrolliks
    3. Kasutaja ja lotoarvude kattuvuse leidmise funktsioonis FindMatchCount()
Testimine

Test 1: Kontrollime unikaalsuse nõuet kasutajale

NB! Kontrolli kindlasti kasutades sama jada!

Test 2: Kontrollime unikaalsuse töötamist lototroni poolt

Selleks, et kontrollida lototroni tööd peame me jällegi manipuleerima konstante.

Selle testiga on meil arvuti poolt genereeritud numbrite arv täpselt sama suur kui maksimaalne unikaalsete numbrite arv. St kõik numbrid 1 – 10 peavad saama genereeritud ning ükski neist korduda ei tohi.

Mõtle ja vasta ka küsimusele mis juhtuks kui oleksime konstandi pannud 9 peale?

Pärast tundi peaksid

  • Teadma millised standardvood eksisteerivad
  • Oskama kasutada voo suunamist erinevatel platvormidel
  • Oskama käivitada enda kompileeritud programme Linuxi käsurealt
  • Oskama kasutada tõeväärtusi (boolean andmetüüp)
  • Oskama tükeldada sisestust vajadusel tähemärkhaaval
  • Oskama kasutada scanf poolt taastatavat väärtust
  • Oskama kasutada üherealisi tingimuslauseid ja tsükleid
  • Oskama genereerida pseudojuhuarve
    • .. pannes need alati algama samast arvust
    • .. pannes need kellaajast sõltuvaks
  • Teadma mis vahet on pseudojuhuarvul ja juhuarvul
  • Oskama piirata juhuarvude genereerimise vahemikku
  • Teadma mis on ning kuidas töötab UNIXi kellaaeg, sh mis tähtsus on 1. jaanuaril 1970.

Täiendav materjal

PR1ET10: Menüü-programm

Teooriat ja meeldetuletusi

Tähemärk, sõne ja väljastusfunktsioonid

Kuigi sõnede juurde tuleme alles mõne nädala pärast võime mõnda omadust ikkagi vaadata.

Sõne (string) tähendab järjestatud tähemärkide jada. St selleks võib olla arusaadav sõna või lause, kuid võib olla ka arusaamatu erinevate sümbolite jada. Sõned on alati jutumärkide vahel.

Näited:

    • "a"
    • "Hello!"
    • "I do wish we could chat longer, but I'm having an old friend for dinner."
    • "lFRD=)m+0FDj2"

Üksikut tähemärki hoiame aga ülakomade vahel. Sõne koosneb sellistest tähemärkidest. NB! Kaldkriipsuga hakkavad erisümbolid (escape sequence) ja neid loetakse üheks tähemärgiks (nt \n  on üks tähemärk arvuti mälus).

Näited:

    • 'a'
    • 'y'
    • '\n'
    • '\t'

Funktsioonid mida saame kasutada teksti väljastamiseks

  • printf()  ehk print formatted. Tegu on kõige keerukamaga seniõpitutest, mille abil saame trükkida kujundatud teksti, mille abil saame ka kõiksugu muutujate sisu väljastada. Reavahetus käib käsitsi!
    Näiteks: printf("Hello, %s!\n", name);
  • puts()  ehk put string. Tegu on lihtsa funktsiooniga mis on mõeldud ühe tekstilõigu kuvamiseks. See ei toeta keerukaid formaate ega muutujatest teksti väljastamist. Reavahetus lisatakse automaatselt.
    Näiteks: puts("Hello, user!");
  • putchar()  ehk put character. See on kõige lihtsam funktsioon neist kõigist. Selle abil saab väljastada vaid ühe tähemärgi. Seda on mugav kasutada nt reavahetuse trükkimiseks.
    Näiteks: putchar('\n');

Massiivi edastamine funktsiooni

Massiive alamfunktsioonidesse edastades andsime edasi viite originaalile – st me saame edastatud massiivi muuta ilma tagastamata ja olenemata kohast.

Reeglina tuleb alati massiiviga koos edastada selle kõigi dimensioonide suurused. Pärast funktsiooni edastamist neid suurusi välja arvutada enam ei ole võimalik! Erandiks on sõned (string), millest räägime tulevikus.

Mõned eripärad edastamisel

  • Kui soovid edastada tervet massiivi, olenemata selle dimensioonide arvust, täpsustame vaid selle massiivi nime Func(numbers);
  • Kui soovid 1-dimensioonilisest massiivist int numbers[N];  edastada vaid ühe väärtuse, täpsustame selle indeksi Func(numbers[2]); . Funktsioonis käsitle seda ühte arvu  Func(int val);
  • Kui soovid 2-dimensioonilisest massiivist ( int numbers[N][M];  edastada rea alguse, täpsustame selle indeksi ja pikkuse Func(numbers[2], M); . Funktsioonis käsitle seda kui 1-dimensioonilist massiivi  Func(int numbs[], int n);
  • Kui soovid 2-dimensioonilisest massiivist int numbers[N][M];  edastada vaid ühe väärtuse, täpsustame selle indeksi Func(numbers[2][1]);

Kahe arvu omavahel vahetamine massiivis

Vahetamaks kahte arvu sobib lahenduseks mullsorteerimise tunnist õpitud vahetamise idee kasutades abimuutujat

Märkus: isegi kui soovid vahetada kahe rea või veeru väärtusi on ikkagi vaja vaid ühte muutujat.

Massiivi kasutamine abimuutuja asemel on mõistlik vaid paralleeltöötlust toetavatele protsessoritele programme kirjutades. Sellised protsessorid põhinevad SIMD (sing-instruction-multiple-data) arhitektuuril – näiteks graafikakaardid (GPU – graphics processing unit).

Massiivide algväärtustamine nulliks

Terve massiivi algväärtustamiseks nulliks paneme soovitud konstandi loogeliste sulgude vahele

Kui tegu on 2-dimensioonilise massiiviga, kasutame kahte komplekti loogelisi sulge.

Esitamisele kuuluvad ülesanded

Selles tunnis tegeleme programmiga, mis töötab senikaua kuniks kasutaja soovib sellest väljuda. Programmi raames tegeleme maatriksi manipuleerimisega.

Alusta näidisprogrammiga tutvumisest, misjärel mine edasi ülesande lahendamise kallale.

Tunnitöö näidisprogramm

Sulle on antud tänasest tunnitööst näidisprogramm. See on antud kompileeritud kujul, st saad selle käivitada ja testida milline selle lõpptulemus peaks välja nägema. Sinu loodav programm peaks lõpuks töötama sarnaselt.

Mõlemad näidisprogrammid on kompileeritud x86-64 arhitektuurile. Garanteeritud töötavad mõlemad laboriarvutitel, kuid peaksid ka töötama enamikel isiklikel arvutitel. Probleeme võib tekkida ARM protsessoritega arvutitel ilma x84-64 emulatsiooni kasutamata.

NB! Linuxil kasutamiseks pead andma failile käivitamisõigused (turvalisus ennekõike!). Õiguste muutmine on ühekordne tegevus. Selleks toimi nii:

See lisab (chmod – change mode) kasutajale (u – user) õigused programmi käivitada (x – execute). Pärast seda tohid programmi käivitada tavapäraselt, st ./program_name

Kirjeldus

Tänane tunnitöö on jaotatud kaheks eraldi hinnatavaks osaks, millele on võimalik juurde teha kolm lisaülesannet

Antud juhul on tegu programmiga, mis töötab kuniks kasutaja soovib sellest väljuda. Seetõttu peame me ka vajadusel jälgima mis seisundis meie maatriks parasjagu on.

Maatriksi maksimaalne suurus mälus on fikseeritud makrotega LIMIT_ROWS ja LIMIT_COLS , mis määravad vastavalt maksimaalse ridade ja veergude arvu. Neid pead eraldi kasutama!

Programmis võib vastavalt kasutaja soovile olla kasutusel parasjagu väiksem osa maatriksist – sellisel juhul jääb lihtsalt otsa maatriksist kasutamata. Seetõttu on funktsioonide prototüüpides igal pool 2 muutujat int rows  ja int cols , mis sisaldavad hetkel kasutusel oleva maatriksi piire.

Lae alla aluskood: https://blue.pri.ee/ttu/files/iax0583/aluskoodid/10_switch_basecode.c

Üldised nõuded

Need nõuded kehtivad olenemata millise osaga programmi lahendamisest tegeled.

  • Sinu lahendus peab võimalikult täpselt matkima etteantud näidisprogrammi.
  • Töö peab olema ehitatud etteantud aluskoodile.
    • Aluskoodi tohid mõistlikes piirides modifitseerida. Näiteks võib kasu olla tegevuste järjekorra muutmisest main() funktsioonis või funktsioonile GetIntInRange() täiendava parameetri lisamisest. Muudel juhtudel mõtle hoolikalt läbi kas muudatus on ikka mõistlik!
    • Aluskoodis on sinu jaoks juba valmis tehtud 2 funktsiooni, kasuta neid vastavalt vajadusele.
    • Aluskoodis on ette antud kahe esimese funktsiooni prototüübid millest peaksid lahendamist alustama tehes tunnitöö esimest osa.
  • Maatriksis olevad arvud on kõik vahemikus 0 – 99.
  • Kõik toimingud peavad olema korratavad ilma programmist väljumata.
  • Kõigi menüü valikute töötlev pool peab olema lahendatud eraldi funktsioonides.
    • switch()-i sees võid julgelt printida välja abiteksti, salvestada funktsioonidest tagastatavaid väärtusi jne. Äärmisel vajadusel võid ka mõne if lause sinna panna.
    • Täiendavaid tsükleid kindlasti main() funktsiooni kirjutada ei tohi!
  • Programm peab olema terviklik ja arusaadav ning töötama kuniks kasutaja soovib sellest ise väljuda.

Tunnitöö osa 1

Esimeses osas loome maatriksi kuvamise ja genereerimise.

Nõuded

  • Kasutaja saab genereerida n * m maatriksi
    • Maatriksi liikmeteks on juhuarvud vahemikus 0 – 99
    • n ja m on kasutaja poolt sisestatavad väärtused. Vajadusel loo piirangud kasutaja sisestusele
    • Genereerimise funktsioonis  GenerateMatrix()  tohid kasutada vaid do while()  tüüpi tsükleid.
    • Meeldetuletus: C funktsioonid on lihtsad ja teevad vaid ühte asja (ning teevad seda hästi)! Funktsioon GenerateMatrix() ei tohi tegeleda kasutajalt sisendi küsimisega!
  • Kasutaja saab kuvada maatriksit
    • Kuvamise funktsioonis tohid kasutada vaid while()  tüüpi tsükleid
    • Maatriks peab olema viisakalt joondus.
  • Kasutaja saab väljuda programmist

Tunnitöö osa 2

Teises tunnitöö osas loome funktsioonid ridade ja veergude omavahel vahetamiseks.

  • Kasutaja peab saama vahetada kaks enda valitud rida omavahel ära
    • Vahetamise funktsioonis tohid kasutada vaid for()  tüüpi tsükleid.
  • Kasutaja peab saama vahetada kaks enda valitud veergu omavahel

Tüüpilised vead

  • Copy-paste ehk korduv kood. Enamasti on selleks sisestus (nt sisesta ridade arv, sisesta veergude arv jne).
  • Off by one ehk ühega mööda. Meeldetuletuseks esimene rida on indeksiga 0.
  • Maagilised numbrid
  • Maatriksi operatsioonide lubamine enne maatriksi genereerimist. Näiteks sa ei saa kuvada maatriksid, mida ei ole veel genereeritud!
  • Vale tsükli tüübi kasutamine (Osa 1 ja 2 puhul on fikseeritud milliseid tsükli tüüpe tohid kasutada)
  • Ridade ja veergude arvu sassi ajamine. Proovi näiteks
    • genereerida 3 x 5 maatriks, vaheta ära read 1 ja 3
    • genereerida 5 x 3 maatriks, vaheta ära veerud 1 ja 3

Lisaülesanne 1: kustutamine

Lisame täiendava funktsionaalsuse olemasolevasse programmi

  • Kasutaja saab kustutada enda valitud rea.
  • Kasutaja saab kustutada enda valitud veeru.
  • Kustutatud rida või veerg eemaldatakse vahelt, mistõttu järgmised read või veerud tulevad varasemaks. Maatriksi suurus väheneb.
  • Lisa vajalik funktsionaalsus menüüsse.

Lisaülesanne 2: lisamine

Lisame täiendava funktsionaalsuse olemasolevasse programmi

  • Kasutaja saab soovitud asukohta lisada täiendava rea
  • Kasutaja saab soovitud asukohta lisada täiendava veeru
  • Kõik elemendid lisatavasse ritta või veergu genereeritakse juhuarvudega
  • Kõik read / veerud, mis paiknevad soovitud asukoha järel nihkuvad ühe võrra kaugemale. Maatriksi suurus suureneb.
  • Lisa vajalik funktsionaalsus menüüsse.

Lisaülesanne 3: transponeerimine

Lisame täiendava funktsionaalsuse olemasolevasse programmi

  • Kasutaja saab maatriksit transponeerida
  • Lisa vajalik funktsionaalsus menüüsse.

Pärast seda tundi peaksid

  • Oskama luua lõputult kestvaid menüü-programme
  • Teadma täiendavaid käske teksti väljastamiseks

Täiendav materjal

Kodutöö: vanuselise jaotuse looja

Ülesandeks on luua programm, mis suudab analüüsida ürituse külastajate vanuselist kuuluvust. Sisendiks tuleb teadmata arv külaliste vanuseid, kuniks programmi kasutaja sisestab nulli. Sellega katkestatakse lugemine ja väljastatakse statistika.

Grupeerimise nõuded:

  • Kõik alla 18 aastased grupeeritakse kui noored
  • Üle 18 aastaste kohta luuakse järjest 9 vanusegruppi, sammuga 5 eluaastat (nt 18 – 22, 23 – 27 jne)
  • Kõik, kelle vanus on suurem kui varasematesse gruppidesse mahtus, lahterda vanurite alla.

Andmestruktuur

Loendurid paiknevad massiivina, mille pikkus on määratud makroga GROUPS . Iga pesa massiivis on eraldi loendur vastavale vanusegrupile.

  • Indeksiga GROUPS - 1  hoitakse eakate loendurit
  • Indeksitega GROUPS - 2  hoitakse noorte loendurit
  • Indeksid 0  … GROUPS - 3  on jaotatud ühtlaselt vanusegruppidele. Näiteks indeks 0 on vanusevahemik 18 – 22; indeks 1 on vahemik 23 – 27 jne.

Programmi nõuded:

  • Grupeerimise väärtused peavad olema kergesti seadistatavad makrote abil
    • Gruppide arv
    • Grupi samm
    • Noorimate grupi ülemine piir
  • Ülejäänud programm peab olema võimeline vaid makrote  väärtuste muutmise peale kohanduma uute vahemikega.

Nõutud funktsioonid

Selle ülesande lahenduse raames peaksid looma kolm funktsiooni

  • Kasutaja sisendi valideerimiseks – kas see oli lubatud vahemikus
  • Isiku vanusegrupi indeksi leidmiseks. Grupi indeks tuleb tagastada funktsiooni poolt ja salvestada  idx  muutujasse.
  • Tulemuste väljastamiseks.

Võid luua ka neljanda funktsiooni, et programm struktuuri veelgi paremaks muutuja. Selleks sobiks algkoodis main funktsioonis oleva lõpmatu tsükli viimine eraldi funktsiooni.

Programmi struktuur

Oleme andnud sulle ette programmi üldise struktuuri koos vajalike makrotega. Peaksid neid kasutama, et programm

Algoritm

Oleme ka kirjeldanud ära suurema osa algoritmist, mis sul realiseerida tuleb. Mõned arvutused oleme sulle ka siiski jätnud välja mõelda – näiteks kuidas leida vanusevahemike otspunktid väljundis ning  ka veidi massiivi indekseerimist.

Näidis

Siin on näha programmi üldine käitumine. Näha on ka silumise jaoks tehtud lisaväljatrükk mis algab DEBUG  trükkimisega – see on kasulik enesekontrolliks mis massiivi indeks lõpuks välja arvutati – st mis loendurit lõpuks ikkagi suurendati.  Valmisprogrammis seda olema ei pea, kuid arenduse juures tasub kindlasti välja trükkida erinevaid väärtusi enesekontrolliks!

NB! Kui testid oma rakendust, proovi muuta makrosid GROUPS  ja GROUP_STEP  ning veendu, et kogu programm kohandub muudatustele!