Selles tunnis on üks ülesanne, mida laiendab üks lisaülesanne
Tunnitöö [W07-1]: Mullsorteerimine
Tunnitöö raames sorteerid kasutaja poolt sisestatud arvujada kasutades mullsorteerimise algoritmi.
Nõuded
Kasutajalt küsitakse 5 täisarvu, mis salvestatakse massiivi
Sorteeri massiiv kasutades mullsorteerimise algoritmi
Optimeeri tsüklite kestvust sedasi, et asjatult võrdlusi ei sooritataks – just nii nagu oli slaidil näidatud. Veendu, etoptimeerid nii sisemise kui ka välimise tsükli piire!
Loenda ja kuva, mitu korda arve võrreldi omavahel. Kui tegid optimeerimise korrektselt, peaksid saama täpselt 10 võrdlust.
Kuva massiiv kasvavas järjekorras
Kuva massiiv kahanevas järjekorras
Kogu programmi vältel tohid sorteerida vaid ühe korra
Luua tuleb neli funktsiooni. Loetelu nõutud funktsioonidest on loetletud allpool
Meeldetuletuseks!
Muutujad
lowerCamelCase
Funktsioonid
UpperCamelCase
Makrod
SCREAMING_SNAKE_CASE
Maagilised numbrid koodist asendatud makrotega
Massiivi pikkus antakse funktsiooni alati kaasa
Vasta küsimusele: jälgida saab nii võrdluste kui vahetuste arvu. Kumb neist meie optimeeringu tulemusel väheneb, kumb jääb samaks?
Lahenduses nõutavad funktsioonid
Selles programmis tuleb sul kokku luua 4 funktsiooni
Numbrite lugemiseks massiivi
Massiivi sorteerimiseks
Kaks funktsiooni massiivi kuvamiseks
Vihjed
Saad soovi korral korduvkasutada juba mõnda eelenvatel nädalatel koostatud funktsiooni
Mullsorteerimise funktsioon on järjekordne funktsioon, mille peaksid oma varasalve panema. Kui funktsiooni endale talletad, võta sealt vahetuste loendamine ära – mida vähem kõrvalmõjusid funktsioonidel on seda parem.
Test 1: Tagurpidine järjestus
Tegu on kõige keerulisema juhuga mullsorteerimiseks. Suurim arv on esimene, vähim viimane.
Sample: sort
1
2
3
4
5
6
7
8
9
10
11
12
This program takes 5 numbers from the user and sorts them. Output is given in both ascending and descending order.
Enter number 1 / 5: 5
Enter number 2 / 5: 4
Enter number 3 / 5: 3
Enter number 4 / 5: 2
Enter number 5 / 5: 1
Comparisons made during sorting: 10
Numbers in ascending order: 1 2 3 4 5
Numbers in descending order: 5 4 3 2 1
Test 2: Juhuslik massiiv
Juhuslik järjekord. Võrdluste arv jääb samaks. Testib ka kitsaid piirjuhte osadel arvutisüsteemidel, kui massiivi piirest üle minnakse. Tegu ei ole garanteeritud tulemust andva testiga (selleks on spetsiaalsed tööriistad), aga võib mõnel juhul vea nähtavaks tuua.
Sample: sort
1
2
3
4
5
6
7
8
9
10
11
12
This program takes 5 numbers from the user and sorts them. Output is given in both ascending and descending order.
Algselt kirjeldatud algoritmi üks puudustest on olukord, kui massiiv saab oluliselt varem sorteeritud, kui algoritmi täielik tööaeg ette näeb. Sellist olukorda on võimalik tuvastada ning ära kasutada.
Kui massiiv saab sorteerituks enne viimast välimise tsükli läbikäiku, peata sorteerimine. Väldi tühja töö tegemist.
Vihjeks: mõtle, millised tegevused tehakse sorteerimise käigus ning mida ei tehta arvude puhul, mis on juba sorteeritud.
Kaitsmisel: Selgita, milliste sisendandmete puhul optimeeritud algoritm parema tulemuse annab, ning tõesta seda oma tulemusega.
Pärast tundi peaksid oskama järgmist
Peaksid saama aru, mis on arvu alus
Peaksid teadma enimlevinuid arvusüsteeme, muuhulgas kahend- ja 16ndsüsteemi.
Peaksid aru saama, mis vahe on positsioonilisel ja mittepositsioonilisel arvusüsteemil.
Peaksid aru saama, mis asi on bitt ja bait ning mitu bitti on baidis.
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"
voidPrintPassedText(chartext[]);
intmain(void)
{
PrintPassedText("Passing by using a constant");
PrintPassedText(DEFINED_STRING);
charinputString[]="Passing by using a variable";
PrintPassedText(inputString);
}
voidPrintPassedText(chartext[])
{
/* 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
voidPrintNum(intnum);
voidPrintIntArray(intarr[],intlen);
intmain(void)
{
intnums[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]);
}
voidPrintNum(intnum)
{
printf("Passed number: %d\n\n",num);
}
voidPrintIntArray(intarr[],intlen)
{
printf("Numbers are: ");
for(inti=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.
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):
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.
Sample 1: Min ind 0
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.
Sample 1: Min ind 0
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
*/
intGetIntInRange(intmin,intmax)
{
}
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
*/
intGetIntInRange(intmin,intmax,charprompt[])
{
}
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: -
*/
voidCompareValues(intval1,intval2)
{
}
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: -
*/
voidDivideValues(intval1,intval2)
{
}
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.
Sample 1: Min ind 0
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
Sample 1: Min ind 0
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.
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
Selle nädala tunnitöö on jupitatud kaheks osaks. Alguses lahenda esimene osa ja esita oma lahendus. Seejärel laienda lahendust teise osaga ning esita oma lahendus uuesti. Baasülesandele on sel korral pakutud 2 laiendavat lisaülesannet.
Ülesanne 1 osa 1 [W05-1]: Ekstreemumite leidmine
Ülesande esimene osa on tunnis tehtud UML tegevusdiagrammi realisatsioon C programmikoodina. Esimeses osas pead sa kokku looma 4 funktsiooni lisaks
main() funktsioonile!
Esimene ülesande osa peab loogilisel tasemel vastama tunnis tehtud UML tegevusdiagramile
Ülesande lahendamiseks pead looma 4 funktsiooni. Funktsioonid on aluskoodis kirjeldatud kommentaaridena. Kirjuta oma funktsioon kohe kommentaari järgi. Lisa puuduvad elemendid nagu makrod, muutujate deklaratsioonid, funktsioonide prototüübid ja väljakutsed.
Klaviatuurilt loetakse 6 täisarvu, mis salvestatakse massiivi.
Sisestuse kulg peab olema kasutajale arusaadav, näidates mitmendat arvu parasjagu sisestatakse ning mitu arvu kokku kasutajalt oodatakse
Massiivist leitakse ja väljastatakse suurim sisestatud arv. Tulemus tuleb leida funktsioonis ning tagastada. Tulemuse väljastus toimub main() funktsioonis
Massiivist leitakse ja väljastatakse vähim sisestatud arv. Tulemus tuleb leida funktsioonis ning tagastada. Tulemuse väljastus toimub main() funktsioonis
Väljasta eraldi funktsioonis kõik sisestatud massiivi liikmed
Ülesande lahendamise juhend
NB! Enne funktsioonide loomist loe läbi aluskoodis olev funktsiooni kirjeldus ja veendu, et saad sellest aru (st mida funktsioon teeb, mis on selle parameetrid ja kas ning mida see funktsioon tagastab). Iga funktsioon tuleb realiseerida ettekirjutatud funktsiooni kommentaari järel.
Alusta funktsiooni
ReadIntArray() lahendamisest. See on esimene funktsioon kohe pärast main() funktsiooni. Selleks kirjuta tsükkel, mille igal kordusel küsitakse kasutajalt väärtus, mis salvestatakse massiivi.
Testimaks, kas see töötab, pead selle funktsiooni välja kutsuma. Selleks pead esmalt deklareerima massiivi, kus arve hoida. Seejärel kutsu funktsioon
ReadIntArray() välja, andes talle kaasa loodud massiiv ning selle pikkus.
Eeldusel, et pikkust kirjeldav makro nimi on
NUM_CNT ja massiivi nimi on
numbers , võiks selle funktsiooni väljakutse näha välja midagi sarnast:
ReadIntArray(numbers, NUM_CNT); Proovi nüüd, kas massiivi arvude lugemine toimis.
Veendumaks, et numbrid ka korrektselt loetud said, peaksid massiivi sisu välja trükkima. Selleks realiseeri funktsioon
PrintArray() ja kutsu see välja main() funktsioonist. Sel korral pead tagastuse tüübi ja parameetrid ise valima. Kui funktsioon tehtud ja välja kutsutud, peaksid nägema oma massiivi sisestatud numbreid.
Nüüd tuleb sul veel viimased kaks funktsiooni lõpetada. Mõlemad on kirjeldatud kommentaaridena aluskoodis. Lõpeta funktsioonid ja väljasta tulemused. NB! min ja max väärtusi leidvatel funktsioonidel ei tohi olla kõrvalmõjusid, tulemused väljasta main() funktsioonis.
Testimine
Test 1: min esimene, max viimane
1
2
3
4
5
6
7
8
9
10
11
12
Enter number 1 / 6: 1
Enter number 2 / 6: 2
Enter number 3 / 6: 3
Enter number 4 / 6: 4
Enter number 5 / 6: 5
Enter number 6 / 6: 6
Entered numbers:
1 2 3 4 5 6
Min value is 1
Max value is 6
Test 2: min viimane, max esimene
1
2
3
4
5
6
7
8
9
10
11
12
Enter number 1 / 6: 6
Enter number 2 / 6: 5
Enter number 3 / 6: 4
Enter number 4 / 6: 3
Enter number 5 / 6: 2
Enter number 6 / 6: 1
Entered numbers:
6 5 4 3 2 1
Min value is 1
Max value is 6
Test 3: Negatiivne min. Min ja max on massiivi keskel.
1
2
3
4
5
6
7
8
9
10
11
12
Enter number 1 / 6: 1
Enter number 2 / 6: 2
Enter number 3 / 6: 3
Enter number 4 / 6: 4
Enter number 5 / 6: -933
Enter number 6 / 6: 1
Entered numbers:
1 2 3 4 -933 1
Min value is -933
Max value is 4
Ülesanne 1 osa 2 [W05-2]: asukohtade ja korduste arvu leidmine
Ülesande esimeses osas leidsid massiivist ekstreemväärtused. Teises osas tuleb leida nende positsioonid ning mitu korda väärtused massiivis esinesid.
Nõuded
Kuva kõik positsioonid, kus asus massiivi suurim väärtus. Tulemus väljastatakse funktsiooni sees, mis positsioone leiab.
Kuva kõik positsioonid, kus asus massiivi vähim väärtus. Tulemus väljastatakse funktsiooni sees, mis positsioone leiab.
Kuva, mitu korda suurim ja vähim väärtus massiivis eksisteerib. Tulemus tuleb leida eraldi funktsioonis, tagastada ning seejärel väljastada
main() funktsioonis.
Kuvatavad positsioonid peavad olema vastavuses sisestusega.
Kõigil funktsioonidel su koodis peavad olema funktsiooni kommentaarid (st funktsioonile eelnev kommentaar)
Ülesande lahendamise juhend
Selle osa lahendamiseks pead looma kokku kaks funktsiooni. Mõlemad funktsioonid on kirjeldatud funktsiooni kommentaaridena. Kopeeri funktsiooni kommentaar enda koodi ja kirjuta lahendus selle järel
Esimene funktsioon väljastab eelnevalt leitud ekstreemumväärtuse kõik asukohad massiivis. Selle lahendamiseks pead looma tsükli, mis käib läbi kõik massiivi liikmed. Iga kord, kui massiivi liikme väärtus on sama kui sinu otsitav (nt minimaalne väärtus massiivis), pead väljastama ekraanile oma praeguse asukoha tsüklis (tsükli praeguse korduse väärtus on seotud massiivi positsiooniga). St kogu funktsioon sisaldab ühte tsüklit, ühte tingimuslauset ja ühte väljastuslauset – ongi kõik.
Loodavat funktsiooni pead korduvkasutama (st 2x välja kutsuma) nii minimaalse kui maksimaalse väärtuse asukohtade kuvamiseks! Tulemustele eelnev tekst (nt “Min value position(s)”) tuleks väljastada main() funktsioonis, enne selle funktsiooni väljakutset.
1
2
3
4
5
6
7
8
9
10
/**
* Description: Prints all positions of val in the array. Shows positions
* (starting from 1), instead of indexes.
*
* Parameters: nums - values that are checked
* len - length of the array
* val - value for which the positions will be printed
*
* Return: -
*/
Testi funktsiooni tööd enne lahendamise jätkamist!
Teine funktsioon saab olema vägagi sarnane eelmisele. Sel korral aga peame loendama (st ühte täisarvulist muutujat suurendama sobilikul hetkel) väljastamise asemel. Funktsioon peab oma tulemuse tagastama. Tulemus väljastatakse main() funktsioonis.
1
2
3
4
5
6
7
8
9
/**
* Description: Counts the number of times val is present in the array
*
* Parameters: nums - values that are checked
* len - length of the array
* val - value to search for
*
* Return: number of times val occurred in array
*/
Testimine
Test 1: min ja max on ühekordsed
Sample: min and max single occurrence
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Enter number 1 / 6: 10
Enter number 2 / 6: 11
Enter number 3 / 6: 12
Enter number 4 / 6: 13
Enter number 5 / 6: 14
Enter number 6 / 6: 15
Entered numbers:
10 11 12 13 14 15
Min value is 10
Min value position(s): 1
Min value occurred 1 time
Max value is 15
Max value position(s): 6
Max value occurred 1 time
Test 2: min ja max korduvad
Sample: min and max multiple occurrence
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Enter number 1 / 6: 10
Enter number 2 / 6: 13
Enter number 3 / 6: 12
Enter number 4 / 6: 10
Enter number 5 / 6: 13
Enter number 6 / 6: 13
Entered numbers:
10 13 12 10 13 13
Min value is 10
Min value position(s): 1 4
Min value occurred 2 times
Max value is 13
Max value position(s): 2 5 6
Max value occurred 3 times
Lisaülesanne 1 [W05-3]: Tulemuste leidmine massiivist
Selles osas leiame kolm täiendavat tulemust massiivist
Nõuded
Loo kolm funktsiooni, vastavalt summa, korrutise ja aritmeetilise keskmise leidmiseks
Aritmeetilise keskmise funktsiooni sisuks ei tohiks olla koopia summa funktsioonist (väldi koodi kopeerimist!). Selle asemel kasuta summa leidmise funktsiooni keskmise leidmise osana.
Kõik kolm funktsiooni saavad parameetriteks massiivi ja selle pikkuse ning peavad oma tulemused tagastama. Tulemused väljastatakse
main() funktsioonis.
Kuva aritmeetiline keskmine kolme komakohaga
Testimine
Selle ülesande kõige suuremaks komistuskiviks on õige aritmeetilise keskmise leidine.
Sample: precision test for avg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Enter number 1 / 6: 1
Enter number 2 / 6: 1
Enter number 3 / 6: 1
Enter number 4 / 6: 1
Enter number 5 / 6: 1
Enter number 6 / 6: 3
Entered numbers:
1 1 1 1 1 3
Min value is 1
Min value position(s): 1 2 3 4 5
Min value occurred 5 times
Max value is 3
Max value position(s): 6
Max value occurred 1 time
Sum is 8
Product is 3
Arithmetic mean is 1.333
Lisaülesanne 2 [W05-4]: n-arvu sisestus
Pakkumaks kasutajale veidi kasulikumat programmi, peaks kasutaja saama otsustada mitme numbri pealt ta statistikat soovib leida. Pakume kasutajale võimaluse sisestada sisestatavate arvude koguse.
NB! Kuigi suur osa C keele kompilaatoritest toetab muutuva pikkusega massiivide (VLA – variable length array) kasutamist, ei ole see kõigi C standardite kohustusliku osana. St tugi võib kompilaatoris puududa täielikult)
Täiendavalt on VLAde puhul ka teisi probleeme – nt on need sageli aeglasemad kui staatilise suurusega massiivid. VLAd kasutav kood sisaldab rohkem käske, mis omakorda vajab rohkem protsessori tsükleid (aega) rakenduse jooksutamiseks. Samuti kui ühtegi rangelt nõutud piirangut ei ole, siis on üsna lihtne kogu programm kokku jooksutada, andes ette lihtsalt suurema numbri (nt tahan sisestada 1 000 000 numbrit).
Seetõttu ei ole sul sel korral lubatud kasutada massiive, mille pikkus on määratud teise muutuja kaudu (nt
intnumbers[numberCount]; , kus
numberCount on täisarvuline muutuja, mis saab oma väärtuse programmi töö ajal). Standardis toetatud universaalne lahendus on kasutada dünaamilist mälu, kuid seda vaatame Programmeerimine 2 aine raames.
Selle ülesande raames peaksid leidma ja määrama maksimaalse võimaliku suuruse, millest kasutaja rohkem numbreid sisestada ei saa. See tähendab, et suure tõenäosusega jääb suur osa massiivi pesadest kasutama. Õnneks on suurused väikesed, seega märkimisväärset probleemi see ei tekita meile.
NB! Enamjaolt on selles aines VLAde kasutamine lubatud. Piirang on seatud ülesandepõhiselt.
Nõuded
Luba kasutajal pärast programmi käivitamist otsustada, mitme numbriga programm töötab
Piira programmi poolt toetatud numbrite kogust vastavalt loodud massiivi suurusega
Kasutaja poolt sisestuse küsimine peab olema teostatud eraldi funktsioonis, mille pead looma selle ülesande jaoks. Funktsioon tohib alles siis tagastada, kui sisestatud number on sobilik
Kasuta funktsiooni parameetreid lubatud sisestuse vahemiku määramiseks
Funktsioon, mille lood, peab olema korduvkasutatav teistes sarnastes situatsioonides (erinev lubatud numbrivahemik)
Numbrite vahemiku võid ise otsustada mõistlikus vahemikus (nt kuni 50 numbrit).
Ebasobiva numbrite arvu korral loo veakäitumine.
Muutuva pikkusega massiivi (VLA – variable length array) kasutada ei tohi
NB! Vaata üle ka koodimisstiil! Muutuja ei tohi olla kirjutatud samas stiilis nagu makro (tüüpviga)
Testimine
Testi hoolikalt kindlasti järgmist
Minimaalne lubatud numbrite arv
Maksimaalne lubatud numbrite arv
Numbrite arv, mis on erinev algsest
Sample: testing of user entered n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Enter number count (up to 50): 127
Error! Invalid number count!
Enter number count (up to 50): 3
Enter number 1 / 3: 5
Enter number 2 / 3: 1
Enter number 3 / 3: 2
Entered numbers:
5 1 2
Min value is 1
Min value position(s): 2
Min value occurred 1 time
Max value is 5
Max value position(s): 1
Max value occurred 1 time
Sum is 8
Product is 10
Arithmetic mean is 2.667
Pärast tundi peaksid
Teadma, mida tähendab tüübiteisendus ning kuidas seda kasutada (type casting)
Teadma, mis asi on murdarvude esitustäpsus ning mis probleeme sellega esineda võib
Teadma, mis asi on püsikomaarv (fixed point notation) ja mis on ujukomaarv (floating point notation).
Teadma, mis asi on matemaatika teek (math.h), kuidas seda kasutada, mis seal sees on ning kuidas lisada kompilaatorile täiendav lipp, et see ka kompileeruks.
Programmi kompileerimisprotsessi selgitamiseks age check
Esitamisele kuuluvad ülesanded
Selles praktikumis on kaks baasülesannet, mille raames lood kokku viis programmi. Täiendavalt on lahendamiseks pakutud kaks lisaülesannet.
Ülesanne 1 [W03-1]: 5-arvu summa.
Selle ülesande raames tuleb sul luua programm, mis leiab viie kasutaja poolt sisestatud arvu summa. Programm tuleb sul luua 3 korda – üks programm iga tsükli tüübi kohta. Kõik kolm loodavat programmi täidavad sama ülesannet.
Nõuded
Programm küsib kasutajalt 5 arvu
Kõigi arvude, peale viimase, sisestamise järel näitab programm praegust vahesummat
Pärast viimase arvu sisestamist kuvatakse lõppsumma. Vahesummat ei kuvata
Programm peab andma kasutajale arusaadava väljundi, mida temalt oodatakse
Programmis ei tohi olla maagilisi arve
Programmi disain peab olema selline, et kui sama ülesannet tuleks teha 10, 20 või ka 1000 arvu korral, siis selleks peaksid muutma programmikoodis vaid ühte numbrit! Testi seda enne esitamist – tehes muudatuse vaid ühes kohas kogu programmis, peab see töötama näiteks 7 arvuga.
Vihjeid
Mõtle hoolikalt läbi, milliseid muutujaid sul vaja on! Olenemata sellest, mitme arvu summat sa leiad, on muutujate arv alati sama.
Tsüklite puhul on soovitatav loendamist alustada nullist. Seda kuna arvutite puhul hakatakse loendama nullist ning väga paljud süsteemid sõltuvad sellest. Tavaline arvutikasutaja aga hakkab loendama ühest. Selleks
(i + 1) võtab muutuja i väärtuse ning kasutab seda suurendatud väärtust konkreetse tehte juures. Küll aga ei suurenda see i enda väärtust. Sedasi saame ajutiselt kasutada ühe võrra suuremat väärtust. Näiteks
printf("%d",i+1);
Operatsioonid nagu i++, ++i, i += 1 ja i = i + 1 jällegi suurendavad i väärtust jäädavalt.
Testimine
Järgnevalt on kujutatud näide oodatavast programmi väljundist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
See programm liidab kokku 5 kasutaja poolt sisestatud arvu ning kuvab jooksvalt vahesummasid.
Sisesta arv 1 / 5
9
Vahesumma on 9
Sisesta arv 2 / 5
3
Vahesumma on 12
Sisesta arv 3 / 5
2
Vahesumma on 14
Sisesta arv 4 / 5
1
Vahesumma on 15
Sisesta arv 5 / 5
5
Lõppsumma on 20
Ülesanne 2 [W03-2]: Kassasüsteem kontrolliga
Selle ülesande käigus lisame mõned elementaarsed veakontrollid eelmisel nädalal tehtud tunnitööle. Aluskoodiks võid kasutada nii enda eelmise nädala programmi kui ka meie poolt antud valmislahendust.
Esimeses praktikumis on kõik uus, mistõttu teeme enamiku praktikumi tööst koos läbi. Praktikumi lõpus saad aga juba sooritada ja kaitsta oma esimese ülesande. Tublimad jõuavad kindlasti ka lahendada lisaülesande.
Ülesanne 1 [W01-1]: Paarsuse kontroll (baasülesanne)
Nõuded
Kasutajalt küsitakse ja seejärel loetakse sisse täisarv
Programm väljastab sisestatud arvu
Programm väljastab, kas sisestatud arv oli paaris või paaritu
NB! Lisaks funktsionaalsetele nõuetele peab vastama programmikood ka stiilinõuetele. Kõige levinumad eksimiskohad stiiliga sellel programmil on treppimisvead (programmi vasakust äärest tühikute arv), tühikute puudumised operaatorite ees ja järel (nt võrdusmärk) ning tühjade ridade puudumine erinevate programmi osade vahel.
Ülesande taust
Jagatise jääke kasutatakse laialdaselt kõiksugu kontrollkoodide arvutamisel. Näiteks kontrollimaks, kas isikukood või pangakaardi number on korrektne.
Meie ülesande jaoks on vajalik jagamine kahega ehk teostame paarsuse kontrolli – kas arv on paaris või paaritu. Paarsuse kontroll on üks lihtsamatest veakontrollidest näiteks andmesides – kas väärtusega ‘1’ bittide arv andmepaketis on paaris või paaritu? Sedasi on võimalik kontrollida, kas andmete ülekandmisel ühest arvutist teise tekkis viga (ja nagu öeldud, vaid väga lihtsad juhud).
Pseudokood
Pseudokood on üks võimalus kirjeldada algoritme. Pseudokood on sarnaselt programmile struktuurne, kuid ei hõlma endas programmeerimiskeeltele omaseid reegleid, mistõttu jääb see võrdlemisi inimloetavaks.
1
2
3
4
5
6
Kasutajalt loetakse üks täisarv
Kui sisestatud arv on paarisarv
Trüki sisestatud arv ja, et tegu on paarisarvuga
Muul juhul:
Trüki sisestatud arv ja, et tegu on paaritu arvuga
Programmi lõpp
Algoritm
Ülesande algoritm modelleeritakse tunnis koos, et näidata sobilike töövõtteid algoritmi koostamisel – kuidas vormistada tingimuslauset, kontrollvoo noolte murdmisel täisnurkade kasutamist jne. Ülesande kirjelduse terviklikkuse huvides oleme lisanud ühe kahest võimalikust vormistusest ka siia.
Kuidas ülesannet lahendada
Ülesande lahendamisel juhindu nii koostatud algoritmist kui ka slaididel etteantud koodilõikudest. See ülesanne on justkui lego, mis tuleb tükkidest õigesti kokku sobitada.
Alusta sellest, et lood uue faili. Salvesta see oma P kettale, programmeerimise alamkausta, kasutades faililaiendit
.c – näiteks
paarsuskontroll.c .
Nüüd kirjuta maha kõige viimasel slaidil olev koodpõhi (mida näitame sulle ka projektorilt). Pane tähele, et oleme sinna sisse jätnud ka ühe vea! Peaksid seda kohe nägema, kui üritad programmi kompileerida. Paranda viga ära enne kui jätkad ülesande lahendamist. Vajadusel otsi oma
tere.c koodist üles sarnane rida (mis viga põhjustab) – sealt leiad ka lahenduse.
Järgmiseks legotükiks on meil vaja tingimuslause struktuuri. Leia tingimuslausete slaidikomplektist if/else lause struktuur ning kirjuta see enda programmi ümber. Ära kopeeri – kirjutamine on oluline musklimälu tekitamiseks. Kindlasti jälgi ka treppimist ning märksõna
if järel olevat tühikut. Koledat koodi kaitsmiselt läbi ei lasta.
Kolmanda puuduva tükina tuleb välja valida ning korrektselt vormistada tingimuslause tingimus (käib
if lausel sulgude sisse). Meenuta, et ülesanne lahendamiseks tuleb kontrollida kas sisestatud arv on paaris või paaritu. Tingimuslausete näited ja jagamise põhimõtted leiad samuti slaididelt. Proovi seejärel programmi kompileerida ja veendu, et vigu poleks!
Viimaseks tükiks on vaja lisada if ja else lause sisu, et tulemus ekraanile trükkida. Selleks pead kirjutama kaks
printf() funktsiooni väljakutset, mis näeksid välja midagi sarnast:
1
printf("The number <.........> is an <........> number\n");
Märka, et jätsime kaks kohatäidet. Ühte neist peab tulema sisestatud arv, teise vastus kas tegu on paaris või paaritu arvuga.
Testimine
Sellel programmil on kaks võimalikku tulemust – arv on paaris või paaritu. Programmi põhjalikuks testimiseks tuleb testida mõlemat juhtu.
Test 1: Paarisarv
1
2
Please enter an integer: 2
The number 2 is an even number.
Test 2: Paaritu arv
1
2
Please enter an integer: 19
The number 19 is an odd number.
Kõik töötas? Väga tubli! Sa oled peaaegu kaitsmiseks valmis.
Meenuta, et kood peab olema loetav. Loetavuse saavutamiseks on kasutusel koodimisstiili reeglid. Võrdle oma koodi varasemate programmidega ja koodinäidetega sellest tunnist. Pööra tähelepanu järgnevale
Tühikute kasutamine (enne ja pärast matemaatilisi operaatoreid, pärast
if märksõna
Treppimine ehk taane vasakult (loogeliste sulgude vahele jääv kood trepitakse täiendavalt 1 võrra ehk 4 tühiku jagu. Kasutaja sisestuse küsimine ja
return lause on seega trepitud 1 võrra, samas if / else sees olevad
printf() laused 2 võrra)
Tühjade ridade kasutamine koodilõikude eraldamiseks (enne
main() funktsiooni, enne
if lauset, enne
return lauset)
Kood töötav ja loetav? Nüüd anna märku, et soovid kaitsta!
Lisaülesanne [W01-2]: Kolme ja viiega jagamine
Enne kui alustad lisaülesande lahendamist, lahenda ära baasülesanne. Lisaülesande lahendamisel tuleb esmalt kaitsta ära baasülesanne, seejärel lisaülesanne.
Miks on oluline, et algoritmid on kirjeldatud sedasi, et nad on kõigile üheselt arusaadavad.
Youtube: Exact Instructions Challenge – THIS is why my kids hate me. | Josh Darnit https://www.youtube.com/watch?v=cDA3_5982h8