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, siis mõne omadusega teeme juba täna tutvust.

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"

Üksiku tähemärgi kirjutame ülakomade vahel. Sõne koosneb sellistest tähemärkidest. NB! Kaldkriipsuga hakkavad erisümbolid (escape sequence) ja neid loetakse samuti üheks tähemärgiks kuna neid kodeeritakse ühe tähemärgina (nt \n  on üks tähemärk arvuti mälus kuna võtab vaid ühe baidi).

Näited:

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

NB! Pane tähele, et "a"  ja 'a'  on erinevad. Üks on sõne, teine on tähemärk.

Funktsioonid, mida saame kasutada teksti väljastamiseks

  • printf()  ehk print formatted. Tegu on kõige keerukama funktsiooniga seniõpitutest, mille abil saame trükkida kujundatud teksti ja väljastada ka kõiksugu muutujate sisu. 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 kolmest. 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 funktsioonidese 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 mõõtmete suurused. Pärast funktsiooni edastamist ei ole võimalik massiivi mõõtmeid arvutuslikult leida! Erandiks on sõned (string), millest räägime tulevikus.

Mõned eripärad edastamisel

  • Kui soovid edastada tervet massiivi, olenemata selle mõõtmete arvust, kirjutame väljakutsesse vaid  massiivi nime Func(numbers);
  • Kui soovid 1-mõõtmelist 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-mõõtmelisest massiivist ( int numbers[N][M];  edastada ühe rea (tehniliselt kirjeldatuna vastava rea alguse asukoha mälus), täpsustame selle indeksi ja pikkuse Func(numbers[2], M); . Funktsioonis käsitle seda kui 1-mõõtmelist massiivi  Func(int numbs[], int n);
  • Kui soovid 2-mõõtmelisest massiivist int numbers[N][M];  edastada vaid ühe väärtuse, täpsustame funktsiooni väljakutses mõlemad indeksid Func(numbers[2][1]);

Kahe arvu omavahel vahetamine massiivis

Vahetamaks kahte arvu sobib lahenduseks sorteerimise 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). See on kusjuures levinud lähenemine ka kõiksugustes tehisaru põhistes lahendustes, mis on suuresti lihtsalt maatriksarvutused, mille põhimõtteid lineaaralgebras.

Massiivide algväärtustamine nulliks

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

Kui tegu on 2-mõõtmelise massiiviga, kasutame kahte komplekti loogelisi sulge.

Esitamisele kuuluvad ülesanded

Selles tunnis loome menüüprogrammi, mis töötab senikaua, kuniks kasutaja soovib sellest väljuda. Programmi raames tegeleme maatriksi manipuleerimisega. Programmi keskmes on mitmed piirjuhtumid (näiteks mis saab siis, kui kasutaja soovib manipuleerida maatriksit, mida ei ole olemas).

Alusta näidisprogrammiga tutvumisest, misjärel saad edasi liikuda ja luua ise samalaadse rakenduse.

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 arvutiklassi arvutitel, 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 (see on tingitud turvalisuse nõuetest!). Õ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 lisada kolm lisaülesannet

Tegu on programmiga, mis töötab kuniks kasutaja soovib sellest väljuda. St menüü asub tsükli sees, millest väljumiseks on eraldi käsk. Lisaks peame seetõttu programmi tegevusi tehes jälgima, mis seisundis maatriks parasjagu on – nt ridu ei saa vahetada maatriksil, millel pole ühtegi rida.

Maatriksi maksimaalne suurus mälus on fikseeritud makrotega LIMIT_ROWS ja LIMIT_COLS , mis määravad vastavalt maksimaalse ridade ja veergude arvu. Need peavad rakendusse jääma sisse ja olema kasutusel – nt kaitsmise käigus palume sul muuta neist vaid ühte suurust!

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 ja põhjendatud!
    • Aluskoodis on sinu jaoks juba valmis tehtud 2 funktsiooni, kasuta neid vastavalt vajadusele.
    • Aluskoodis on ette antud kahe esimese sinu poolt loodava funktsiooni prototüübid, millest peaksid oma lahenduse loomist alustama.
  • Rakendus peab töötama ka olukorras, kus ridade ja veergude arvud on erinevad, st tegu pole ruutmaatriksiga.
  • Kõik maatriksis olevad arvud on 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()  lause sees võid julgelt printida välja abiteksti, salvestada funktsioonidest tagastatavaid väärtusi jne. Vajadusel võid ka mõne if  lause lisada.
    • Ära deklareeri switch() sees uusi muutujaid!
    • Uusi tsükleid main()  funktsiooni kirjutada ei tohi!
  • Programm peab olema terviklik ja arusaadav ning töötama, kuniks kasutaja soovib sellest ise väljuda.

Tunnitöö osa 1 [W10-1]: Maatriksi genereerimine ja kuvamine

Esimeses osas loome maatriksi kuvamise ja genereerimise. Ülesande raames harjutad ka kindlat tüüpi tsüklite kasutamist!

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 [W10-2]: Ridade ja veergude vahetamine

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

  • Kasutaja peab saama vahetada kaks enda valitud rida omavahel
    • 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
  • Konstantide vale kasutamine – muuda maksimaalne ridade või veergude arvu määrav makro ära ja testi oma rakendust

Lisaülesanne 1 [W10-3]: 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 tuuakse 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 [W10-5]: 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
  • Eristama tähemärki ja sõnet
  • Oskama edastada ja funktsioonis vastu võtta
    • tervet maatriksit
    • maatriksi ühte rida
    • maatriksi ühte elementi

Täiendav materjal