PR1ET4: Funktsioonid

Labori materjal

Esitamisele kuuluvad ülesanded

Selles laboris on kokku kolm ülesannet. Kõigil ülesannetel on antud koodipõhi, mis määrab ära ülesande üldise struktuuri ja annab sulle ettemääratud töövoo. Töövoog on antud samm-sammuliste juhenditena, alguses täpsemalt, lõpupoole üldisemalt.

Ülesandeid 2 ja 3 on võimalik laiendada lisaülesannetega.

Ülesanne 1: Elektri hinna kalkulaator

Antud ülesandes on sinu eest juba kogu programmi loogika valmis tehtud. St kogu main()  funktsiooni sisu on juba valmis ja seda muuta ei ole põhjust.

Tegemata on jäetud aga enda loodavate (user-defined) funktsioonide sisud ning need on vastavalt asendatud kõik tagastama 0 väärtust (selleks, et programm kompileeruks). Sinu ülesandeks täita kõigi funktsioonide deklaratiivne osa (keha) vastavalt funktsioonile eelnevale kommentaarile.

Lae alla ülesande aluskood; https://blue.pri.ee/ttu/files/iax0583/aluskoodid/4_1_electricity_template.c

Nõuded

  • Ülesande lahendamist alusta baaskoodiga tutvumisest. Sinu lahendus peab olema ehitatud ette antud baaskoodile.
  • Sinu ülesandeks on kirjutada funktsioonide kehad seitsmele funktsioonile. Funktsiooni eesmärk on kirjeldatud selle ees kommentaarina.
  • main()  funktsiooni sisu ja koodi struktuuri muuta ei tohi. Soovitav on vältida ka funktsioonide ja muutujate ümbernimetamist.

Vihjeid ja soovitusi

  • Alusta tutvumist koodi ülesehitusest. Vaata kus on makrod, kus prototüübid, kus main() ja kus funktsioonid. Vaata kuidas main() funktsioonist teisi funktsioone välja kutsutakse, mis kaasa antakse jne. Ära muuda midagi alguses!
  • Üldine pilt selge, hakka järjest funktsioonide sisusid täitma.  Lahenda 1 funktsioon korraga, kompileeri ja testi enne kui järgmise juurde lähed!
  • Sisestuse funktsioonides on soovitatav struktuur do while tsükkel, mille sees on if lause veateate väljastamiseks.
  • Kõik ülejäänud funktsioonid on lahendatavad ühe reaga, asendades olemasoleva return 0  asemel õige valemi
  • Ettevaatust ühikutega. Erinevates kohtades on kord kasutusel vatt-tunnid, kord kilovatt-tunnid, kord megavatt-tunnid! Juhindu funktsiooni kommentaaridest.
  • VAT – value added tax tähendab käibemaksu (Eestis 20%)
  • Jooksev börsihind MWh kohta (enne makse) on leitav https://dashboard.elering.ee/et
  • Jooksvat börsihinda kWh kohta sentides koos maksudega näitab https://www.elektrikell.ee

Testimine

Test 1: veavaba sisend

Test 2: vigadega sisend

Ülesanne 2: Arvujadade generaator

Selle ülesande raames tuleb koostada programm, mis sisaldab endas kahte arvujada generaatorit, aritmeetilise ja geomeetrilise jada genereerimiseks. Ülesannet laiendab lisaülesanne, mille raames lisatakse algarvude generaator ja muudetakse programmi väljundit kenamaks.

Jälgi ülesande lahendamisel samm-sammulist juhendit.

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

Nõuded

  • Funktsioonide lahendamisel juhindu funktsiooni kommentaarist ja siin lehel olevast samm-sammulisest juhendist.
  • Programm peab suutma genereerida aritmeetilist ja geomeetrilist jada vastavalt etteantud sisenditele.
  • Kasutaja peab saama valida kumba generaatorit kasutada ning sisestada sellele parameetrid (algväärtus, vahe või tegur ja sammude arv).
  • Jada algväärtus, geomeetrilise jada tegur ja aritmeetilise jada tegur sisestatakse kümnendmurruna.
  • Jada liikmed kuva kahe komakohaga.

