Praktikumi 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 sama, mida eelmine nädal 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 funktsioon lihtsam ja kergemini korduvkasutatav.
Teise valikuna pakun lahenduse, 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 ka meie lahenduseks – me saame väljastatava teksti (sõne) 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 väljastuse ette tuleks lisada 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. Kusjuures igal tähemärgil on oma indeks.
- Erinevalt arvumassiividest 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 edastama funktsiooni. Oluline oli
- Massiiv edastatakse alati viitena originaal asukohale
- Massiivi sisu saab muuta alamfunktsioonides, muudatus kehtib kõikjal
- Massiiviga tuleb 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. Esimest ülesannet laiendab kaks lisaülesannet.
Ülesanne 1 [W06-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 arvud 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, nullist suurematest 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. Kui kopeerid funktsioone eelneva nädala ülesandest, ära unusta ka nendele eelnevat kommentaari kopeerida!
Nüüd lähme ümberjärjestamise juurde. Loo uus massiiv (lisaks olemasolevale), kuhu salvestad ü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); CreateRearrangedArray(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 nullist suurematest arvudest massiivi koostama. Struktuurilt on koostamine üsna sarnane eelnevalt tehtud ümberjärjestusele, kuid mõned erinevused siiski eksisteerivad. Kui ümberjärjestatud massiiv oli liikmete arvult samapikk algse massiiviga, siis nullist suuremate 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() funktsioonis välja massiivi väljatrükk, et ka kolmas massiiv ekraanile väljastada.
Testimine
Esimese testina proovime tavapärast juhtu, kui sisestuses on nii positiivseid kui negatiivseid arve.
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 greater than 0 array 6 3 4 |
Arvesta, et antud olukorras võivad ka nullist suuremad arvud 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 greater than 0 array Empty array |
Ülesanne 2 [W06-2]: kahe arvu võrdlus
Teises ülesandes praktiseerime massiivi indekseerimist, pöördudes vaid soovitud massiivi indeksite poole ning teostame lihtsaid operatsioone leitud väärtustega.
Nõuded
- Loe klaviatuurilt 5 täisarvu
- Küsi kasutajalt kahe soovitud arvu positsioon (järjekorranumber)
- Kontrolli, et need oleksid sobilikus vahemikus enne jätkamist! Vajadusel küsi uuesti
- Numeratsioon peab olema sama nagu sisendit küsides
- Soovitus: kontrollimaks kas leidsid õiged arvud, 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 funktsiooni 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) { } |
Testimine
NB! Näites on nähtavale jäetud silumiseks kasutatavad read (algusega DEBUG), mida soovitan ka sinul alguses teha. Need saad hiljem kiirelt 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, mida proovida
- 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 [W06-3]: Ühekordsed arvud
Ülesanne on tunnitöö #1 laiendus.
Nõuded
- Ülesanne peab olema tehtud laiendusena baasülesandele. Baasülesande funktsionaalsus peab säilima täies ulatuses.
- 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 greater than 0 array: 3 9 3 5 The nonrecurrent array: -5 3 9 5 |
Lisaülesanne 2 [W06-4]: Vastandarvude paarid
Ülesanne on tunnitöö #1 laiendus.
Nõuded
- Ülesanne peab olema tehtud laiendusena baasülesandele. Baasülesande funktsionaalsus peab säilima täies ulatuses.
- 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 greater than 0 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 funktsiooni edastada nii terviklikku massiivi kui ka üksikut massiivi liiget
- Oskama koostada ning kasutada massiive, mille kõik liikmed (positsioonid) ei ole kasutusel
- Tundma end mugavamalt massiivi käsitledes ka juhtudel, kus läbikäik pole esimesest elemendist viimaseni
- 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