Labori materjal
- Slaidid: Standardvood
- Slaidid: Pseudojuhuarvud
- Täiendav: voo suunamise juhend
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 .
- NB! Kuupäevade formaadid on konkreetselt määratletud.
https://en.wikipedia.org/wiki/Date_format_by_country
- NB! Kuupäevade formaadid on konkreetselt määratletud.
- 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!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
14041805 26052100 31012015 30092011 01012001 31062011 32011999 00012011 01002023 01132033 29022022 28022022 28022000 29022000 29022004 29021900 |
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:
- Programmikood (nt date.c )
- 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!
Veendume, et failid on kõik seal, kus peaks kasutades käsku ls -l :
1 2 3 4 5 |
INTRA\risto.heinsar@lx27:~/P/date> ls -l total 18 -rwxr-xr-x 1 INTRA\risto.heinsar INTRA\domain users 12732 Oct 6 14:11 date -rwxr-xr-x 1 INTRA\risto.heinsar INTRA\domain users 536 Oct 5 15:50 date.c -rwxr-xr-x 1 INTRA\risto.heinsar INTRA\domain users 73 Oct 6 14:11 input.txt |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
INTRA\risto.heinsar@lx27:~/P/date> ./date < input Dates read: 16 14.04.1805 26.05.2100 31.01.2015 30.09.2011 01.01.2001 31.06.2011 32.01.1999 00.01.2011 01.00.2023 01.13.2033 29.02.2022 28.02.2022 28.02.2000 29.02.2000 29.02.2004 29.02.1900 |
Testimine: valmislahendus
Pärast programmi valmimist peaks su väljund nägema välja samasugune nagu siin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
INTRA\risto.heinsar@lx27:~/P/kp> ./date < input Dates read: 16 14.04.1805 < Invalid date! 26.05.2100 < Invalid date! 31.01.2015 < OK 30.09.2011 < OK 01.01.2001 < OK 31.06.2011 < Invalid date! 32.01.1999 < Invalid date! 00.01.2011 < Invalid date! 01.00.2023 < Invalid date! 01.13.2033 < Invalid date! 29.02.2022 < Invalid date! 28.02.2022 < OK 28.02.2000 < OK 29.02.2000 < OK 29.02.2004 < OK 29.02.1900 < Invalid date! |
Ülesanne 2: loto
Lae alla ülesande aluskood:
- Eestikeelsete kommentaaridega: https://blue.pri.ee/ttu/files/iax0583/aluskoodid/8_2_loto_base.c
- Ingliskeelsete kommentaaridega: https://blue.pri.ee/ttu/files/iax0583/aluskoodid/8_2_loto_base_en.c
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Enter lottery number [1 ... 25] (1 / 6): 1 Enter lottery number [1 ... 25] (2 / 6): 3 Enter lottery number [1 ... 25] (3 / 6): 5 Enter lottery number [1 ... 25] (4 / 6): 13 Enter lottery number [1 ... 25] (5 / 6): 14 Enter lottery number [1 ... 25] (6 / 6): 15 User numbers are 1 3 5 13 14 15 Lottery numbers are 17 18 10 1 20 25 4 9 13 15 Winning number: 1 Winning number: 13 Winning number: 15 Matched 3 out of 6! |
Test 2: Võidunumbrid puuduvad
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Enter lottery number [1 ... 25] (1 / 6): 11 Enter lottery number [1 ... 25] (2 / 6): 12 Enter lottery number [1 ... 25] (3 / 6): 14 Enter lottery number [1 ... 25] (4 / 6): 21 Enter lottery number [1 ... 25] (5 / 6): 22 Enter lottery number [1 ... 25] (6 / 6): 23 User numbers are 11 12 14 21 22 23 Lottery numbers are 17 18 10 1 20 25 4 9 13 15 Matched 0 out of 6! None of the numbers matched. Better luck next time! |
Test 3: Jackpot
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Enter lottery number [1 ... 25] (1 / 6): 17 Enter lottery number [1 ... 25] (2 / 6): 18 Enter lottery number [1 ... 25] (3 / 6): 10 Enter lottery number [1 ... 25] (4 / 6): 1 Enter lottery number [1 ... 25] (5 / 6): 20 Enter lottery number [1 ... 25] (6 / 6): 25 User numbers are 17 18 10 1 20 25 Lottery numbers are 17 18 10 1 20 25 4 9 13 15 Winning number: 17 Winning number: 18 Winning number: 10 Winning number: 1 Winning number: 20 Winning number: 25 Matched 6 out of 6! Congratulations! You won the jackpot! |
Test 4: Vigane sisestus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Enter lottery number [1 ... 25] (1 / 6): -5 Invalid number! Retry: 5 Enter lottery number [1 ... 25] (2 / 6): 26 Invalid number! Retry: 27 Invalid number! Retry: -4 Invalid number! Retry: 6 Enter lottery number [1 ... 25] (3 / 6): 7 Enter lottery number [1 ... 25] (4 / 6): 8 Enter lottery number [1 ... 25] (5 / 6): 9 Enter lottery number [1 ... 25] (6 / 6): 10 User numbers are 5 6 7 8 9 10 Lottery numbers are 17 18 10 1 20 25 4 9 13 15 Winning number: 9 Winning number: 10 Matched 2 out of 6! |
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.
1 |
#define MAX_LOTTO 1 |
Antud testi juures saame jälgida kusjuures kahte erinevat asja
- Jälgi võitude arvu! St Matched 6 out of 6!)
- Jälgi lototroni genereeritud numbreid. Need tohivad olla vaid ühed! (0 või 2 esinemine tähendab, et sul on viga juharvude valemi koostamisel!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Enter lottery number [1 ... 1] (1 / 6): 1 Enter lottery number [1 ... 1] (2 / 6): 1 Enter lottery number [1 ... 1] (3 / 6): 1 Enter lottery number [1 ... 1] (4 / 6): 1 Enter lottery number [1 ... 1] (5 / 6): 1 Enter lottery number [1 ... 1] (6 / 6): 1 User numbers are 1 1 1 1 1 1 Lottery numbers are 1 1 1 1 1 1 1 1 1 1 Winning number: 1 Winning number: 1 Winning number: 1 Winning number: 1 Winning number: 1 Winning number: 1 Matched 6 out of 6! Congratulations! You won the jackpot! |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
INTRA\risto.heinsar@lx27:~/P/kp> ./date_adv < input Dates read: 16 14.04.1805 < Year out of range! 26.05.2100 < Year out of range! 31.01.2015 < OK 30.09.2011 < OK 01.01.2001 < OK 31.06.2011 < Day exceeds maximum days for given month! 32.01.1999 < Day exceeds maximum days for given month! 00.01.2011 < Day before first of month! 01.00.2023 < No such month exists! 01.13.2033 < No such month exists! 29.02.2022 < 29th of February only exists on leap year! 28.02.2022 < OK 28.02.2000 < OK 29.02.2000 < OK 29.02.2004 < OK 29.02.1900 < 29th of February only exists on leap year! |
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
- Kasutaja lotonumbrite unikaalsuse kontrolliks
- Lototroni genereeritud võidunumbrite unikaalsuse kontrolliks
- Kasutaja ja lotoarvude kattuvuse leidmise funktsioonis FindMatchCount()
Testimine
Test 1: Kontrollime unikaalsuse nõuet kasutajale
NB! Kontrolli kindlasti kasutades sama jada!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Enter lottery number [1 ... 25] (1 / 6): 1 Enter lottery number [1 ... 25] (2 / 6): 2 Enter lottery number [1 ... 25] (3 / 6): 3 Enter lottery number [1 ... 25] (4 / 6): 4 Enter lottery number [1 ... 25] (5 / 6): 3 You've already entered this number! Retry: 2 You've already entered this number! Retry: 1 You've already entered this number! Retry: 5 Enter lottery number [1 ... 25] (6 / 6): 6 User numbers are 1 2 3 4 5 6 Lottery numbers are 17 18 10 1 20 25 4 9 13 15 Winning number: 1 Winning number: 4 Matched 2 out of 6! |
Test 2: Kontrollime unikaalsuse töötamist lototroni poolt
Selleks, et kontrollida lototroni tööd peame me jällegi manipuleerima konstante.
1 |
#define MAX_LOTTO 10 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Enter lottery number [1 ... 10] (1 / 6): 1 Enter lottery number [1 ... 10] (2 / 6): 2 Enter lottery number [1 ... 10] (3 / 6): 3 Enter lottery number [1 ... 10] (4 / 6): 4 Enter lottery number [1 ... 10] (5 / 6): 5 Enter lottery number [1 ... 10] (6 / 6): 6 User numbers are 1 3 4 5 6 Lottery numbers are 2 8 5 1 10 9 3 6 7 4 Winning number: 1 Winning number: 2 Winning number: 3 Winning number: 4 Winning number: 5 Winning number: 6 Matched 6 out of 6! Congratulations! You won the jackpot! |
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
- Boolean type support library
https://en.cppreference.com/w/c/types/boolean - What is a leap year
https://www.timeanddate.com/date/leapyear.html - Standard streams
https://en.wikipedia.org/wiki/Standard_streams - Redirection
https://en.wikipedia.org/wiki/Redirection_(computing) - Pseudorandomness
https://en.wikipedia.org/wiki/Pseudorandomness - Why does Cloudflare use lava lamps to help with encryption? (üks võimalik lahendus pseudojuhuslikkuse probleemile)
https://www.cloudflare.com/learning/ssl/lava-lamp-encryption/ - Unix time
https://en.wikipedia.org/wiki/Unix_time - Unixi praegune kellaaeg ja selle teisendi
https://www.unixtimestamp.com - rand() and srand() in C/C++
https://www.geeksforgeeks.org/rand-and-srand-in-ccpp/ - time.h library in C
https://www.cplusplus.com/reference/ctime/