A múltkori bevezető után, most nézzük meg egy kicsit részletesebben, hogy hogyan is működik a C nyelv struktúrája, alapvető nyelvi elemei.
Ez alkalommal egy Digitális Órának az implementációját fogom bemutatni. A feladat nagyon egyszerű, csinálunk egy órát, ami mutatja az eltelt időt és mindig 0 óra 0 perctől indul.
A feladatot érdemes kisebb részekre bontani:
- Kell egy óra algoritmus, ami másodpercenként számol és ha elérte a 60 másodpercet, akkor vált percet majd órát is.
- Kell egy megjelenítő algoritmus, ami kiírja a pontos időt.
- Kell egy futtató rendszer, ami elindítja az órát és nem is lehet leállítani.
Futtató keretrendszer
Kezdjük az utolsó ponttal, talán az a legkézenfekvőbb a múltkori feladat bemutatása után. Mint mindig, így most is lesz egy belépési pontja a programunknak ami nem tesz majd mást, mint meghívja az óra algoritmust. Lesz ugyan egy kilépési pontja is a programnak, de ha jól dolgoztunk, akkor az sosem fog meghívódni. Hogy ezt pontosan hogyan kell elképzelni, ehhez később még visszatérek.
Óra algoritmus
Hogyan működik egészen pontosan egy digitális óra? Először is van 3 része:
- másodperc [0..59]
- perc [0..59]
- óra [0..23]
A feladatnak megfelelően mindegyiket 0-ra állítjuk, mint kiindulási érték. A másodperc mutatót másodpercenként növeljük és ha elérte a 60-at, akkor 0-ra állítjuk és növelünk a perc részen egyet. Majd ha a perc is elérte a 60-at akkor az órán is növelünk egyet. 23:59:59-nél pedig visszaállítunk mindent 0-ba és az egész kezdődik elölről.
Egyetlen kérdés van, hogyan fogjuk pontosan másodpercenként egyszer megnövelni a másodperc mutatót? Hogyan mérjük az eltelt időt?
Nos a legegyszerűbb megoldás, ha indítunk egy ciklust, ami számol körülbelül 1 másodpercig, majd végrehajtjuk a saját kódunkat, aztán megint a ciklusban vagyunk 1 másodpercig. Ezzel a megoldással két probléma van:
- Nem lesz elég pontos
- Folyamatosan foglalja a CPU-t, pedig az csak az idő tört részében fog hasznos munkát végezni, egyébként egy ciklusban teker
Szerencsére már más is gondolt hasonló időmérésre, ezért kidolgoztak egy úgynevezett altató könyvtárat. Ennek lényege, hogy a processzorban megszakítják az aktuális program végrehajtását a megadott ideig. Amíg nem az aktuális program fut, addig a CPU tud más feladatokkal foglalkozni és a pontossága is nagyságrendekkel jobb lesz az előző megoldásnál. Sajnos azonban nem operációs rendszer független a megoldás, jelen példában a Windows-os megoldást mutatom be:
#include
Sleep(1000);
Tehát a Sleep() függvény paraméterként milliszekundumot vár és amíg a megadott idő le nem telik, addig a program futása várakozik. Majd a megadott idő után a program futása újra onnan folytatódik, ahol az altatás előtt abbamaradt.
Fontos, hogy az óra algoritmus sosem tér vissza, tehát nem lehet a programból leállítani. Ez viszonylag furcsán hangozhat, de beágyazott rendszerekben gyakran előfordul, hogy addig működik amíg van áramellátása és nincs semmilyen mód a kikapcsolásra. Ezzel a gondolattal analóg módon fog a mi óránk is működni. Lesz benne egy úgynevezett végtelen ciklus, ami másodpercenként egyszer fogja végrehajtani az óra algoritmust. A végtelen ciklus sosem fog megszakadni normál körülmények között.
A teljes algoritmus így épül fel:
Megjelenítő algoritmus
Én a következő formátumba szeretném mindig megjeleníteni az aktuális időt:
hh:mm:ss
De nem szeretném mindig a múltkor bemutatott printf() kiírató függvényt hívni és el szeretném szeparálni az óra algoritmustól azt, ahogyan az idő megjelenítődik. Lehet, hogy a későbbiekben másképpen szeretném megmutatni az eltelt időt és előnyös, ha ehhez csak a kód egy jól dedikálható részéhez kell hozzányúlnom. Ez a rész majd csak az éppen aktuális időt fogja megkapni bemenetként, neki nem kell tudnia értelmeznie ezeket az adatokat csak kiíratni.
Ennek érdekében készítek egy különálló Header fájlt, ami kizárólag a megjelenítő algoritmus definícióját fogja tartalmazni. Ezzel párhuzamosan elkészítem a Source fájlt is, ami pedig magát az algoritmust valósítja meg:
Sajnos nem elegendő a korábbiakban definiált formátumnak megfelelően felparaméterezni kiírató függvényt. A printf() függvény ugyanis nem tesz mást, mint egy belső bufferbe, tárolóba betölti az adatokat, majd a buffer tartalmát a megfelelő pillanatban kiteszi a képernyőre. Azonban nekünk most determinisztikus működésre van szükségünk a CPU altatása miatt, ezért a buffer feltöltése után rögtön rá is kényszerítjük a programot a buffer kiürítésére, ezért felel az fflush() függvényt. Ezáltal az eredmény rögtön láthatóvá válik a képernyőn.
Erőforrás kezelés
Jelen példában a legnagyobb szám amire szükségünk van, az nem más mint az 59, a legkisebb pedig a 0, tehát nincs szükségünk negatív számokra. Az 59 egy elég kicsi szám, egészen pontosan 6 biten elfér.
Annak érdekében, hogy a lehető legkevesebb memória felhasználásával meg tudjuk oldani a feladatot érdemes a legkisebb típusban ábrázolni a számokat, ami képes kezelni 6 bitet összefüggően. Ez nem lesz más, mint a 8 bites unsigned char típus. Ennek kezelésére szintén létrehozok egy különálló Header fájlt, aminek tartalma tehát a következő:
A typedef egy önálló C parancs, amely arra szolgál, hogy új típusdefiníciókat tudjunk egyszerűen létrehozni. Az uint8_t a klasszikus elnevezése ennek a típusnak.
A program végrehajtásának az eredménye:
Jól látható tehát, hogy a központi algoritmus viszonylag egyszerű. Egy valódi környezetben az idő megjelenítése kicsit másképpen működik, de ez a rész, ahogyan fent is leírtam, jól elszeparálható. Ezen felül még néhány gombot kellene beprogramozni és már kész is a valódi digitális óra. A valódi óra gombjai azonban számítógépen is jól szimulálhatóak a billentyűzet gombjainak segítségével, ezért érdemes lehet kísérletezni ennek az implementálásával. A mintapéldát a szokásos helyen megtaláljátok.
Ha pedig komolyan érdekel a téma, akkor ajánlom figyelmedbe a hamarosan induló Java Tanfolyamomat!

Szia, Bajor Tamás vagyok, a Programozz Te Is oldal alapítója és oktatója. Köszi, hogy itt vagy és éppen az én cikkem olvasására fordítod a drága idődet! Azért dolgozom minden nap, hogy neked segítsek a programozás világában minél profibban elmélyülni. A cikkek egyetlen írójaként rengeteg munkát és energiát fektetek mind az oldalba, mind pedig az oktatásba!
Arra kérlek, ha tetszett cikk amit olvastál vagy szívesen veszed az ingyenes anyagokat akkor dobj egy Like-ot a Facebook-on, ezzel is támogatva a munkámat. Neked ez egy apró kattintás, nekem pedig hatalmas segítség!