Järgnevad näited on koostatud üleskirjutisena esimesest õppetunnist, mis aitab sul tunni praktilist poolt meelde tuletada. Tekst võib sisaldada täiendavaid kommentaare, mida klassiruumis ei esitatud.
Antud lehelt leiad järgneva sisu
- Tere koodi esimene osa, lineaarne sündmuste voog
- Tere koodi teine osa, tinglik sündmuste voog
- C-keelsete programmide süntaks ja koodimisstiil
- UML tegevusdiagrammid mõlema koodinäite kohta
- Täiendavad kommentaarid mõlema programmi kohta
tere.c esimene osa: lineaarne sündmuste voog
Esimeses osas loome lihtsa kalkulaatori inimese vanuse leidmiseks. Kalkulaatorisse on lihtsuse huvides jäetud sisse mõningad puudujäägid, et mitte öelda vead. Osad neist saavad adresseeritud programmi teises osas, kuid mõningate jaoks on vaja rohkem eelteadmisi, mida oleks esimesel nädalal liiga palju tahta.
Kõik järgnevad näited sisaldavad täiendavaid kommentaare.
Esimese osa algoritm
Algoritm peab kirjeldama lahenduseks vajaminevat sündmuste jada üheselt ning detailselt. Algoritmide kirjelduseks saab kasutada erinevaid tähistusi, nt pseudokoodi, tegevusdiagramme, voodiagramme jne. Selles õppeaines fokusseerime UML tegevusdiagrammidele, kuid aeg-ajalt kasutame ka teisi esitlusviise. Tänased näited on esitatud nii pseudokoodi kui tegevusdiagrammina.
Esimese osa pseudokood
Pseudokoodis kirjeldame algoritme samm-sammulise jadana. Kirjelduses kasutatakse tavapärast kõnekeelt ja erinevates programmeerimiskeeltes kasutatavaid üldlevinud mõisteid. Pseudokood peab olema võimalikult inimloetav, säilitades oma struktuurse ülesehituse. Pseudokoodi kirjutamisel puuduvad otsesed reeglid.
1 2 3 4 |
- Tervita kasutajat - Küsi kasutajalt sünniaasta - Arvuta kasutaja võimalik (tõenäoline) vanus - Väljasta vanus |
Esimese osa UML tegevusdiagramm
Tegevusdiagramme kasutatakse eeskätt algoritmide visualiseerimiseks. Diagrammi koostamisele kulub rohkem aega, kuid nad pakuvad mitmeid eeliseid, muuhulgas on UML standardiseeritud keel ja diagrammi formaat on hõlpsamini loetav mitte-arendajale. Enamjaolt kasutavad erinevaid UML diagramme suurettevõtted ja valitsused, mis vajavad täpset spetsifikatsiooni, rahvusvahelist sertifitseerimist ja standardiseeritust.
Tegevusdiagrammide juures on oluline, et need oleksid programmeerimiskeelest sõltumatud ning inimloetavad. Märka eelnevas diagrammist järgnevaid komponente
- Algoritmi alguses on tegevuse alguse sümbol (initial node)
- Nooltega näidatakse algoritmi kontrollvoogu (control flow)
- Tegevused kirjeldavad tegevusi inimloetavalt, jättes välja programmeerimiskeeltes olulised märksõnad, keelereeglid, kujunduse jne
- Algoritm lõppeb tegevuse lõpu sümboliga (final node)
Programmikood
Programmikoodis tutvume C-keelsete programmide põhistruktuuriga. Enamik programme algavad loeteluga teekidest, mis võimaldavad rakendusel kasutada teekide kogumike. Näiteks stdio.h teek võimaldab kasutada mitmeid sisend-väljundkäske. Kuigi rakendus seda ei kasuta, siis näiteks math.h teek võimaldaks kasutada matemaatilisi funktsioone.
Teekidele järgneb main() funktsioon pea kõige olulisem funktsioon. C keeles kirjutatud programmid alustavad koodi täitmist main() funktsioonist, täites koodi rida-rea haaval järjestikuliselt. Main funktsiooni lõpus paikneb return lause, lõpetab funktsiooni täitmise. Ühtlasi antud näites lõpetab see ka programmi töö.
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 36 |
/** * File: hello.c * Author: Risto Heinsar * Created: 01.09.2014 * Edited: 23.07.2025 * * Description: This is the first hello.c example showing program flow without * any conditionals and basic input-output function calls. */ // Includes the standard input-output library (printf, scanf) #include <stdio.h> // The program always starts from the main() function int main(void) { // Print the greeting in the terminal. printf("Hello!\n"); printf("This program determines the approximate age of a person\n\n"); // Variable declaration, type int (integer), variable name "year" int year; // Prompt the user and read the year of birth as integer printf("Please enter your year of birth: "); scanf("%d", &year); // Calculating the rough estimate of the age int age = 2025 - year; // Printing the result printf("You are most likely %d years of age\n", age); // The program finished successfully. Integer 0 indicates success. return 0; } |
Keelereeglid ja koodimisstiil
Süntaks ehk keelereeglid on komplekt reegleid, mille jälgimine on kohustuslik, et programmikood oleks arvutile arusaadav. See hõlmab endas kõiksugu nõudeid programmikoodi struktureerimisel (nt komad, punktid, semikoolonid, märksõnad jne). Iga programmeerimiskeel omab veidi erisuguseid reegleid, mida tuleb teada, kuid suurel osal programmeerimiskeeltest on ka üsna suur ühisosa reeglites (sageli on programmeerimiskeeled inspireeritud üksteisest ning kasutatakse laialt levinud häid praktikaid). Lisaks võib juhtuda, et erinevates programmeerimiskeeltes tähistavad samad sümbolid erinevaid asju!
Toome välja mõningad olulised süntaksi ehk keelereeglid eelnevast programmikoodist
- Iga lause lõppeb semikooloniga
- Igas programmis peab olema main() funktsioon. Programmi täitmist alustatakse main() funktsioonist.
- main() funktsioonid paiknevad koodilaused on ümbritsetud avaneva { ja } sulguva loogelise suluga. Koodi mis jääb nende sulgude vahele kutsume koodiplokiks. See ühtlasi defineerib ära ka skoobi, millest räägime veidi hiljem.
- Sõne (tähemärkide jada, ingl. string ) ümbritsetakse jutumärkidega, nt . "This is a string"
- Kommentaarid algavad kahe kaldkriipsuga // (või ümbritsetakse /* ja */ sümbolitega)
- Funktsioonikutsed koosnevad funktsiooni nimest, millele järgnevad ümarsulud. Eelnevas programmis kasutasime kahte erinevat funktsiooni,
printf() ja
scanf()
- Funktsioonile edastatavad argumendid paiknevad sulgude sees
- Kui argumente on mitu, eristatakse need komadega
Koodimisstiili üle otsustame meie ise, eesmärgiga tagada koodi loetavus ja hallatavus. Koodimisstiili järgimine ei mõjuta seda kas programmikood on kompileeritav, käivitatav või kui hea on programmi jõudlus. Enamasti määratakse stiilinõuded meeskonnasiseselt või ettevõtte poolt, kelle heaks töötad. Selles kursuses oleme koodimisstiili nõuded määranud meie, sinu õppejõud. Lähemalt nõuetest võid lugeda stiilijuhendist, kuid toome mõningad neist ka siin välja
- Muutujad deklareeritakse üldiselt vahetult enne nende kasutusele võtmist
- Iga fail algab kommentaariga, mis kirjeldab ära programmi eesmärgi, autori ja kuupäeva
- Tühje ridu kasutame erinevate koodiosade ja loogiliste osade eraldamiseks visuaalselt
- Kommentaarid on enamasti vahetult enne koodiridu, mida nad selgitavad. Kahe kaldkriipsu järel on tühik. Kommentaar algab suure algustähega.
- Algav ja lõppev loogeline sulg, mis tähistavad koodiploki algust ja lõppu, on joondatud samale kaugusele vasakust äärest.
- Loogelised sulud paiknevad eraldi ridadel
- Koodiploki sees paiknev kood (loogeliste sulgude vahel) on trepitud ühe võrra
- Funktsiooni argumentide loetelus järgneb komale alati tühik
- Muutujate nimed kasutavad kaameliKüüruMeetodit (ingl. camel case). Esimene sõna algab väikese tähega, järgnevad sõnad algavad suure tähega.
- Muutuja nimetusest peab olema välja loetav muutuja eesmärk (sisu)
- Kõigi operaatorite ees ja järel on tühik (nt matemaatilised operaatorid nagu +, -. /, *; omistamise operaator =; võrdluse operaatorid <, >, ==, != jne)
- Koodirea pikkus ei tohi ületada 80 tähemärki. Kui koodirida osutub pikemaks, tuleb see poolitada.
tere.c teine osa: tinglik programmivoog
Teises programmi osas on meie eesmärk muuta vanuse arvutamist täpsemaks. Selleks tutvustame tingimuslauset, mis arvutab vanuse erinevalt vastavalt kas kasutaja sünnipäev oli juba ära olnud või on alles ees. Sedasi saame oma programmi ühe varasema vea ära parandatud.
Märka järgnevat algoritmi ja programmikoodi lugedes, et kuigi enamasti on nüüd programm täpne, jääb sellegi poolest üks veaolukord programmi sisse! Vaata, kas leiad üles?!
Tegevusdiagramm
Järgneva lahenduse kirjeldame esmalt ära diagrammi kujul. Muudatused algsesse rakendusse on järgnevad:
- Meil on vaja teada, kas kasutaja sünnipäev on sel aastal juba ära olnud või alles ees. Selleks lisame ühe täiendava tegevuse (action).
- Lisame juurde tingimuse, mis tagab erineva valemi kasutamise vastavalt kas sünnipäev oli juba ära või mitte. Selleks peame lisama
- hargnemise (junction node), mis alustab tingimuslauset
- koondumise (merge node), mis lõpetab tingimuslause
- kommentaari, mille sees kirjeldame ära tingimuse
- tõene/väär väljundid tingimusest, et teaks milline kontrollvoog on õige ehk millise tee peame valima
- Lõpetuseks uuendasime ka väljundit, kuna nüüd oleme võimelised vanust leidma kõigil peale ühe juhu
Programmikood
Oma koodi muudame vastavalt eelnevalt koostatud algoritmi kirjeldusele.
Selleks peame lisama täiendava päringu ja muutuja kasutaja sisestuse lugemiseks ning tingimuslause, mis selle põhjal õige valemi abil vanuse leiab.
Märka ka järgneva näitekoodi treppimist. Meeldetuletuseks, iga koodiploki sisu on trepitud ühe võrra. Kuna if/else lause asub juba main funktsiooni koodiploki sees, siis arvutustehted trepitakse veel ühe võrra kaugemale. See aitab meil kiiresti koodile peale vaadates aru saada koodi struktuurist ning aitab kaasa koodi haldamisele.
Nagu varasemalt sai kirjutatud, on sel programmil ka üks piirjuht, mille puhul antud valem osutub valeks. Kas leidsid selle üles!?
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
/** * File: hello_conditional.c * Author: Risto Heinsar * Created: 01.09.2014 * Edited: 23.07.2025 * * Description: This is the second hello example showing conditional program * flow. */ // Includes the standard input-output library (printf, scanf) #include <stdio.h> // The program always starts from the main() function int main(void) { // Print the greeting in the terminal. printf("Hello!\n"); printf("This program determines the approximate age of a person\n\n"); // Variable declaration, type int (integer), variable name "year" int year; // Prompt the user and read the year of birth as integer printf("Please enter your year of birth: "); scanf("%d", &year); int hasCelebratedBirthday; printf("Enter 1 if you've already had your birthday this year\n"); printf("Enter 0 if you have not.\n"); scanf("%d", &hasCelebratedBirthday); // Calculating age depending on the user's birthday // Note: There is a bug in this code that only triggers on an edge case. // Can you find it? int age; if (hasCelebratedBirthday) { age = 2025 - year; } else { age = 2025 - year - 1; } // Printing the result printf("You are %d years of age\n", age); // The program finished successfully. Integer 0 indicates success. return 0; } |