Samm-sammuline juhend

  1. Kompileeri aluskood. Proovi seda, vaata mis ta teeb. Loe kood läbi.
  2. Lisa main()  funktsiooni väljakutse funktsioonile  PrintMenu() . Väljakutse asukoht on märgistatud TODO kommentaarina. Kirjuta väljakutse kommentaarist järgmisele reale. Proovi – kui töötab, kustuta TODO kommentaar ära.
    KOMPILEERI JA TESTI, ET TEHTU TÖÖTAB ENNE EDASI LIIKUMIST!
  3. Kirjuta funktsiooni  PrintSeparator()  sisu. Selleks pead kirjutama tsükli,  mis trükib   #  sümbolit  täpselt nii mitu korda  kui oli ette antud funktsiooni parameetriga.
    KOMPILEERI JA TESTI, ET TEHTU TÖÖTAB ENNE EDASI LIIKUMIST!
  4. Lõpeta funktsioon  PrintAsciiWelcomeMsg()  , pannes see väljastama endale meelpärast ASCII kunsti (pilt, tekst, …). Võid näiteks kasutada ka pildi teisendajaid ASCII kunstiks või kasutada mõnda teost internetis olevatest galeriidest.
    KOMPILEERI JA TESTI, ET TEHTU TÖÖTAB ENNE EDASI LIIKUMIST!
    Vihje: Internetis on mitmeid ASCII galeriisid ja teisendajaid. Üks nest on kättesaadav siit: https://www.asciiart.eu
    NB! Osad tähemärgid omavad erilist tähendust ja neid ei saa niisama lihtsalt ekraanile manada. Sellisteks on näiteks  \  (escape sequence) ja  %  (formaat ehk format specifiers). Nende väljastamiseks peame  \  asemel kirjutama  \\  ja  %  asemel  %%. Kõige lihtsam viis (kui selliseid sümboleid on palju) on teha Geanys uus fail, panna oma kunstiteos sinna ja kasutada kogu dokumendi ulatuses asendust (kiirklahv ctrl+h avab menüü, valik replace all in document).
  5. Nüüd mine ArithmeticSequence()  funktsiooni juurde.
    1. Deklareeri puuduvad muutujad (3 tk kokku, ettevaatust andmetüüpidega!)
    2. Lisa kasutajale päringud ja loe väärtused loodud muutujatesse.
    3. Lisa funktsiooni  ArithmeticSequenceGenerator()  väljakutse koos vajaminevate parameetritega.
      NB! Märka, et funktsioon ArithmeticSequenceGenerator()  on koodist välja kommenteeritud! Seda tegime selleks, et vähendada liigseid kompilaatori hoiatusi mis võivad summutada muud olulised hoiatused ja veateated sinu jaoks. Kuniks sa seda funktsiooni sisse ei kommenteeri, annab kompilaator sulle  “undefined reference” veateate ja programm ei kompileeru. Kommenteeri see funktsioon sisse, et saaksid testimise läbi viia (hetkel veel tulemusteta)!
      KOMPILEERI JA TESTI, ET TEHTU TÖÖTAB ENNE EDASI LIIKUMIST!
  6. Liigu edasi funktsiooni ArithmeticSequenceGenerator()  juurde ja lõpeta see. Sul on vaja kirjutada üks tsükkel, mille sisse tuleb paigutada 2 lauset
    1. Väljasta praeguse jada liikme väärtus.
    2. Arvuta järgmise jada liikme väärtus.
      NB! Järjekord on oluline!
      Vihje 1: järgmine_väärtus = praegune_väärtus + vahe Vihje 2: Sul ei ole tegelikult vaja siin funktsioonis ühtegi uut muutujat deklareerida peale tsükliloenduri. . Kindlast väldi massiivide kasutamist (teema järgnevateks nädalateks).
      KOMPILEERI JA TESTI, ET TEHTU TÖÖTAB ENNE EDASI LIIKUMIST!
  7. Menüüs, mis on realiseeritud  switch ()  lausena, on valmis kirjutatud vaid üks case . Lisa veel 2 puuduolevat menüü valikut ja nendele vajaminevad laused. Vajaminevad käsud on kirjeldatud menüüs ( PrintMenu()  funktsioonis)
  8. Samal viisil nagu lahendasid aritmeetilise jada genereerimise funktsioonid tuleb nüüd lahendada ka geomeetrilise jada genereerimiseks vajaminevad funktsioonid.

Nüüd peaks ülesanne lahendatud olema. võrdle oma väljundit etteantud testjuhtudega!

