Jätkub arvutiprogrammide koostamise põhimõtteid ja –võtteid tutvustav artiklisari, mis algas jaanuaris. Käesolevas numbris vaatleme lähemalt alamprogrammide, parameetrite ja muutujate omavahelisi suhteid.
Kodutöö lahendused
Ühekohalise ristsumma ülesande võib lahendada, korrates eelmises numbris ilmunud algoritmi tavalise ristsumma arvutamiseks, kuni saame ühekohalise tulemuse:
Function Ristsumma1(N)WHILE N > 9
S = 0
WHILE N > 0
S = S + N MOD 10
N = N \ 10
WEND
N = S ' asendame N väärtuse ristsummaga
WEND
Ristsumma1 = N End Function
Muidugi võib algoritmi ümberkirjutamise asemel kasutada juba olemasolevat funktsiooni Ristsumma:
Function Ristsumma2(N)WHILE N > 9
N = Ristsumma(N)
WEND
Ristsumma2 = N End Function
Teise ülesande juurde asudes kasutame esmalt ära asjaolu, et eesti tähestik jaguneb üheselt täis- ja kaashäälikuteks, millest saame:
Function Tahti(S)Tahti = Tais(S) + Kaas(S) End Function
Kuna täis- ja kaashäälikute loendamine peaks toimuma sisuliselt samamoodi, ainult erinevat tähtede nimekirja kasutades, siis lükkame ka nende funktsioonide kirjutamisel tehnilise töö edasi:
Function Tais(S)Const TaisH = "aeiouõäöü"
Tais = Loenda(LCase(S), TaisH) End Function
Function Kaas(S)Const KaasH = "bcdfghjklmnpqrsšzžtvwxy"
Kaas = Loenda(LCase(S), KaasH) End Function
Lõpuks pole muidugi enam pääsu ka ülesande sisulisest lahendamisest:
' Loendab sõne T tähtede esinemised sõnes S Function Loenda(S, T)N = 0
FOR I = 1 TO LEN(S)
IF INSTR(T, MID(S, I, 1)) > 0 THEN
N = N + 1
ENDIF
NEXT I
Loenda = N End Function
Õiged lahendused saatsid Andres Vahter, Andres Võsa, Toivo Hein, Toomas Vahter, Kristel Kivikangur, Anu Adler, Allan Voog, Kert Sasi, Roger Mikomägi, Taavi Ojaveer ja Mikk Leini. Auhinna saab loosi tahtel Allan Voog, kellel palume toimetusega ühendust võtta.
Muutuja skoop ja eluiga
Siiani oleme me muutujaid lihtsalt kasutanud ja lasknud Basicu keskkonnal neid automaatselt luua. Nii on mugav kirjutada väikesi programme, aga suuremates on parem asi enda kontrolli alla võtta. Isegi kui me oleme rahul sellega, mida Basic meie eest automaatselt teeb, on kasulik teda, mida ta ikkagi teeb — sest kuidas me muidu teaks, kas me võime sellega rahul olla?
Sarja esimeses artiklis kirjutasin, et muutuja on nimega mälupesa. Nagu see väljend juba natuke vihjab, koosneb muutuja kahest poolest: üks pool on mälupesa, mida kasutatakse muutuja väärtuse hoidmiseks, ja teine pool on nimi, mida kasutatakse sellele mälupesale viitamiseks. Nende kahe poolega on seotud kaks olulist mõistet. Muutuja eluiga näitab, kui kaua on mälupesa sellele muutujale reserveeritud. Peaks olema selge, et muutuja eluiga määrab, kui kaua muutujale omistatud väärtus säilib — kui muutujale A eraldatud mälupesa kasutatakse vahepeal mingite muude andmete hoidmiseks, siis läheb A väärtus sellega kaduma. Muutuja skoop seevastu näitab, millistes programmi osades selle muutuja nimi nähtav on. Seega määrab just skoop ära, millised programmi osad saavad seda muutujat kasutada ja millised mitte.
Basicus on nii muutuja eluiga kui ka skoop määratud muutuja kirjelduse asukohaga.
Globaalsed ja lokaalsed muutujad
Muutuja, mis on kirjeldatud väljaspool kõiki alamprogramme, luuakse (see tähendab, talle eraldatakse mälupesa) enne programmi esimese käsu täitmist ja üldiselt on see muutuja nähtav kõigis selle programmi alamprogrammides. Sellist muutjat nimetatakse globaalseks.
Muutuja, mis on kirjeldatud mõne alamprogrammi sees, luuakse uuesti iga kord selle alamprogrammi täitmise alguses ja hävitatakse alamprogrammi täitmise lõpus. Selline muutuja, mida nimetatakse lokaalseks, on nähtav ainult oma alamprogrammi sees.
Eelnevast võib esialgu jääda mulje, et muutuja eluiga ja skoop on üks ja seesama. Siiski pole see nii. Näiteks alltoodud koodilõigus on alamprogrammis Main loodud muutuja A eluiga alamprogrammi täitmise algusest lõpuni. Kui me aga vaatleme aega, mil täitmisjärg on alamprogrammis Sub1, siis sel ajal on muutuja A küll olemas (sest Main täitmine pole veel lõppenud), kuid alamprogrammi Sub1 sees olles me teda ei näe. Seega on selles näites muutuja skoop kitsam kui tema eluiga:
Sub MainDim A ' lokaalne muutuja
A = 1 ' algväärtustame
Sub1()
' A väärtus on säilinud End Sub
Sub Sub1' A ei ole siin nähtav End Sub
Skoobireegleid illustreerib täpsemalt veidi keerulisem näide. Siin on meil kaks muutujat, kusjuures mõlema nimi on A. Selguse huvides tähistame neid lisaks nimele ka värvidega (Basic neid muidugi ei värvi, tal on nende eristamiseks omad vahendid). Esimene A on kirjeldatud väljaspool kõiki alamprogramme, ja peaks seega olema olemas kogu programmi tööaja vältel ja kasutatav kõigist alamprogrammidest. Teine A luuakse alamprogrammi Sub1 käivitumisel ja sel hetkel varjab ta oma alamprogrammi keha jaoks ära esimese, globaalse A. Kuna aga teine A on lokaalne ja pole nähtav väljaspool oma alamprogrammi, kasutab Sub2 taas esimest, globaalset muutujat A. Teine, lokaalne A on sel ajal küll olemas (ja säilitab oma väärtuse), aga nähtamatu:
Dim A ' globaalne muutuja
Sub MainA = 0 ' omistab globaalsele
Sub1()
MsgBox(A) End Sub
Sub Sub1Dim A ' lokaalne muutuja, varjab globaalse
A = 1 ' omistab lokaalsele
Sub2()
MsgBox(A) End Sub
Sub Sub2A = 2 ' omistab globaalsele
MsgBox(A) End Sub
Kogu see keerukus on välja mõeldud peamiselt selleks, et iga alamprogrammi autor võiks olla kindel, et keegi teine ei saa tema lokaalsete muutujate väärtusi rikkuda. Selline siseasjade privaatsus on väga oluline suurtes süsteemides, mille kallal töötab palju programmeerijaid, kes võivad kogemata võtta kasutusele mitu sama nimega muutujat. Kui nad teevad seda globaalsete muutujatega, on kuri karjas. Lokaalsed muutujad on aga igalühel omad ja midagi halba ei juhtu. Sellest järeldub, et üldiselt tuleks kõik muutujad teha lokaalsed, kui pole mõjuvat põhust, miks mõni neist peaks globaalne olema.
Väärtus- ja viiteparameetrid
Eelmises numbris alamprogrammide parameetritest rääkides jätsin lihtsuse huvides mainimata, et Basicus, nagu ka paljudes teistes programmikeeltes, on kaht põhimõtteliselt erinevat liiki parameetreid:
- väärtusparameetri edastamisel tehakse alamprogrammile parameetrina antud väärtusest koopia, alamprogramm kasutab seda ja alamprogrammi töö lõppedes visatakse tema jaoks tehtud koopia minema; kasutades eelmises lõigus omandatud terminoloogiat, võib öelda, et väärtusparameeter pole midagi muud kui algväärtustatud lokaalne muutuja;
- viiteparameetri puhul seevastu kasutab alamprogramm sedasama mälupesa, ainult viitab talle teise nimega – oma formaalse parameetri nimega.
Üsna hea viis selles kõiges selgust saada on käivitada järgnev programm siluri all ja jälgida muutuja N väärtust:
Dim N
Sub MainN = 0
Sub1(N)
Sub2(N) End Sub
' Väärtusparameeter Sub Sub1(ByVal A)A = 1 ' N väärtus jääb endiseks End Sub
' Viiteparameeter Sub Sub2(ByRef A)A = 2 ' N väärtus muutub End Sub
Kodune töö
Uus kodune töö on aga selline:
- teha katse, mis näitab, kas Basicu automaatselt loodavad muutujad on globaalsed või lokaalsed (st kumba liiki muutuja saame, kui lihtsalt omistame muutujale ilma teda kirjeldamata);
- teha katse, mis näitab, kas Basicu alamprogrammide parameetrid on vaikimisi väärtus- või viiteparameetrid (st kumba liiki parameetri me saame, kui ei kirjuta ei ByRef ega ByVal).
Mõlema ülesande lahenduseks esitada:
- programmi tekst;
- selgitus, milline ja miks peaks olema katse tulemus ühel (vastavalt globaalse muutuja või väärtusparameetri) ja milline teisel (vastavalt lokaalse muutuja või viiteparameetri) juhul;
- katse tegelik tulemus ja mida sellest järeldada saab.
Seekordsete lahenduste hindamisel on kõige kaalukam punkt 2.
AUHINNAD paneb välja MAX 123 — DELLi müügi- ja teeninduskeskus. Seekordseks kuuauhinnaks on temaatiline saunalina. AASTAAUHINNAKS on DELLi sülearvuti.
Rubriigi autor AHTO TRUU (1972) on WM-data AS tarkvaraarendaja. Viimased kümme aastat tegelenud lisaks põhitööle informaatikavõistluste korraldamisega nii üldhariduskoolide õpilastele kui ka Tartu Ülikooli tudengitele. Eesti Informaatikaolümpiaadi žürii esimees, mitme rahvusvahelise võistluse žürii liige.
Siit saate endale laadida programminäited OpenDocument Spreadsheet vormingus. Nende avamiseks kasutage OpenOffice.org versiooni 2.0 või uuemat.
Faili avamisel hoiatab OpenOffice.org, et see sisaldab makrosid, mis võivad teie arvutit kahjustada. Kui te tahate failis olevaid programme ainult vaadata, võite makrode käivitamise keelata (nupp ‘Disable Macros’). Kui aga tahate programme ka käivitada proovida, peate ise otsustama, kas usaldate makrode käivitamist lubada (nupp ‘Enable Macros’) või mitte.
Programmitekstide vaatamiseks valige pärast faili avamist peamenüüst ‘Tools’ → ‘Macros’ → ‘Organize Macros’ → ‘OpenOffice.org Basic’. Avanevas dialoogiaknas valige kastis ‘Macro from’ vastavatud fail, selle all ‘Standard’, selle all omakorda soovitava programmi nimi. Programmi teksti vaatamiseks vajutage seejärel nuppu ‘Edit’, käivitamiseks aga nuppu ‘Run’.
WHILE N > 9






