Labori materjal
- Sel nädalal tegeleme eelkõige teadmiste kinnistamise ja harjutamisega
- Sissejuhatus siluri kasutamisse
- Tutvu algoritmide ülesannetega – selliseid näed ka kontrolltöös.
Teooriakild 1: Teksti edastamine funktsiooni
Sageli võib tekkida olukord, kus funktsioon ise oleks justkui kenasti korduvkasutatav, kuid kasutajale kuvatav tekst ei sobi. See on tüüpiline üldiste sisend- ja väljundfunktsioonide puhul.
Üks viis seda lahendada on see mida varem tegid – trükkisid teksti enne sisendi/väljundiga tegeleva funktsiooni väljakutset (nt loe arv, loe massiiv, väljasta massiiv). See jääb jätkuvalt mu soovituseks enamikes olukordades. Sedasi on sul vähem keerukust funktsioonis ja funktsioon jääb kergemini korduvkasutatavaks.
Teise valikuna pakun välja alternatiivi, mis on funktsioonide koostamise mõttes üsna tavapärane. Vaatame ühte põhilist ideed millal funktsioon luua – Kui kahe koodilõigu vahel on marginaalne erinevus, mis sunnib sind koodi kopeerima, siis lahenda erinevused kasutades funktsiooni parameetreid. See saab meie ka meie lahenduseks – me saame väljastatava teksti või osa tekstist (nt sõna) edastada parameetrina.
Selline meetod töötab üsna hästi kui kasutajale on vaja selgitada mida ta sisestama peab (st mida programm ootab temast). Samuti sobib see enamasti ka näiteks massiivi väljastamisel kui on vaja väljastuse ette panna kirjeldus.
NB! Kaks olulist mõtet veel! Mõlemast neist räägime süviti semestri teises pooles.
- Tekst on samamoodi massiiv – see on tähemärkidest koosnev massiiv. Igal tähemärgil on kusjuures oma indeks.
- Erinevalt numbrimassiividest ei ole tekstimassiivi puhul meil selle väljastamiseks vajalik pikkust eraldi kaasa anda (pärast viimast sümbolit kasutatakse erisümbolit, mis annab märku kui string ehk sõne lõpeb).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <stdio.h> #define DEFINED_STRING "Passing by using a macro" void PrintPassedText(char text[]); int main(void) { PrintPassedText("Passing by using a constant"); PrintPassedText(DEFINED_STRING); char inputString[] = "Passing by using a variable"; PrintPassedText(inputString); } void PrintPassedText(char text[]) { /* To print double quotes, they need to be escaped first! */ printf("Text passed to this function: \"%s\"\n", text); } |
Teooriakild 2: Massiivi vs massiivi liikme edastamine
Eelmises tunnis tutvustasime kuidas peaks massiivi edastamine funktsiooni. Oluline oli
- Massiiv edastatakse alati viitena originaal asukohale
- Massiivi sisu saime muuta ka alamfunktsioonides, kehtis kõikjal
- Massiiviga tuleks kaasa anda selle pikkus
- Massiivi edastades kasutame vaid selle nime, ilma ühegi täiendava märgendita.
Samuti meeldetuletuseks, kasutades massiivi nime järel kantsulge keset koodi indekseerime me selle massiivi konkreetset liiget.
Siit saame kokku ka järgmise näite, kus võrdleme massiivi vs üksiku liikme edastust massiivist.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include <stdio.h> #define ARR_LEN 5 void PrintNum(int num); void PrintIntArray(int arr[], int len); int main(void) { int nums[ARR_LEN] = {9, 24, -2, 3, 25}; /* Passing an entire array */ PrintIntArray(nums, ARR_LEN); /* Passing the second number in the array */ PrintNum(nums[1]); /* Passing the fourth number in the array */ PrintNum(nums[3]); } void PrintNum(int num) { printf("Passed number: %d\n\n", num); } void PrintIntArray(int arr[], int len) { printf("Numbers are: "); for (int i = 0; i < len; i++) { printf("%d ", arr[i]); } printf("\n\n"); } |
Esitamisele kuuluvad ülesanded
Selles tunnis tuleb lahendada kaks ülesannet. Täiendavalt on pakutud välja lisaülesanded täiendavate punktide teenimiseks.
Ülesanne 1: Uute massiivide koostamine
Antud ülesanne põhineb suuresti algoritmiülesandel. Vastav ülesanne on püstitatud siin: https://blue.pri.ee/ttu/programmeerimine-i/algoritmide-ulesanded/#Algoritm_3_Negatiivsete_ja_positiivsete_arvude_umberjarjestus
Selle algoritmi lahendus on sulle ette antud. Ülesandele on lisatud algoritmis puuduvaid täiendusi.
Algoritm
Nõuded
- Programm peab põhinema etteantud algoritmil.
- Kasutajalt loetakse 6 arvu ja salvestatakse need massiivi
- Programmi vältel koostatakse teine samapikk massiiv põhimõttel negatiivsed numbrid ettepoole, positiivsed nende järel. Arvu 0 loetakse positiivseks arvuks.
- Programmi vältel koostatakse ka kolmas massiiv, kuhu kuuluvad vaid nullist suuremad arvud. Massiivi pikkus võib osutuda lühemaks algsest massiivist.
- Pärast massiivide koostamist väljastatakse järjest kõik 3 massiivi.
- Programm peab endas sisaldama kokku nelja funktsiooni – arvude lugemiseks kasutajalt, arvude ekraanile väljastamiseks, positiivsetest arvudest koosneva massiivi koostamiseks ning etteantud algoritmi alusel järjestatud massiivi koostamiseks.
- Kõik enda loodud funktsioonid peavad olema välja kutsutud main() funktsioonist.
Soovitusi ja vihjeid
Alusta programmi koostamist sisestusest ja massiivi ekraanile kuvamisest. Seda oled juba eelmine kord teinud. Loo vajalik massiiv ja korduvkasuta varasemalt tehtud funktsioone. Kopeerides funktsioone ära unusta ka nendele eelnevat kommentaari kopeerida!
Nüüd lähme ümberjärjestamise juurde. Loo uus massiiv (lisaks olemasolevale), kuhu koostame ümberjärjestatud arvujada. Uue massiivi pikkus on sama nagu esmase massiivi pikkus. Meenuta, et funktsioonist massiivi tagastada ei ole võimalik, seega massiiv tuleb deklareerida main() funktsioonis ja edastada funktsioonile. Ümberjärjestamise ülesande lahendamiseks jälgi etteantud algoritmi, mis oli esitatud veidi ülevalpool.
Seejärel kutsu uuesti välja massiivi väljastamise funktsioon, sel korral ümberjärjestatud massiivi väljastamiseks. St kood võiks funktsiooni väljakutsete mõttes näha välja umbes sarnane (nimed ei ole olulised):
1 2 3 4 5 6 7 8 |
ReadIntArray(inputNumbers, NUM_CNT); CreateRearrangedArra(inputNumbers, rearrangedNumbers, NUM_CNT); printf("Printing the original array: "); PrintIntArray(inputNumbers, NUM_CNT); printf("Printing the modified array: "); PrintIntArray(rearrangedNumbers, NUM_CNT); |
Siinkohal kui soovid oma main() funktsiooni puhtamaks saada, siis tasuks massiivi väljastuse ette minev tekst parameetriga kaasa anda. Selleks vaata esimest teooriakildu!
Nüüd liigu viimase funktsiooni juurde, mis peaks ainult positiivsetest arvudest massiivi koostama. Struktuurilt on koostamine on üsna sarnane eelnevalt tehtud ümberjärjestusele, kuid mõned erinevused siiski eksisteerivad. Kui ümberjärjestatud massiiv oli liikmete arvult samapikk algse massiiviga, siis positiivsete arvude massiiv tuleb suure tõenäosusega lühem. Mõtle, kuidas saada koostatud massiivi pikkus alamfunktsioonist välja, main() funktsiooni! Kui pikkus käes, kutsu jälle main() funktsioonist välja massiivi väljatrükk, et ka kolmas massiiv ekraanile väljastada.
Testimine
Esimese testina proovime tavapärast juhtu, kui arvude hulgas on nii positiivseid kui negatiivseid numbreid.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Enter number 1 / 6: 6 Enter number 2 / 6: -9 Enter number 3 / 6: 3 Enter number 4 / 6: -12 Enter number 5 / 6: 0 Enter number 6 / 6: 4 The original array 6 -9 3 -12 0 4 The rearranged array -9 -12 6 3 0 4 The positive number array 6 3 4 |
Arvesta, et antud olukorras võivad ka positiivsed numbrid puududa. Väljastus peaks jääma jätkuvalt arusaadavaks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Enter number 1 / 6: -1 Enter number 2 / 6: -4 Enter number 3 / 6: -66 Enter number 4 / 6: -97 Enter number 5 / 6: -3 Enter number 6 / 6: -5 The original array -1 -4 -66 -97 -3 -5 The rearranged array -1 -4 -66 -97 -3 -5 The positive number array Empty array |
Ülesanne 2: kahe arvu võrdlus
- Loe 5 täisarvu klaviatuurilt
- Küsi kasutajalt kaks indeksit / järjekorranumbrit.
- Kontrolli, et need oleksid sobilikus vahemikus enne jätkamist! Vajadusel küsi uuesti.
- Numeratsioon peab olema sama nagu sisendit küsides.
- Soovitus: Kontrollimaks et leidsid õiged numbrid, trüki need välja.
- Leia sisestatud positsioonide põhjal nendele vastavad arvud algsest massiivist. Kasutades neid arve tee järgnevat:
- Võrdle neid kahte arvu ning kuva nende omavaheline suhe (väiksem, suurem, võrdne)
- Koosta jagamistehe ning kuva selle vastus. Tehe tuleb koostada sedasi, et suurem arv on jagatav ning väiksem arv on jagaja.
- Vastus anna ühe komakohaga
- Ülesandes on vaja luua neli funktsiooni. Funktsioonid on sulle vähemal või rohkemal määral kirjeldatud järgnevas peatükis.
Loodavad funktsioonid
1. Massiivi lugemine. Selleks korduvkasuta koodi varasematest programmidest. Kopeeri funktsioon koos sellele eelneva kommentaariga.
2. Indeksi lugemine. Selleks tuleks luua uus funktsioon. Loome korduvkasutatava funktsiooni, mida saad tulevikus kasutada igal korral, kui on vaja kasutajalt lugeda täisarv kindlas vahemikus (nt 0 … 5, -10 … 10 jne). Kui tegid eelmine nädal lisaülesande ära, on sul see funktsioon suure tõenäosusega juba olemas.
Pakun välja kaks funktsiooni varianti, Vali kumb meelepärasem tundub ja realiseeri see.
Esimene versioon eeldab, et kasutajale esitatav küsimus küsitakse väljaspool seda funktsiooni.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * Description: Asks the user for an integer in between the given limits. * Repeats until requirements are met and returns the number. * * Parameters: min - lower bound for the user input (inclusive) * max - upper bound for the user input (inclusive) * * Return: number within the specified limits */ int GetIntInRange(int min, int max) { } |
Teine versioon eeldab, et küsimus saadetakse funktsiooni kaasa ja väljastatakse selle sees. Vaata esimest teooriakildu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * Description: Asks the user for an integer in between the given limits. * Repeats until requirements are met and returns the number. * * Parameters: min - lower bound for the user input (inclusive) * max - upper bound for the user input (inclusive) * prompt - prompt for user input, printed before entry * * Return: number within the specified limits */ int GetIntInRange(int min, int max, char prompt[]) { } |
3. Arvude võrdlemine. Siia funktsiooni tuleks edastada 2 arvu, mida võrreldakse omavahel ning väljastatakse kumb neist oli suurem (või olid nad võrdsed). Väljastus toimub funktsioonis sees. Väljastus on kujul “a < b”, “a > b” või “a = b”
NB! Arvude edastamiseks siia funktsiooni vaata teist infokildu!
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * Description: Compares the given values (val1 and val2) and prints * results of the comparison (which is greater; or equal) * * Parameters: val1 - first value being compared * val2 - second value being compared * * Return: - */ void CompareValues(int val1, int val2) { } |
4. Jagatise teostamine. Siia funktsiooni edastatakse samamoodi kaks arvu. Taaskord toimub arvude võrdlemine nagu ka eelmine kord, kuid sel korral määrab võrdluse tulemus jagamistehte operandide järjekorra.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * Description: Compares the given values (val1 and val2). Performs the * division by dividing greater number with the smaller number. * Both division operation and result are printed. * * Parameters: val1 - first value * val2 - second value * * Return: - */ void DivideValues(int val1, int val2) { } |
Näide lahendusest
NB! Näites on nähtavale jäetud silumiseks kasutatavad read (algusega DEBUG), mida soovitan ka sinul alguses teha. Kui oled indeksite põhjal arvude valimises kindel ja kõik töötab, soovitan need välja kommenteerida.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Enter number 1 / 5: 5 Enter number 2 / 5: -5 Enter number 3 / 5: 24 Enter number 4 / 5: 9 Enter number 5 / 5: 1 Enter first index: -5 Error! Index must be within 1 and 5! Enter first index: -7 Error! Index must be within 1 and 5! Enter first index: 0 Error! Index must be within 1 and 5! Enter first index: 4 DEBUG: Corresponding value: 9 Enter second index: 3 DEBUG: Corresponding value: 24 9 < 24 24 / 9 = 2.7 |
Testid
Järgnevalt pakun välja osalise loetelu testidest:
- Proovi koodi sisenditega, mis peaksid andma tulemuse ilma ühegi veata.
- Proovi indekseid, mis on massiivi piiridest väljas. Katseta seda nii esimese kui teise sisendiga.
- Proovi massiivi piiridest välja jäävaid indekseid korduvalt, et programm ei läheks edasi enne kui sobilik sisend on saadud.
- Proovi piirjuhtusid
- Kui loendasid 0 – 4, proovi -1, 0, 4, 5
- Kui loendasid 1 – 5, proovi 0, 1, 5, 6
- Proovi sisendeid, mis testiksid läbi kõik 3 võrdlusjuhtu (<, >, ==)
- Proovi nulliga jagamist. NB! Nulliga jagamine on defineerimata operatsioon. Nulliga jagamine võib jooksutada programmi või isegi kogu arvuti kokku (mikrokontrollerite puhul on tavapärane, et terve seade taaskäivitab end nulliga jagamise tulemusel). Nulliga jagamistehet ei tohi sooritada!
Lisaülesanne 1: ühekordsed numbrid
Ülesanne on tunnitöö #1 laiendus.
Nõuded
- Ülesanne peab olema tehtud laiendusena baasülesandele. Baasülesande funktsionaalsus peab säilima täies ulatuses.
- Lahenduses võivad korraga esineda mõlema edasijõudnute ülesande tulemused.
- Loo uus massiiv olemasolevate arvude põhjal. Uus massiiv tuleb luua põhimõttel, et kõik numbrid tohivad esineda vaid ühekordselt.
Näide lahendusest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Enter number 1 / 6: -5 Enter number 2 / 6: 3 Enter number 3 / 6: 9 Enter number 4 / 6: 3 Enter number 5 / 6: -5 Enter number 6 / 6: 5 The original array: -5 3 9 3 -5 5 The rearranged array: -5 -5 3 9 3 5 The positive number array: 3 9 3 5 The nonrecurrent array: -5 3 9 5 |
Lisaülesanne 2: paarid
Ülesanne on tunnitöö #1 laiendus.
Nõuded
- Ülesanne peab olema tehtud laiendusena baasülesandele. Baasülesande funktsionaalsus peab säilima täies ulatuses.
- Lahenduses võivad korraga esineda mõlema edasijõudnute ülesande tulemused.
- Leia ja kuva massiivis olevate arvude ja nende vastandarvude paarid.
- Samu arve tohib paarina kuvada ühekordselt, olenemata arvude järjestusest või korduste arvust.
Testimine
Testimisel veendu, et paarid ei korduks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Enter number 1 / 6: 1 Enter number 2 / 6: 5 Enter number 3 / 6: -1 Enter number 4 / 6: -5 Enter number 5 / 6: 5 Enter number 6 / 6: 224 The original array 1 5 -1 -5 5 224 The rearranged array -1 -5 1 5 5 224 The positive number array 1 5 5 224 The nonrecurrent array 1 5 -1 -5 224 Pairs: (-1, 1) (-5, 5) |
Pärast tundi peaksid
- Oskama sõnesid (teksti) funktsioonidesse edastada
- Oskama edastada nii terviklikku massiivi kui üksikut massiivi liiget funktsiooni
- Teadma ja oskama koostada ning kasutada massiive, kus massiivi kõik liikmed (kohad) ei ole kasutusel.
- tundma end mugavamalt massiivi käsitledes ka juhtudel, kus läbikäik pole esimesest viimase elemendini.
- oskama kopeerida ühest massiivist arve teise massiivi, kusjuures kasutades kahte erinevat indeksit ühes samas tsüklis erinevate massiivide indekseerimiseks.
- Tundma ennast juba natuke kodusemalt funktsioone kasutades.