Testimine

Testi kindlasti kõiki kolme menüü valikut ning ka tundmatut sisendit!

Testime aritmeetilist jada

Testime geomeetrilist jada

Lahkume ilma jada genereerimata

Ülesanne 3: Vastuvõtuaegade planeerimine

Selles üleandes lood lihtsa generaatori millega saab luua ajavahemike vastuvõtuaegade planeerimiseks

Lae alla aluskood: https://blue.pri.ee/ttu/files/iax0583/aluskoodid/4_3_timetable_template.c

Soovitus: Enne ülesande lahendamist loe läbi ja mõtesta enda jaoks  lahti etteantud algoritm (pärast nõudeid)! Kui tekib segadus, soovitan piiluda sisse lähenemise peatükki.

Nõuded

  • Tööpäeva algus on määratud makrona
  • Kasutaja sisestab klientide arvu ning ühe kliendikohtumise kestvuse
  • Programm genereerib kliendikohtumiste kellaajad. Ajad on järjestikused.
  • Minimaalselt peavad olema realiseeritud ja kasutatud aluskoodis antud funktsioonid. Funktsioone võid juurde luua.
  • Genereeritud ajad peavad olema reaalsed
  • Väljund peab olema visuaalselt joondus
  • Aluskoodis on kõigi funktsioonide kohta on antud vaid nende nimed. Sa pead määrama nende tagastatava andmetüübi ja parameetrid. Kui parameetrid puuduvad, siis tuleb sulgudesse kirjutada void .

Algoritm

Lähenemine

Sel korral on lähtekood juba üsna õhuke, kuid sisaldab siiski struktuuri kuidas oleks mõistlik see programm funktsioonideks tükeldada.

Iga funktsiooni puhul mida lahendad, alusta selle tagastuse andmetüübi ja parameetrite loetelu määramisest. Need on sulle ette antud funktsiooni kommentaarina. Kui see on tehtud, lisa funktsiooni prototüüp enne main() funktsiooni. Seejärel kirjuta funktsiooni kena ning lisa funktsiooni väljakutse sobilikku kohta.

Ava mind vihjete nägemiseks
  • Esmalt alusta asjadest, mis on juba koodis kasutusel ja/või poolikult realiseeritud. Sellisteks funktsioonideks on  PrintTime()  ja PrintTimeInterval() . Need peaksid olema üsna lihtsad realiseerida ja saad mõned häirivad hoiatused eest ära.
  • Nüüd realiseeri GetPositiveInt()  funktsioon. Selle funktsiooni oled juba eelnevate tunnitööde raames teinud. Määra tagastuse tüüp ja funktsiooni parameetrid ning kopeeri eelnevast ülesandest kood sisse. Seejärel saad funktsiooni kasutada nii klientide arvu kui kliendikohtumise kestvuse lugemiseks.
  • Järgmisena tuleks alustada tööd funktsiooni  PrintTimetable()  kallal. Kutsu see funktsioon main() -ist välja. Funktsiooni sisse loo tsükkel klientide ja nende kellaaegade väljastamiseks. Ära kellaaegade peale veel mõtle, veendu lihtsalt, et kliendide loetelu kuvataks korrektselt.
  • Kellaaegade saamiseks tuleb lahendada funktsioonid  CalcNextHour()  ja CalcNextMin() . Mõlemad funktsioonid on lahendatavad ühe reaga, pead vaid vaid piisavalt täpse matemaatilise tehte välja mõtlema ja tulemuse tagastama.
    Vihje: Sa saad nende funktsioonide töötamist testida ka eraldiseisvalt ülejäänud koodist. Näiteks kutsudes funktsioon välja
    CalcNextHour(8, 0, 50)  peab tagastatavaks väärtuseks olema 8 ning CalcNextHour(8, 0, 70)  puhul 9. Sarnaselt peab teise funktsiooni korral CalcNextmin(8, 0, 50)  tagastama 50 ja  CalcNextmin(8, 0, 70)  korral 10.
  • Nüüd mine tagasi funktsiooni   PrintTimetable()  ja hakka sinna kirjutatud tsüklit sisustama. Vaata kindlasti algoritmi võrdluseks.
    NB! Funktsiooni korrektseks tööks on sul vaja teada nii kohtumise alguskellaaega (märgitud kui hetkeaeg – current time) kui lõpukellaaega. Kui need 4 väärtust on teada, kasuta neid funktsiooni PrintTimeInterval()  väljakutses.
  • Nüüd on aeg testimiseks ja vajadusel silumiseks. Kõik jupid koodist on valmis. Veendu, et need töötavad ootuspäraselt.

