- 1 1. Sissejuhatus: Mis on lõputu tsükkel C-keeles?
- 2 2. Lõputu tsükli põhistruktuurid C-keeles
- 3 3. Praktilised näited lõputu tsükli kasutamisest
- 4 4. Lõputu tsükli juhtimise meetodid
- 5 5. Tähelepanekud: probleemid ja lahendused lõputute tsüklitega
- 6 6. Praktilised ülesanded ja selgitused
- 7 7. KKK: korduma kippuvad küsimused C-keele lõputute tsüklite kohta
- 8 8. Kokkuvõte: lõputu tsükli eelised ja ohutu kasutamine
1. Sissejuhatus: Mis on lõputu tsükkel C-keeles?
Lõputu tsükkel C-keeles on programmi põhiline juhtimiskonstruktsioon, mis kordab käske seni, kuni täidetakse teatud tingimus. Lõputult jätkuvad tsüklid mängivad olulist rolli, toetades selliseid funktsioone nagu süsteemi pidev jälgimine või kasutaja sisendi ootamine.
Selles artiklis selgitame üksikasjalikult, kuidas C-keeles lõputuid tsükleid rakendada – alates põhistruktuuridest kuni praktiliste näideteni ja probleemide vältimiseni. Sihtgrupiks on algajad kuni kesktasemel õppijad ning kasutame konkreetseid näiteid koos näidiskoodidega.
2. Lõputu tsükli põhistruktuurid C-keeles
2.1 Lõputu tsükkel while-käsuga
while
-käsk kordab tegevusi seni, kuni tingimus on tõene. See on kõige sagedamini kasutatav meetod lõputu tsükli loomiseks.
Koodinäide
#include <stdio.h>
int main() {
while (1) { // 1 tähendab alati tõene
printf("See tsükkel kordub lõputult\n");
}
return 0;
}
See kood kuvab sõnumit „See tsükkel kordub lõputult” seni, kuni programm lõpetatakse.
Põhipunktid
- Kuna tingimus on alati tõene, muutub tsükkel lõputuks.
- Tingimustes saab kasutada muutujaid, et luua dünaamiline lõpetamistingimus.
2.2 Lõputu tsükkel for-käsuga
for
-käsku saab samuti kasutada lõputu tsükli loomiseks. Kui initsialiseerimine, tingimuse kontroll ja uuendus jäetakse ära, moodustub lõputu tsükkel.
Koodinäide
#include <stdio.h>
int main() {
for (;;) { // tingimuseta lõputu tsükkel
printf("Ka see tsükkel kordub lõputult\n");
}
return 0;
}
Põhipunktid
for (;;)
väljendab lõputut tsüklit lihtsustatult ja teeb koodi lühemaks.for
-käsku kasutatakse sageli korduste arvu määramiseks, kuid seda saab rakendada ka lõputu tsüklina.
2.3 Lõputu tsükkel do-while-käsuga
do-while
-käsk käivitab esmalt vähemalt ühe korra, seejärel hindab tingimust.
Koodinäide
#include <stdio.h>
int main() {
do {
printf("Ka see tsükkel kordub lõputult\n");
} while (1); // tingimus alati tõene
return 0;
}
Põhipunktid
- Sobib juhul, kui tegevust peab kindlasti vähemalt korra täitma.
- Tingimust hinnatakse hiljem, mistõttu käitumise järjekord erineb
while
-käsust.
3. Praktilised näited lõputu tsükli kasutamisest
3.1 Kasutaja sisendi ootamine
Allpool on programm, mis ootab pidevalt kasutaja sisendit.
Koodinäide
#include <stdio.h>
int main() {
char input[100];
while (1) {
printf("Sisesta väärtus: ");
scanf("%s", input);
if (strcmp(input, "exit") == 0) { // lõpetatakse, kui sisestatakse "exit"
break;
}
printf("Sisestatud: %s\n", input);
}
return 0;
}
Selgitus
scanf
-funktsioon loeb kasutaja sisendi ja kordab tsüklit seni, kuni sisestatakse “exit”.- Tingimuse täitumisel katkestab
break
-käsk tsükli.
3.2 Serveri jälgimise tsükkel
Allpool on näide süsteemist, mis kontrollib serveri olekut kindla intervalliga.
Koodinäide
#include <stdio.h>
#include <unistd.h> // sleep-funktsiooni jaoks vajalik
int main() {
while (1) {
printf("Serveri olekut jälgitakse...\n");
sleep(5); // ootab 5 sekundit
}
return 0;
}
Selgitus
sleep
-funktsiooni abil vähendatakse tsükli sagedust ja CPU koormust.- Seda tüüpi lõputuid tsükleid kasutatakse sageli süsteemihalduse ja monitooringutööriistade puhul.
3.3 Mängutsükli näide
Mängu põhitsükkel kordab iga kaadri korral teatud protsesse.
Koodinäide
#include <stdio.h>
#include <stdbool.h>
int main() {
bool running = true; // mängu oleku haldamine
int count = 0;
while (running) {
// mängu loogika
printf("Mäng töötab...\n");
// kasutaja lõpetamiskäsk (nt klaviatuurilt)
char command;
printf("Lõpetamiseks sisesta 'q': ");
scanf(" %c", &command);
if (command == 'q') {
running = false;
}
}
printf("Mäng lõpetatud\n");
return 0;
}
Selgitus
- Tsüklit juhitakse lipumuutujaga
running
. - Tingimusliku lõpetamise kaudu tagatakse ohutu seiskumine.
4. Lõputu tsükli juhtimise meetodid
4.1 Tsükli lõpetamine break-käsuga
break
-käsku kasutatakse tsükli sundlõpetamiseks. See on kasulik, kui soovitakse tsüklist väljuda kindla tingimuse täitumisel.
Koodinäide: lõpetamine kasutaja sisendi abil
#include <stdio.h>
int main() {
int input;
while (1) {
printf("Sisesta number (0 lõpetab): ");
scanf("%d", &input);
if (input == 0) { // lõpetatakse, kui sisestatakse 0
break;
}
printf("Sisestatud number: %d\n", input);
}
printf("Programm lõpetatud\n");
return 0;
}
Selgitus
- Kui
if (input == 0)
tingimus on tõene, lõpetabbreak
-käsk tsükli kohe. - Kui tingimus on väär, jätkub tsükkel.
4.2 continue-käsuga sammude vahelejätmine
continue
-käsk jätab tsükli järelejäänud käsud vahele ja liigub järgmisele iteratsioonile. Seda kasutatakse, kui soovitakse teatud tingimust välistada.
Koodinäide: ainult paarisarvude kuvamine
#include <stdio.h>
int main() {
for (int i = 1; i <= 10; i++) {
if (i % 2 != 0) { // kui on paaritu, jäetakse vahele
continue;
}
printf("%d on paarisarv\n", i);
}
return 0;
}
Selgitus
- Kui tingimus
i % 2 != 0
on tõene, jätkabcontinue
tsükli järgmist iteratsiooni. - Kuvatakse ainult paarisarvud.
4.3 Lipumuutuja kasutamine
Lipumuutuja abil saab lõputule tsüklile lisada paindlikke lõpetamistingimusi. Seda meetodit kasutatakse eriti keerukamate programmide puhul.
Koodinäide: lõpetamise juhtimine lipumuutujaga
#include <stdio.h>
#include <stdbool.h> // bool-tüübi jaoks vajalik
int main() {
bool running = true; // lipumuutuja
int count = 0;
while (running) {
printf("Loendus: %d\n", count++);
if (count >= 5) { // kui loendus >= 5, lõpetatakse
running = false;
}
}
printf("Tsükkel lõpetatud\n");
return 0;
}
Selgitus
- Tsükli jätkumist/lõpetamist juhitakse lipumuutujaga
running
. - Muutuja väärtuse muutmisega saab tsükli tingimusi paindlikult kontrollida.
4.4 Tingimusliku tsükli disain
Praktilistes olukordades tuleb sageli kombineerida mitut tingimust tsükli kontrollimiseks.
Koodinäide: ajapiiranguga tsükkel
#include <stdio.h>
#include <time.h> // ajafunktsioonide jaoks vajalik
int main() {
time_t start = time(NULL); // salvestatakse algusaeg
int count = 0;
while (1) { // lõputu tsükkel
printf("Loendus: %d\n", count++);
if (difftime(time(NULL), start) > 10) { // lõpetab pärast 10 sekundit
break;
}
}
printf("10 sekundit möödus. Lõpetamine.\n");
return 0;
}
Selgitus
time()
-funktsiooniga mõõdetakse algusaeg ningdifftime()
abil arvutatakse möödunud aeg.- Kombineeritud tingimustega tsükkel võimaldab luua ajapiiranguga programme.
5. Tähelepanekud: probleemid ja lahendused lõputute tsüklitega
5.1 CPU koormuse suurenemine
Kui lõputu tsükkel töötab väga kiiresti, võib CPU kasutus tõusta 100%-ni ning kogu süsteemi jõudlus halveneda. See on eriti kriitiline piiratud ressurssidega sisseehitatud süsteemides.
Probleemne näide
while (1) {
// mõttetu tegevus kordub lõputult
}
See kood ei tee midagi kasulikku, kuid kulutab pidevalt CPU ressursse.
Lahendus: kasuta sleep-funktsiooni
Tsükli sees tuleb lisada ootepaus, et vähendada protsessori koormust.
Parandatud koodinäide
#include <stdio.h>
#include <unistd.h> // vajalik sleep-funktsiooni jaoks
int main() {
while (1) {
printf("Jälgin...\n");
sleep(1); // oota 1 sekund
}
return 0;
}
Põhipunktid
sleep()
-funktsioon võimaldab reguleerida tsükli sagedust ja vähendada CPU koormust.- Sisseehitatud süsteemides on tõhusam kasutada
usleep()
-funktsiooni või taimerit, mis toetab millisekundite täpsust.
5.2 Programmi hangumine või vastuse lakkamine
Kui lõputul tsüklil puudub lõpetamistingimus, võib programm hanguda ja lõpetada sisendi või väliste käskude vastuvõtmise.
Probleemne näide
while (1) {
// lõpetamistingimust pole
}
See tsükkel ei lõpe enne, kui programm sunniviisiliselt katkestatakse.
Lahendus: lisa lõpetamistingimus
Parandatud koodinäide
#include <stdio.h>
int main() {
int count = 0;
while (count < 5) {
printf("Loendus: %d\n", count);
count++; // suurenda loendust
}
return 0;
}
Tulem
Loendus: 0
Loendus: 1
Loendus: 2
Loendus: 3
Loendus: 4
Põhipunktid
- Oluline on meeles pidada tsükli muutujate uuendamist.
- Lipumuutujate või loendurite kasutamine muudab tingimuste kontrolli ja silumise lihtsamaks.
5.3 Raskused silumisel
Lõputute tsüklite probleemide põhjuseid on sageli raske leida, eriti suurtes programmides. Sageli põhjustavad neid tahtmatud tingimused või sisendandmed, seetõttu on oluline tsükli käitumist täpselt jälgida.
Probleemne näide
int count = 0;
while (count != 10) { // tingimuse viga → lõputu tsükkel
printf("Loendus: %d\n", count);
}
Kuna count
ei muutu, jääb tsükkel lõputuks.
Lahendus: lisa logiväljund silumiseks
Parandatud koodinäide
#include <stdio.h>
int main() {
int count = 0;
while (count != 10) { // vältida tingimuse viga
printf("Debug: loendus=%d\n", count); // seire
count++; // uuenda väärtust
}
printf("Lõpetatud\n");
return 0;
}
Põhipunktid
- Logiväljund aitab jälgida tsükli seisu ja lihtsustab probleemide leidmist.
- Reaalses kasutuses tuleks silumiseks mõeldud väljund eemaldada või kommenteerida.
5.4 Turvaline disain mitme tingimusega
Keerukamate programmide puhul tuleb sageli kombineerida mitu tingimust, et tsüklit turvaliselt juhtida.
Probleemne näide
while (1) {
// töötab ilma ühegi tingimuseta
}
Lahendus: kombineeritud tingimused
Parandatud koodinäide
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
int main() {
bool running = true;
time_t start = time(NULL);
while (running) {
printf("Jälgin...\n");
// lõpetamine aja põhjal
if (difftime(time(NULL), start) > 10) { // 10 sekundi järel lõpetab
running = false;
}
}
printf("Jälgimine lõpetatud\n");
return 0;
}
Põhipunktid
- Mitme tingimuse seadistamine võimaldab lisada ohutuid lõpetamisvõimalusi ja erandite käsitlemist.
- Aja või loenduri abil saab ehitada turvalisema ja kontrollitavama tsükli.
6. Praktilised ülesanded ja selgitused
6.1 Koodiviktoriin: ennusta tulemusi
Ülesanne 1: tsükli töö kontroll
Kuidas töötab järgmine kood? Ennusta tulem.
Koodinäide
#include <stdio.h>
int main() {
int i = 0;
for (;;) { // lõputu tsükkel
printf("%d\n", i++);
if (i > 5) { // kui tingimus täitub, tsükkel lõpetatakse
break;
}
}
return 0;
}
Vihjed
for (;;)
on lõputu tsükli põhivorm.i++
suurendab muutujai
väärtust ühe võrra.- Kui
if (i > 5)
tingimus täitub, lõpetabbreak
tsükli.
Vastus ja selgitus
Kood väljastab arvud 0 kuni 5 järjest ja lõpetab enne 6 väljastamist.
Tulemus
0
1
2
3
4
5
Põhipunktid
- Näide näitab, kuidas lõpetada lõputu tsükkel
break
-käsuga. - Pärast tsükli lõppu naaseb programm tavapärasesse käiku.
6.2 Koodiparandus: vea kõrvaldamine
Ülesanne 2: tingimuse vea parandamine
Järgmisel koodil on probleem – see ei lõpeta tsüklit. Kus viga on ja kuidas parandada?
Koodinäide
#include <stdio.h>
int main() {
int count = 0;
while (count < 5) { // tingimuslik tsükkel
printf("Loendus: %d\n", count);
}
return 0;
}
Vihjed
count
väärtus ei muutu.- Tsükli sees peab olema loenduri suurendamine.
Vastus ja selgitus
Probleem on selles, et count
ei uuene, mistõttu tingimus count < 5
jääb alati tõeseks. Seetõttu tsükkel ei lõpe.
Parandatud kood
#include <stdio.h>
int main() {
int count = 0;
while (count < 5) {
printf("Loendus: %d\n", count);
count++; // suurenda loendurit
}
return 0;
}
Tulemus
Loendus: 0
Loendus: 1
Loendus: 2
Loendus: 3
Loendus: 4
Põhipunktid
- Oluline on uuendada tsüklimuutujaid.
- Lipumuutujate või loendurite kasutamine aitab ka silumisel.
6.3 Laiendusülesanne: ajapiiranguga tsükkel
Ülesanne 3: programm, mis töötab kindla aja jooksul
Järgmine kood töötab ainult 10 sekundit. Selgita tööpõhimõtet ja mõtle välja kasutusnäiteid.
Koodinäide
#include <stdio.h>
#include <time.h>
int main() {
time_t start = time(NULL); // algusaeg
while (1) { // lõputu tsükkel
printf("Töötab...\n");
// lõpetamine ajapiiranguga
if (difftime(time(NULL), start) > 10) {
break;
}
}
printf("10 sekundit möödus. Lõpetamine.\n");
return 0;
}
Vastus ja selgitus
Kood kasutab time()
-funktsiooni, et salvestada algusaeg, ning arvutab difftime()
-funktsiooniga möödunud aja.
Põhipunktid
difftime()
abil saab tsüklile määrata ajapiirangu.- Kasutusnäited: serveri jälgimine, automaatsed protsessid.
Näidisrakendused
- Andmete lugemine andurist kindlate intervallidega.
- Serveri vastuse kontrollimine ja uuesti proovimine, kui vastust ei tule.
6.4 Vigade käsitlemine: vale sisendi tuvastamine
Ülesanne 4: katkesta tsükkel vigase sisendi korral
Paranda järgmist koodi nii, et vale sisendi korral kuvatakse veateade ja programm lõpetatakse.
Koodinäide
#include <stdio.h>
int main() {
int number;
while (1) {
printf("Sisesta number: ");
if (scanf("%d", &number) != 1) { // kui sisestus pole arv
break;
}
printf("Sisestatud number: %d\n", number);
}
printf("Tekkis viga. Programm lõpetatakse.\n");
return 0;
}
Selgitus
scanf()
tagastusväärtuse kontroll võimaldab tuvastada vale sisendi.- Turvalistes programmides on oluline rakendada veakäsitlust.
7. KKK: korduma kippuvad küsimused C-keele lõputute tsüklite kohta
7.1 Küsimused lõputu tsükli põhiteadmiste kohta
K1. Millal peaks kasutama lõputut tsüklit?
V. Lõputuid tsükleid kasutatakse järgmistes olukordades:
- Serveri jälgimine: süsteemi oleku pidev jälgimine ja probleemide avastamisel reageerimine.
- Kasutaja sisendi ootamine: programm ootab pidevalt sisendit klaviatuurilt või sensoritelt.
- Reaalajas töötlus: mängudes või animatsioonides, kus on vaja pidevalt värskendada kaadreid.
K2. Miks muutub programm mõnikord reageerimatuks, kui kasutada lõputut tsüklit?
V. Kui tsüklile pole määratud lõpetamistingimust, töötab see igavesti ning programm ei vasta enam sisenditele.
Selle vältimiseks tuleb lisada lõpetamistingimus.
Näide: tsükkel koos lõpetamistingimusega
#include <stdio.h>
int main() {
int count = 0;
while (1) {
printf("Loendus: %d\n", count++);
if (count > 10) { // lõpetab, kui count > 10
break;
}
}
return 0;
}
Nagu näha, saab break
-käsu või lipumuutujaga tagada turvalise lõpetamise.
K3. Kui palju koormab lõputu tsükkel protsessorit?
V. Lõputu tsükkel ilma pausideta võib põhjustada CPU kasutuse tõusu kuni 100%.
Lahendus
- Lisa ootepaus
#include <unistd.h> // sleep-funktsiooni kasutamiseks
while (1) {
printf("Jälgin...\n");
sleep(1); // 1 sek paus
}
Seda tehes vähendatakse CPU koormust.
- Sündmustepõhine disain
Tsüklite asemel saab kasutada väliste sündmuste põhjal töötavat loogikat, näiteks klahvivajutuse või võrgusõnumi vastuvõtmisel.
7.2 Küsimused silumise ja vigade käsitlemise kohta
K4. Millele tuleks tähelepanu pöörata, kui siluda lõputut tsüklit?
V. Tõhusaks silumiseks tuleb kasutada järgmisi võtteid:
- Lisa silumislogid
Väljasta muutuja väärtus või tsükli seisuinfo.
printf("Debug: x=%d\n", x);
- Kasuta katkestuspunkte
Pane debuggimisvahendiga katkestuspunkt tsükli sisse, et näha seisu. - Kasuta loenduri piiranguid
Piira tsükli korduste arvu ja vaata tulemusi.
if (counter > 100) break;
K5. Mida teha, kui programm ei välju lõputust tsüklist?
V. Programmi saab lõpetada järgmiselt:
- Käsurea/terminali puhul
- Vajuta Ctrl + C, et katkestada programm.
- IDE või redaktori puhul
- Kasuta „Stop”-nuppu, et lõpetada protsess.
- Tegumihalduri kasutamine
- Ava tegumihaldur ja lõpeta vastav protsess.
Ennetamine
Programmeerimisel lisa alati lõpetamistingimused või taimerid, et vältida lõputut käivitust.
7.3 Küsimused lõputute tsüklite rakendamise kohta
K6. Kuidas kujundada efektiivseid programme, mis kasutavad lõputuid tsükleid?
V. Efektiivseks kujundamiseks tuleb järgida järgmisi põhimõtteid:
- Sündmustepõhine lähenemine
Väldi pidevat tsüklit, kasuta sündmustel põhinevat loogikat (nt nupuvajutus, võrgusõnum). - Kasuta taimerit
Määra tsükli töö intervallsleep()
või taimeriga. - Haldus ressursse
Vabasta mälu ja failide käepidemed õigesti, et vältida lekkeid.
K7. Kuidas muuta lõputu tsükli lõpetamistingimusi paindlikumaks?
V. Kasuta lipumuutujat, et tsükli lõpetamist dünaamiliselt kontrollida.
Näide: lipumuutujaga tsükli lõpetamine
#include <stdio.h>
#include <stdbool.h>
int main() {
bool running = true; // lipumuutuja
int count = 0;
while (running) {
printf("Loendus: %d\n", count++);
if (count > 10) {
running = false; // muuda lippu → lõpetab tsükli
}
}
printf("Lõpetatud\n");
return 0;
}
Nii saab programmis paindlikult kontrollida tsükli kestust ja tingimusi.
8. Kokkuvõte: lõputu tsükli eelised ja ohutu kasutamine
8.1 Lõputu tsükli eelised
Lõputu tsükkel on kasulik järgmistes olukordades:
- Pidev jälgimine ja töötlemine
- Serveri või süsteemi monitooringutööriistad kasutavad lõputuid tsükleid seisundi kontrollimiseks.
- Reaalaja rakendused
- Mängud ja kasutajaliidesed töötlevad sündmusi pidevalt tsüklite abil.
- Kasutaja sisendi ootamine
- Süsteemid, mis ootavad sisendit, saavad lõputu tsükli abil reageerida dünaamiliselt.
- Vigade käsitlemine ja uuestikäivitamine
- Andmete lugemine või võrguühenduse taastamine ebaõnnestumise korral.
8.2 Lõputute tsüklite riskid ja vältimine
Samal ajal kaasnevad lõputute tsüklitega järgmised riskid:
1. CPU liigkoormus
- Põhjus: kui tsüklis puudub paus, suureneb CPU koormus.
- Lahendus: kasuta
sleep()
või taimerit, et kontrollida töö sagedust.
Näide: CPU koormuse vähendamine
#include <stdio.h>
#include <unistd.h> // sleep-funktsiooni jaoks
while (1) {
printf("Jälgin...\n");
sleep(1); // 1 sek paus
}
2. Programmi hangumine või vastuse lakkamine
- Põhjus: kui puudub lõpetamistingimus, programm ei lõpe.
- Lahendus: kasuta lipumuutujat või
break
-käsku.
Näide: lõpetamistingimusega tsükkel
#include <stdio.h>
int count = 0;
while (count < 5) {
printf("Loendus: %d\n", count);
count++;
}
return 0;
3. Raskused silumisel
- Põhjus: tahtmatult loodud lõputud tsüklid on keerulised jälgida.
- Lahendus: lisa logiväljund tsükli sisse.
Näide: logi lisamine
#include <stdio.h>
int main() {
int count = 0;
while (1) {
printf("Debug: count=%d\n", count++);
if (count > 10) break; // katkestamine tingimuse alusel
}
return 0;
}
8.3 Efektiivse kujunduse põhimõtted
Lõputute tsüklite ohutuks ja tõhusaks kasutamiseks järgi järgmisi põhimõtteid:
- Määra selged lõpetamistingimused
- Kasuta lipumuutujaid või ajapiiranguid, et tagada ohutu lõpetamine.
- Lisa pausid
- Kasuta
sleep()
-i või taimerit, et vähendada CPU koormust.
- Rakenda veakäsitlus
- Lisa kood, mis lõpetab tsükli vigaste sisendite või ootamatute vigade korral.
- Integreeri silumisvõimalused
- Lisa logiväljundid ja kasuta katkestuspunkte, et jälgida programmi käiku.
8.4 Õpitu kordamine
Käesolevas artiklis vaatasime üle järgmised teemad:
- Põhistruktuurid
while
-,for
– jado-while
-tsüklite tööpõhimõte.
- Praktilised näited
- Kasutaja sisendi ootamine, serveri jälgimine, mängutsükkel.
- Juhtimismeetodid
break
,continue
ja lipumuutujate kasutamine.
- Probleemid ja lahendused
- CPU koormuse vähendamine, hangumise vältimine, silumise tehnikad.
- Praktilised harjutused
- Koodiviktoriinid ja veaparandused aitasid teadmisi kinnistada.
8.5 Kokkuvõtteks
Lõputu tsükkel on C-keeles väga oluline konstruktsioon. Kui mõista põhistruktuure ja juhtimismeetodeid ning rakendada parimaid praktikaid, saab kirjutada turvalist ja tõhusat koodi.
Edaspidi proovi ise lõputuid tsükleid rakendada ja täiustada.
Soovitatud järgmised teemad õppimiseks
- Tingimuslaused ja funktsioonid: keerukamate loogikate loomiseks.
- C-keele andmestruktuurid ja algoritmid: samm edasi tõhusate programmide kirjutamiseks.
- Silumisvahendite kasutamine: koodikvaliteedi tõstmiseks.
Jätka C-keele õppimist ja arenda välja keerukamaid programme!
Küsimuste või lisaselgituste korral kirjuta julgelt kommentaaridesse!