fel
le

Rekord

A vektorok és listák kíválóan alkalmasak arra, hogy több, azonos típusú adatot fogjunk össze. Tárolhatjuk benne például egy cég dolgozóinak havi telefonköltségeit. De hogyan tároljuk el azt is, hogy mi a neve a dolgozónak, akinek ennyi-meg-ennyi a telefonköltsége?

A rekordok olyan adatszerkezetek, melyek:

  • összetett, vagyis egy rekord típusú változóban egy időben több adat is tárolható,
  • inhomogének, vagyis a bennük tárolt adatok típusai különbözőek is lehetnek,
  • random elérésű, vagyis a rekord elemeihez azonos sebességgel lehet hozzáférni,
  • fix méretűek, vagyis deklaráláskor meg kell adni milyen adatokat (és hány darabot) akarunk tárolni,
  • folytonos tárolású, a rekordban tárolt értékek a memóriában egymás után helyezkednek el.

Egyszerű rekord

A fenti problémára (a név és a telefonköltésgek tárolása) a rekord nem önállóan nyújt megoldást, de mindjárt látni fogjuk hogy sok rekord már igen. Első lépésben írjuk le, mi mindent akarunk egyetlen dolgozóról tárolni:

1. ábra: A rekord típus deklarációja

Majd hozzunk létre ezen kis adatcsomagokból egy listát (de erről a következő fejezetekben bővebben lesz szó):

List<dolgozo> koltsegek = new List<dolgozo>();
 

A dolgozó rekordokból álló lista már mindent tud, amire szükségünk van. Elemei rekordokok, és minden rekord maga tárolja el a neveket és a telefonköltségeket. Így a név és a költség összekapcsolása teljes.

Természetesen, ha a neveken túl pl. a beosztásokat is tárolni szeretnénk, akkor a rekord bővíthető újabb részekkel:

class dolgozo
{
   public string neve;
   public int telefonkoltsege;
   public string beosztas;
   public int fizetes;
   public bool fonok_e;
}
 

A rekord elemeit mezőknek nevezzük. Ez a bővített rekord 5 mezőből áll. Minden mezőnek van típusa és neve. A beosztas mező típusa string.

Ezen lépés, amikor magát a rekord szerkezetét írjuk le - típusdeklarációnak minősül. Egy új típust hozunk létre. A típusunk neve az általunk választott dolgozo lesz. A típusdeklarációt a class kulcsszóval vezetjük be - ezt jelöli hogy egy új rekord típust fogunk létrehozni. Meg kell adni az új típus nevét, majd kapcsos zárójelek között fel kell sorolni a rekord mezőit.

Minden meződeklarációt a public kulcsszóval vezetünk be, majd megadjuk a mező típusát és nevét. A public kulcsszó elhagyása nem jelent szintaktikai hibát, de azt a mezőt nem fogjuk tudni használni a kódunkban, ezért ne feledkezzünk el a public kiírásáról.

Deklaráció

A rekordok is referencia típusú változóknak lesznek. Vagyis minden rekord típusú változó (függetlenül attól, hogy melyik rekordról is van szó) mindig 4 byte helyigényű. Ezen a területen kezdetben a nul érték kerül tárolásra, és ezen a ponton még a rekord nem működik, a mezői nem alkalmasak az adatok tárolására.

dolgozo lajos;
dolgozo bela;
 

Kezdőértékadás

A rekord típusú változóknak (mint minden referencia típusú változónak) a new kulcsszóval kell helyet foglalni. Szokásosan, a new után meg kell adni újra a helyfoglaláshoz szükséges információkat.

lajos = new dolgozo();
bela = new dolgozo();
 

Vagy egyben:

dolgozo lajos = new dolgozo();
dolgozo bela = new dolgozo();
 
2. ábra: A rekord példány a memóriában

Miközben a dolgozo azonosító magát a rekord típust azonosítja, a lajos és bela azonosítók ezen típus példányait azonosítják. Ez hasonló, mint az int a deklaráció esetén, ahol az int a típus, a a példány azonosítója. Egy típusból több példány is készíthető.

Műveletek mezőkkel

Ahhoz, hogy a mezőkkel dolgozni tudjunk, először egy létező rekord példányra van szükségünk. A csak deklarált, de kezdőértékkel nem rendelkező példányoknak nincsenek még mezőik, így azok esetében a hivatkozás hibás! A mezőre a példánynév.mezőnév alakban kell hivatkozni.

dolgozo lajos;
lajos.nev = "Nagy Laja";  // HIBÁS - nincsenek mezői
 
dolgozo bela = null;
bela.fizetes = 120000;    // HIBÁS - nincsenek mezői

dolgozo.fizetes = 45000;  // HIBÁS - a típusnak nincsenek mezői

dolgozo mari = new dolgozo();
mari.neve = "Juhászné Szép Annamária"; // JÓ !!
mari.fizetes = 156000;                 // JÓ !!
 

A fenti példákban a lajos és bela példányokhoz nincs másodlagos tárterület lefoglalva, így a mezőkben tárolandó értékeket nem lehet hol tárolni. A dolgozo.fizetes gyakori ötlet, de hibás. A dolgozo a típusnak a neve, a típusnak magának nincsenek mezői, csak a típusból létrehozott példányoknak. A mari egy példány, a new segítségével ki is van alakítva neki a másodlagos tárterület, így a példány minden szempontból alkalmas az adatok tárolására.

Rekordok közötti értékadó utasítás

Ha van két ugyanazon típusból készített rekord példányunk, akkor értelmezhetjük közöttük az értékadó utasítást. Ez természetes, hisz az értékadó utasítás akkor biztosan végrehajtható, ha mindkét oldal típusa azonos.

dolgozo mari = new dolgozo();
mari.neve = "Juhászné Szép Annamária";
mari.fizetes = 156000;                

dolgozo gizi;
gizi = mari;  // !! ÉRTÉKADÁS !!

gizi.neve = "Varga Gizella";
Console.WriteLine(mari.neve);
 

Mi lesz ennek a hatása, működése? A gizi és a mari változók is referencia típusú változók, alapvetően 4 byte helyfoglalásúak. A referencia típusú változók között általában is igaz, hogy az értékadás során csak a referencia (memóriacím) másolódik át. Eredményeképp a gizi''-ben tárolt és a mari''-ban tárolt memóriacímek megegyeznek, így a továbbiakban a gizi.neve és a mari.neve mezők lényegében ugyanazon név mezők. Ezért a fenti esetben a mari.neve kiírás a "Varga Gizella" szöveget fogja megjeleníteni.

3. ábra: A két rekord változó értékadás után

Jegyezzük meg tehát, hogy a rekord változók közötti értékadó utasítás nem a mező értékeket másolja át egyik rekordból a másikba (holott első felületes ellenőrzés után gondolhatnánk erre is), hanem a memóriacímeket másolja át (4 byte mozgatása). E miatt ugyanazon rekord példányt (mezőket) e pillannattól kezdve két változón keresztül is elérhetjük és módosíthatjuk.

Hernyák Zoltán
2013-01-24 11:02:00