Testimine

Testime vaid minuti ületäitumisega

Testime tundide ületäitumist

Testime kõiki ületäitumisi korraga ja mitmekordselt

Lisaülesanded

Selles laboris on kaks lisaülesannet, vastavalt teisele ja kolmandale baasülesandele.

Lisaülesanne 1: Algarvude generaator ja rea pikkuse piiramine

Tegu on laiendusega baasülesandele.

Nõuded

  • Kasuta lahendatud laboriülesannet selle töö põhjaks
  • Lisa algarvude generaator. Kasuta järgmises punktis etteantud funktsiooni enda lahenduse koostamisel.
  • Lisa limiit mitu tulemust ühe rea kohta generaatorid kuvavad. Leia enda programmile sobilik limiit.
    Alternatiivina võid teha programmi kenamaks, piirates hoopiski väljastatavat tähemärkide arvu. Selleks tuleb loendada väljastatavaid tähemärke. Üks võimalikest abistatavatest funktsioonidest võiks olla snprintf() .

Funktsioon algarvude tuvastamiseks

Kasuta järgnevat funktsiooni testimaks kas tegu on algarvuga või mitte. NB! Märka, et pead lisama enda koodi ka IS_PRIME makro!

Vihje: Funktsiooni tagastust saad kontrollida otse if  lause tingimuses.  https://blue.pri.ee/ttu/coding-guides/conditional-statements/#Function_calls_in_conditionals

Testimine

NB! Märka, et sel korral on näidatud kahte erinevat lahendust. Mõlemad on korrektsed ja aktsepteeritavad lahendused sellele ülesandele. Sa pead näitama neist vaid ühe.

Teine ülesanne on antud inspiratsiooniks kui soovid väheke rohkem pead murda ja teha väljund veelgi kenamaks.

Test: Väljundis piiratud tulemuste arv

Test: väljundis piiratud tähemärkide arv

Lisaülesanne 2: Lisa puhkepausid ja mitmele päevale ulatuv planeerimine

Tegu on laiendusega baasülesandele.

Nõuded

  • Kasuta lahendatud laboriülesannet selle töö põhjaks
  • Lisa kasutaja poolt seadistatav paus iga kliendikohtumise vahele (nt 10 minutit).
  • Lisa tööpäeva lõpu kellaaeg. Kui kliendikohtumine ületaks seda aega, siis planeeri kohtumine hoopis järgmisse päeva. Kui kohtumiste plaan osutub mitmepäevaseks, näita iga päeva ees ka päeva numbrit.

Testimine

Näide oodatavast väljundist kui broneering läheb mitmepäevaseks koos pausidega.

Pärased tundi peaksid

  • Teadma lihtsamaid polsterdamise ja joondamise võimalusi
    • Täisarvude polsterdamine nullide või tühikutega
    • Kümnendmurdude polsterdamine
    • Sõnede polsterdamine ja joondamine
    • Liigpikkade sõnelõppude ära lõikamine
  • Teadma mis erinevus on lokaal- ja globaalmuutujal
  • Teadma mis on funktsioon ja mis on nende olulisus programmeerimisel
  • Saama aru, et tegelikult kasutasime juba esimesest nädalast peale funktsioone.
  • Mõistma järgmisi mõisteid
    • Funktsiooni prototüüp
    • Funktsiooni tagastuse tüüp
    • Funktsiooni argumendid
    • Funktsiooni parameetrid
    • Funktsiooni päis
    • Funktsiooni keha
  • Oskama ise koostada funktsioone (kasutaja-defineeritud funktsioonid)
  • Oskama väärtusi (konstandid, makrod, muutujate kaudu) edastada funktsioonidesse
  • Oskama salvestada funktsioonist tagastatavat väärtust
  • Oskama oma koodi tükeldada funktsioonideks
  • Omama väikest kogust universaalseid funktsioone, mida saad kasutada tulevikus järgnevate programmide koostamisel! See loetelu hakkab iga nädalaga laienema.

Täiendav materjal