2015. november 5., csütörtök

Következő óra anyaga

A Pascal és a C program szerkezetének és utasításainak összehasonlítása.

A Pascal program szerkezete:

program programnév;
uses unitok;
{A deklarációk kezdete.}
const konstansok;
type típusdefiníciók;
var globális deklarációk;
procedure eljárásnév(paraméterek);
    lokális deklarációk
begin
    utasítások
end;
function függvénynév(paraméterek): visszatérési típus;
    lokális deklarációk
begin
    utasítások
end;
…  
{A deklarációk vége.}
{A főprogram blokkjának kezdete.}
begin
    utasítások
end.
{A főprogram blokkjának vége.}

A Pascal nyelven a főprogram blokkjában lévő utasítások kerülnek végrehajtásra. Ha ezek eljárás és függvényhívásokat is tartalmaznak, akkor az eljárások és függvények blokkja is végrehajtódik. Minden azonosítót - konstanst, cimkét, típust, változót, eljárást és függvényt – deklarálni kell.

program pelda;
var i, j, k: integer;
{Két egész közül a nagyobbat adja.}
function max(a, b: integer): integer;
begin
    if a>b then max:=a
    else max:=b;
end;
{Két egész számot felcserél.}
procedure csere(var a, b: integer);
var temp: integer;
begin
    temp:=a;
    a:=b;
    b:=temp;
end;
{A főprogram.}
begin
    i:=12;
    j:=20;
    writeln(’Csere előtt: i=’, i:2, ’j=’, j:2);
    csere(i, j);
    writeln(’Csere után: i=’, i:2, ’j=’,  j:2);
    k:= max(i, j);
    writeln(’A nagyobb szám: ’, k:2);
end

A C program szerkezete:

preprocesszor parancsok
típusdefiníciók
függvény prototípusok
globális változók
függvények

A C függvény szerkezete a következő:

visszatérési típus függvénynév(paraméterek){
    lokális deklaráció
    utasítások
return visszatérési érték
}

A C- ben is minden nevet deklarálni kell. Valamelyik függvénynek kötelező a main nevet adni, ez lesz a főprogram. Amikor a program végrehajtása megkezdődik, akkor a main függvény hívódik meg, és azon belül kerül sor a többi függvény aktivizálására. Néhány függvénynek a típusa void, ami azt jelenti, hogy nincs visszatérési értéke, így ezek hasonlóak a Pascal eljárásokra

#include <stdio.h>
int i, j, k;
/*Két egész közül a nagyobbat adja.*/
int max(int a, int b){
    if (a>b) return a;
    else return b;
}
/*Két egész számot felcserél.*/
void csere(int *a, int *b){
    int temp;
    temp= *a;
    *a= *b;
    *b= temp;
}
/*A main függvény.*/
main(){
    i=12;
    j=20;
    printf(„Csere előtt: i=%2d j=°%2d\n”, i, j );
    csere(i, j);
    printf(„Csere után: i=%2d j=°%2d\n”, i, j );
    k=max(i, j);
    printf(„A nagyobb szám: %2d\n”, k);
    return;
}

A Pascal nyelv utasításai:

Az értékadó utasítás:
változónév:= kifejezés;
A változónév azonosítójú változó felveszi a kifejezés kiszámított értékét. A két oldalnak azonos típusúnak kell lennie.

A goto utasítás:
goto label;
Feltétel nélküli vezérlésátadást valósít meg. A program végrehajtása a label cimkénél folytatódik. Kerüljük a használatát. Helyette használjuk a break és continue eljárásokat.

Az eljáráshívás:
eljárásnév(paraméterek);
Az eljáráshívás folyamán a hívott programrész végrehajtódik, majd a vezérlés visszakerül a hívás utáni utasításra.

Az utasításblokk:
begin
utasítás;
utasítás;

end;
Az utasításblokk egyetlen utasítássá fogja össze az általa közrezárt utasításokat. Pascal-ban utasításblokkban csak utasítás állhat. Ahol utasítás állhat, ott utasításblokk is állhat.

A with utasítás:
with rekordváltozó do utasítás;
Kényelmes hozzáférést biztosít a rekord mezőihez.

A feltételes utasítások:
A nyelv kétféle feltételes végrehajtási konstrukciót tartalmaz.

Egyszerű elágazáshoz:
if logikai kifejezés then utasítás
else utasítás;
Ha a logikai kifejezés igaz, a then utáni utasítás hajtódik végre, egyébként az else ág utáni utasítás. Az else ág opcionális.

Többirányú elágazáshoz:
case kifejezés of
lista: utasítás;
lista: utasítás;

else utasítások
end;
A kifejezés csak sorszámozott típusú lehet. A lista konstansok sorozata, amely tartalmazhat résztartományt is. Ha a kifejezés értéke megegyezik valamelyik konstanssal, a konstans után álló legfeljebb egy utasítás vagy utasításblokk kerül végrehajtásra, majd az end utáni sorra kerül a vezérlés. Egyébként az else után található utasítások futnak le. Az else ág opcionális.

A ciklusutasítások:
for változó:=kezdőérték to végérték do utasítás;
A változó értéke kezdőérték végértékig nő.

for változó:=kezdőérték downto végérték do utasítás;
A változó értéke kezdőértéktől végértékig csökken.

while belépésifeltétel do utasítás;
Amíg a belépésifeltétel igaz, végrehajtja az utasítást.

repeat utasítás until kilépésifeltétel;
Amíg a kilépésifeltétel hamis, végrehajtja az utasítást. Egyszer mindig lefut.

A C nyelv utasításai:

A kifejezés utasítás:
kifejezés;
Tetszőleges kifejezés utasítás lesz, ha pontosvesszőt teszünk mögé.

Az utasításblokk:
{
lokális definíciók és deklarációk
utasítás;
utasítás;

}
Az utasításblokk egyetlen utasítássá fogja össze az általa közrezárt utasításokat. A Pascallal ellentétben, C-ben utasításblokkban utasítás és lokális deklaráció is állhat. Ahol utasítás állhat, ott utasításblokk is állhat.

A feltételes utasítások:
A nyelv kétféle feltételes végrehajtási konstrukciót tartalmaz.

Egyszerű elágazáshoz:
if kifejezés utasítás;
else utasítás;
A kifejezés tetszőleges kifejezés lehet, melynek 0 értéke esetén hamis, egyébként igaz elágaztatás történik. Az else ág opcionális.

Többirányú elágazáshoz:
switch (kifejezés){
case konstans kifejezés: utasítások
case konstans kifejezés: utasítások

default: utasítások
}
A konstans kifejezés csak egyetlen érték lehet, és egyedinek kell lennie. A kifejezésnek megfelelő sor kerül végrehajtásra, majd sorban lefut az összes további utasítás. Ha egyik case konstans sem egyezik meg a kifejezés értékével, a futás a default cimkénél folytatódik. A default opcionális. Pascal-szerű végrehajtáshoz, az esethez tartozó utasítássorozatot a break utasítással kell lezárni.

A ciklusutasítások:
for (init kifejezés; feltétel kifejezés; léptető kifejezés) utasítás;
Belépéskor kiértékelődik az init kifejezés, majd amíg a feltétel kifejezés értéke nem 0, végrehajtódik az utasítás, majd kiértékelődik a léptető kifejezés. Sokkal rugalmasabb a Pascal for ciklusánál, elhagyhatjuk bármely kifejezést.

while (kifejezés) utasítás;
Amíg a kifejezés nem 0, végrehajtja az utasítást.

do utasítás while (kifejezés);
Amíg a kifejezés nem 0, végrehajtja az utasítást. Egyszer mindig lefut.

A break utasítás:
Az utasítás hatására, az utasítást tartalmazó legközelebbi switch, while, for, do-while utasítások működése megszakad, és a vezérlés a megszakított művelet utáni első utasításra kerül.

A continue utasítás:
Az utasítás a ciklusutasítások soron következő iterációját indítja el, a continue után elhelyezkedő utasítások átlépésével.

A goto utasítás:
goto label;
Feltétel nélküli vezérlésátadást valósít meg. A program végrehajtása a label cimkénél folytatódik. Kerüljük a használatát. Helyette használjuk a break és continue utasításokat.

A return utasítás:
return;
return kifejezés;
Az utasítás befejezi az éppen futó függvény működését és a vezérlés visszakerül a hívó függvényhez. Az első formában void függvényből léphetünk ki, nem ad vissza értéket, második esetben, a kifejezést adja vissza a hívónak.

Operációsrendszerek processzorkezelése
Alapvetõ definíciók

    Szoftverek osztályozása : rendszerprogram / felhasználói program

    Operációs rendszer := A legalapvetõbb rendszerprogram amely a számítógép erõforrásait kezeli és azt az alapot biztosítja, amelyen felhasználói programok írhatóak (és futtathatóak).

    Erõforrás := Minden olyan dolog amelyre egy programnak szüksége lehet a futása során. Pl.:
        CPU idõ
        memória
        B/K eszközök
        adatállományok
        fájlrendszer
        kommunikációs szolgáltatások
        stb...

    Processzus := Egy végrehajtás alatt álló program annak környezetével és állapotával együtt. A környezetének része a hozzárendelt memóriaterület, a nyitott fájlok (fájlleírók), CPU állapota, futás állapota is.

    Processzus állapotok := Az operációs rendszer egyik erõforrása a CPU. A rendszerben egyszerre futtatható processzusok mennyisége véges, CPU mennyiség és típus függõ. Annak eldöntése, hogy mely CPU erõforrás melyik processzust futtatssa egy adott idõben, az ütemezõ feladata. Az ütemezõ része az operációs rendszernek. Az ütemezõ mûködése során a processzusokhoz állapotokat rendel:

Szálak és szinkronizáció

Szálak := Azonos memóriaterületen (címtartományban), de külön ütemezett és külön futási állapottal bíró végrehajtási egységek. Modern operációs rendszerekben az ún. egyszálú programot is szálakkal valósítják meg.

Olyan esetekben amikor egymással konkuráló végrehajtási egységek azonos erõforrásokat érnek el szükség lehet az elérések szinkronizációjára. Ennek hiányában az adott erõforrás nem tervezett állapotot vehet fel amely program hibához vezet. Az ilyen helyzeteket versenyhelyzetnek is hívják. Ennek elkerülésére szinkronizációs mechanizmusokat használhatunk fel:

Mutex (Mutual exclusion) := Kölcsönös kizárás mechanizmusa. Ha egy végrehajtási egység birtokolja, akkor másik végrehajtási egység nem birtokolhatja. Ha a másiknak szüksége van rá, várnia kell. Mûveletei:

    Lock
    Unlock

Read-Write lock := író-olvasó lock. Egyszerre max. 1 író, vagy tetszõleges számú olvasó birtokolhatja. Egyes implementációk engedik az olvasó-író átmenetet, amikor egy olvasó van. Mûveletei:

    Read Lock
    Write Lock
    Upgrade Lock
    Unlock



Szemafor := A szemafor megadott számú konkurens elérést enged. Amikor a megadott számú végrehajtási egység már birtokolja, a következõnek várnia kell amíg, az egyik elengedi. Mûveletei:

    Down
    Up

Kritikus terület := Egy program részt lehet védeni vele, hogy a kritikus terület eleje és vége között maximum egy végrehajtási egység tartózkodhat, a többi amely szintén azt a kódrészletet készül végrehajtani, várni fog. Mûveletei:

    Enter
    Leave

Barrier := Az ellenkezõje a szemafornak. Megadott számú végrehajtási egységet bevár. Amikor mind elérkezik a barrierhez-akkor egyszerre futni engedi õket. Mûveletei:

    Wait

A programozó feladata, hogy az adott feladathoz kiválassza a megfelelõ szinkronizációs mechanizmust. A megfelelõ kiválasztása sebesség szempontjból kritikus lehet, mivel ezek különbözõ mértékû párhuzamos futást tesznek lehetõvé.

Processzusok közötti kommunikáció (Inter Process Communication=IPC)

Feladatoktól függõen szükség lehet különbözõ processzusok információ cseréjére. Az információ csere speciális módjai a már említett szinkronizációs mechanizmusok. Ezen kívül lehetõség van adatok átadására is a következõ mechanizmusok valamelyikével:

    Üzenet küldés
    Osztott memóriába írás és olvasás onnan

Filozófusok

1965-ben Dijkstra felvetett és megoldott egy szinkronizációs problémát, amelyet étkezõ filozófusok problémának nevezett el. A probléma a következõ: öt filozófus ül egy kerek asztal körül. Mindegyik filozófusnak van egy tányér spagettije. A spagetti olyan csúszós, hogy egy filozófusnak két villára van szüksége, hogy megegye. Minden egymás melletti tányér között van egy villa. A filozófusok élete egymást váltogató evésbõl és gondolkodásból áll. Amikor egy filozófus éhes lesz, megpróbálja megszerezni a bal és jobb oldalán lévõ villát, egyszerre csak egyet, tetszõleges sorrendben. Ha sikerül mindkét villát megszereznie, akkor eszik egy ideig, majd lerakja az evõeszközöket és gondolkodik. Kulcskérdés: tudunk-e olyan programot készíteni mindegyik filozófus számára, amelyik azt csinálja, amit elvárunk és soha nem akad el? A nyilvánvaló megoldás (próbálja megszerezni a bal oldalon lévõ villát, majd ha ez megvan, szerezze meg a job oldalon lévõt) sajnos hibás. Ha ugyanakkor szerzi meg mind az öt filozófus a bal oldali villát, akkor nem lesz villa a jobb oldalon és holtpont alakul ki. Az sem segít, ha várakozunk. Véletlen ideig történõ várakozás nem hoz garantált sikert. A korrekt megoldás bináris szemaforokat használ.

Iró-olvasó

Az író-olvasó probléma nem más, mint az adatbázisok hozzáférési problémáit modellezõ feladat (például repülõjegy-foglalás). Elfogadható, hogy több olvasó legyen a bázisban egyidejûleg, de az írónak kizárólagos jogot kell adni a hozzáféréshez. Ha az olvasó mindig új olvasókat enged maga mellé, (mert teheti), akkor hatékony egyidejûséget kapunk. Ugyanakkor a bázis elõtt akár a végtelenségig is várakozhat egy író, hogy az olvasók elfogyjanak, és egyedül maradjon a bázisban. Ezt elkerülendõ, ha író várakozik, és újabb olvasó érkezik, azt az író maga mögé parancsolja. Csak azt kell megvárnia, hogy a bázisban tartózkodó olvasók elfogyjanak. Ez a módszer kevésbé hatékony, mert nem támogatja az egyidejû olvasást oly mértékben, mint a filozófusos.

Alvó borbély

Megint egy másik klasszikus IPC probléma a borbélynál fordul elõ. A fodrászüzletben egy borbély van, egy fodrászszék, és n szék a várakozó vendégeknek. Ha éppen nincs vendég, akkor a orbély leül a fodrászszékbe és elalszik. Ha egy vendég érkezik, fel kell ébresztenie. Ha további vendégek érkeznek, míg a borbély egy vendég haját vágja, akkor vagy leülnek (ha van üres szék) vagy elmennek (ha minden szék foglalt).

Megoldásunk három szemafort használ: customers (a várakozó vendégeket számolja, a fodrászszéken ülõ kivételével), barbers (az unatkozó borbélyok száma, értéke 0 vagy 1 lehet) és mutex (a kölcsönös kizárásra használunk.

Ütemezési algoritmusok

    Round-Robin := Az ütemezési egységek sorban egymás után kerülnek futó állapotba. Minden végrehajtási egység azonos mennyiségû idõt kap. A kiosztott idõszeletrõl önszántából lemondhat, ha olyan rendszerhívást hív amely blokkolást eredményez.

    Prioritásos ütemezés := A legmagasabb prioritású végrehajtási egység fog futni. Az egyes egységek prioritása idõben változhat. Például futás után átmenetileg csökkenthetõ azért, hogy a többi processzus is futhasson.

    Prioritási osztályok := Azonos osztályon belül round-robin ütemezés.

    Garantált ütemezés := Az ütemezõ figyel arra, hogy n darab processzus 1/n idõt használjon fel.

    Sorsjáték ütemezés := Minden ütemezési egység egy sorsjegyet kap, amelyek közül az ütemezõ véletlenszerûen választ.

    Valós idejû ütemezés := Külsõ fizikai eszközök számára garantálja, hogy a hardver megszakítás megadott idõn belül feldolgozásra kerüljön.



--------
 Pascal adattípusok, deklarálásuk, ábrázolásuk, konstansok, mûveletek, konverziók, kompatibilitás; a típusokhoz kapcsolható fontosabb függvények, eljárások
1. Egyszer&ucirc; típusok értékek
Deklarálásuk: Var Változonev: Tipus ;
  - Egészek:
        Byte                   0..255     1 byte
        Word                   0..65,535    2 byte
        ShortInt?            -128..127    1 byte
        Integer          -32,768..32,767    2 byte
        Longint   -2,147,483,648..2,147,483,647   4 byte

  Számkonstansok pl.:8 ; const Valtozonev = 5;
     

           Mûveletek egész típusokkal(az eredmény is egész típusú):
+,- (elõjel) *, +, - (a megszokott szorzás, összeadás, kivonás) div egész osztás, pl. 13 div 3 = 4 mod maradékképzés, pl. 13 mod 3 = 1
 Függvények, eljárások egész típusokkal:
Inc(I, N) I értékét növeli N-el (inkrementálja), N elhagyható, abban az esetben 1-gyel növel. Dec(I, N) I értékét csökkenti N-el (dekrementálja), N elhagyható, abban az esetben 1-gyel csökkent. Randomize Paraméter nélküli eljárás, olyan programban, ahol véletlen számokat állítunk elõ a Random függvénnyel, általában egyszer meg kell hívnunk. Inicializálja (elõkészíti) a véletlen szám generátort. Abs(I) Abszolút érték függvény. Sqr(I) A paraméterének a négyzetét állítja elõ. Megegyezik I * I-vel, ha a paramétere egy hosszabb kifejezés, akkor célszerû használni. Trunc(R) Úgynevezett konverziós függvény, valós paraméterét egész típusúvá konvertálja a törtrész levágásával.
    X := 4.56;
    A := Trunc(X)    {A értéke 4 lesz, típusa egész}
Round(R) Úgynevezett konverziós függvény, valós paraméterét egész típusúvá konvertálja kerekítéssel.
    X := 4.56;
    A := Round(X)    {A értéke 5 lesz, típusa egész}
Random(I) Egy véletlen egész számot állít elõ a 0..I-1 intervallumban. (Ld. még Randomize és valós típusok függvényei.) - Logikai:
        Boolean         True,False    1 byte
   0 vagy 1 értéket vehet fel
  Konstansok: True,False
  Mûveletek logikai típusokkal: not, and, or, xor (fontos a zárójelezés)
  Függvények:  
Odd(I) Párosság vizsgálat. Visszatérési értéke igaz, ha I páratlan.
 - Karakter:
        Char            bármely ASCII karakter   Pl: 'A' 1 byte

  Konstansok: karakteres konstansok &#8217;A&#8217; vagy  #65
  Mûveletek: nincs olyan mûvelet amelynek az eredménye is Char típusú
  Relácíós mûveletek lehetnek, de az eredmény logikai típusú lesz.
  Függvények:  
Ord(K) A karakter ASCII kódját adja vissza. Chr(I) Az Ord függvény inverzének tekinthetõ, az ASCII kódnak megfelelõ
  karaktert adja vissza.
   UpCase?(K)   Ha a paramétere egy kisbetû, akkor a nagybetûs változatával tér vissza, 
        egyébként nincs hatása.
   Pred(K)  A K-t megelõzõ karakterrel tér vissza.
Succ(K) A K-t követõ karakterrel tér vissza. - Felsorolásos vagy intervallum típus:
 A felsorolásban szereplô elemek  Pl.:  T=(ôsz,tél)
  A felsorolt típus értékei azonosítók lehetnek, melyeket a deklaráláskor fel kell sorolnunk. Például:
  var Tantargy: (Magyar, Tori, Matek, Tesi);
  A változó (Tantárgy) által felvehetõ értékeket zárójelben, vesszõvel elválasztva adjuk meg. Az 
  értékekhez a rendszer egy sorszámot rendel, 0-tól kezdõdõen. Az intervallum típust egy már létezõ típus 
  intervallumaként, a felsõ és alsó határával adhatjuk meg. Például:
  var Szamjegy: '0'.. '9';
      Honap: 1..12;
Lényeges, hogy az intervallum határai közé pontosan két pontot írjunk. - Valós:
        Real             2.9E-39..1.7E38    6 byte
        Single            1.5E45..3.4E38
        Double          5.0E-324..1.7E308
        Extended       3.4E-4932..1.1E4932
        Comp         -2(63-on)+1..2(63-on)-1
        (Lebegôpontos ábrázolás, Real "felett" aritmetikai társprocesszor
         szükséges, illetve annak emulálása. Lásd $N és $E direktivákat.)

  Konstansok:   Tizedespontot kell alkalmaznunk (nem vesszõt), nagy, illetve kis abszolút 
    értékû számok esetén használhatjuk a normál alakú formát.
  Mûveletek:   Az eredmény is valós típusú: +,- (elõjel), *, /, +, - 
Az eredmény logikai típusú: <, >,E, >=, =, <> (Vigyázzunk, nincs div és mod!)
  Függvények, eljárások: Egész típusoknál leírtak(Abs,Sqr,Round,
Trunc,Str,Val,Randomize) +
    Sqrt(R)  Egy szám négyzetgyökét adja vissza.
    Sin(R), Cos(R) Egy radiánban megadott szög szinuszát, illetve koszinuszát 
adja vissza.
    ArcTan?(R) Arkusztangens függvény, visszatérési értéke radiánban 
értendõ.
    Pi  Paraméter nélküli függvény, a pi értékét adja vissza.
Exp(R) Exponenciális függvény, eR &#8211; ent adja vissza. (e &#61504; 2,71) Ln(R) Paraméterének a természetes alapú logaritmusát adja vissza. Int(R) A paraméterének az egész részét adja vissza, de valós típusúként kezelve. Frac(R) A paraméterének a tört részét adja vissza. Random Már találkoztunk vele az egész típusoknál, ha paraméter nélkül hívjuk meg, akkor egy valós véletlen számot állít elõ a 0..1 intervallumban 2.Struktúrált típusok
- String:
        String[szám]    Legfeljebb szám hosszúságú ASCII karakter 1-255 byte
 Deklarálása:  var 
      S1: string;  0-255 byte
          S2: string[20];       0-20 byte
 Konstansok: Write('String konstans') ;
       S1 := '';
 Mûveletek: Konkatenáció jele: + Karakterláncok összefûzése
       Relációs mûveletek, melyek logikai értéket adnak
  Függvények:  Length Egy karakterlánc hosszával tér vissza.
Pos Egy rész karakterláncot keres egy karakterláncban. Copy A karakterlánc egy részével tér vissza.
    Concat Stringek sorozatát egymáshoz fûzi, konkatenálja. (Kiváltható az 
     egyszerûbb + mûvelettel.)
 Eljárások: Str Egy numerikus értéket karakterlánccá konvertál. 
     Val Egy karakterláncot numerikus értéké konvertál. Az Str fordítottjának 
      tekinthetõ.
     Delete A karakterlánc egy részét kitörli. 
     Insert Egy karakterláncot beilleszt egy másikba.

- Tömb:
        Tomb : Array[index1,index2...] of alaptípus
        (index csak sorszámozott típusú, az indexszámtól függ a dimenzió)
A tömb adott számú, azonos típusú elemet tartalmazó összetett(strukturált) adattípus. A tömb elemeinek a sorrendje kötött, minden elemnek van egy indexe, az elemekhez közvetlenül hozzáférhetünk, egy tömbelemre az indexével hivatkozhatunk.
 Mûveletek: Két azonos típusú tömbre az értékadás és az egyenlõség 
      vizsgálat megengedett.

 - Rekord: Pl.: type
      Nev = (Teglalap, Negyzet, Kor)
      Sikidom = record
      X,Y: real ;
      Case S: Nev of
       Teglalap: (Magassag, Szelesseg: word) ;
       Negyzet:  (Oldal: byte) ;
       Kor:      (Sugar: real) ;
      End ;
A rekord olyan struktúrált típus, mely adott számú és típusú komponensbõl épül fel. Ezeket a komponenseket mezõnek nevezzü, s egy rekordon belül a mezõk különbözõ típusúak lehetnek, sõt egy rekordban több, különbözõ típus szokott szerepelni. - Állomány:
        Típusos       -->    File of alaptípus  Pl : File of 
                             Integer;
        (Komponensei egyforma méret&ucirc;ek, az alaptípus nem lehet 
         állomány ill. objektum típus)

  Assign : file változó hozzárendelése a fizikai file-hoz
  Reset, Rewrite: file megnyitása
  Close : lezárás 
  
        Típus nélküli -->   File   Tipikus         --> Pl : 
                                   BlockRead?/Write     

        Szöveges      -->   Text   Felhasználásuk  --> Pl : 
                                   Listafile
        (Csak szekvenciális elérés, soros szervezés)
    - Eljárás
        Procedure(formális paraméterlista)
        Function(formális paraméterlista): típusazonosító
        (paraméterlista elhagyható)
(Objektum) - Mutató típusok
    - Típusos:    4 byte-os memóriacímet tartalmaz
        Mut = ^alaptípus azonosítója
    - Típus nélküli:    4 byte-os memóriacímet tartalmaz
        Pointer
    (Mutatók felhasználása pl. Listaszerkezetnél)
 A C nyelv függvények halmaza. Maga a főprogram is „main()” egy függvény. A függvény az eljáráshoz hasonló, ugyanúgy kapja meg a vezérlést és a visszatérés módja is ugyanaz. A függvény, ahogy az eljárás is tetszőleges számban és mélységben hívhat meg újabb függvényeket. A függvények teljesen egyenrangúak, bármelyik meghívhatja bármelyiket, akár önmagát is (rekurzió), sőt akár a már említett main() függvényt (a főprogramot) is. A függvénynek tetszőleges számú bemenő paramétere lehet, de az eljárással ellentétben kell hogy legyen visszatérési értéke is.
Így néz ki egy függvény általánosságban:

Függvénynév(paraméterlista)
/* a paraméterek típusának megadása */
/* további függvények */
{
belső változók +
utasítások
return( visszatérési érték);
}

A paraméterek típusait egyszerű megadni, elég leírni a típust, és utána felsorolni az adott típusba tartozó paramétereket. Pl:

int a,b,c;

A belső változók megadása, formálisan ugyanúgy történik, mint a paraméterek meghatározásakor, azzal a különbséggel, hogy itt rögtön értéket is tudunk adni a változóinknak. Pl.:

int s=10,l=9;
float tort=0.99;
Konstansok
C-ben kétféle konstans van. Szöveges és numerikus. A numerikus lehet lebegőpontos, vagy egész, a szöveges lehet egy karakter, vagy string. A C a numerikus konstansokat több számrendszerben is tudja kezelni. Ha 0-val kezdjük, akkor az adott konstans oktális, ha 0x-el, akkor hexadecimális, egyébként pedig decimális. Pl.:

0711 Oktális
0xff hexadecimális
222 decimális
Konstansdeklaráció:
# define NULLA 0

A konstansneveket mindig nagybetűvel kell írni, és a sor végére nem kell pontosvesszőt tenni.
Ez esetben ha a programban bárhova beírjuk, hogy NULLA, a fordító indításkor karakterről karakterre bemásolja az adott névhez rendelt értéket, tehát a 0-t, utána kezd fordítani. Ezért a konstansok a tárban nem foglalnak helyet.

 Operátorok

A négy alapművelet: + - * /
% maradékképzés
++ növelés
-- csökkentés
E két utóbbi a változó előtt, és után is működik, mégsem ugyanaz.
b=a++; a értékét berakja b-be, majd növeli a-t
b=++a; növeli a-t, majd a növelt értékét berakja b-be.
a++;
++a; Ugyanaz


Típus konverziók

Struktúra (struct):
A struct egy olyan bizé, mint pascalban a record. A record pedig egy olyan bigyó, amelynek több mezője van. Például el akarjuk tárolni barátainkról, hogy mikor születtek (/fognak megpurcanni (vajon honnan tudjuk(:!)). Csinálunk egy olyan struktúrát, amelynek van egy olyan mezője, hogy név , meg egy olyan, hogy dátum(ev,honap,nap). pl.:
 
struct smyfriends
{
char nev[20];
int ev;
int honap;
int nap;
} myfriends[100]; //feltéve, hogy 100 baratunk van

--

Az SQL lekérdező nyelv alaptípusai, adatbázis és táblakezelési utasítások
Az SQL a strukturált lekérdező nyelv (Structured Query Language) rövidítése, melyet az IBM dolgozott ki a DB2 relációs adatbáziskezelőjéhez. Ma már a relációs adatbáziskezelők szabványosított nyelve, bár több dialektusa, bővítése alakult ki.
Az SQL szerepe, tulajdonságai
Az SQL egy szabványosított lekérdező nyelv, melyet több relációs adatbáziskezelő ismer, különböző operációs rendszeri környezetben. Ennek óriási jelentősége van az adatbázis alkalmazások fejlesztőinek körében, mert így az alkalmazások a különböző operációs rendszerek és adatbáziskezelők között módosítás nélkül vagy csekély módosítással átvihetők.
Az SQL nem algoritmikus nyelv, nem tartalmaz algoritmus szerkezeteket (elágazás, ciklus stb.). Az SQL halmaz orientált nyelv, mely a relációkon dolgozik. A halmaz orientáltság azt jelenti, hogy nem kell definiálni a művelet végrehajtásának lépéseit, hanem a feladat nem eljárás szerű megfogalmazását kell megadni, melyek a reláció vagy relációk kiválasztott sorain hajtódnak végre. A művelet végrehajtásához optimális megoldás megtalálása a nyelvi processzor feladata, nem a programozóé. Például annak eldöntése, hogy egy adott visszakeresésben alkalmazhatók-e indexek, vannak-e indexek vagy építsen-e fel új indexet, a nyelvi processzor feladata. Az SQL nem rekurzív nyelv.
Az SQL nyelvnek két felhasználási lehetősége van:
•    önálló SQL,
•    vagy 4. generációs nyelvbe beágyazott SQL
Az SQL nyelv önálló felhasználása esetén csak a nyelv utasításai állnak rendelkezésre. Ennek alkalmazására főként akkor kerülhet sor, ha nincs megfelelő alkalmazás az adott feladat elvégzésére, illetve az alkalmazások fejlesztői használják a negyedik generációs nyelvekbe építve. Ilyen eszközök a jelentés készítő, az űrlap készítő vagy menü készítő lehet.
A beágyazott SQL esetén egy negyedik generációs algoritmikus nyelvbe (C, PL/SQL, Pascal, FORTRAN, Visual FoxPro, stb.) ágyazva alkalmazzuk az SQL nyelv elemeit. Ebben az esetben az algoritmikus feladatokat a negyedik generációs nyelvre, az adatbázissal kapcsolatos műveleteket pedig az SQL-re bízhatjuk. A beágyazott SQL alkalmazását könyvünkben nem tárgyaljuk.
Az SQL a következő elemekre osztható
•    adatdefiníciós nyelv
•    adatmanipulációs nyelv
•    lekérdező nyelv (ezt a részt a 17-es tétel tárgyalja részletesen)
•    adatvezérlő nyelv
A parancsok ismertetésénél nagy betűvel írjuk az SQL parancsokon belüli fix szöveget, kisbetűvel pedig a felhasználó által megadható részeket. Szögletes zárójelbe tesszük a parancsok elhagyható részeit. A parancsok általános alakjába írt ... (három pont) az előző rész ismételhetőségére utal. A | (függőleges vonal) jelet az egymást kizáró paraméterek közé tesszük, ezek közül csak egy adható meg. A mintapéldákban az olvashatóság kedvéért általában több sorra bontottuk az SQL utasításokat, de azok egy sorban vagy másféle tördeléssel is leírhatók. A tárgyalás során nem csak a szabványos SQL parancsokat, hanem az ORACLE nyelvjárását ismertetjük, a teljesség igénye nélkül.
Az adatdefiniciós nyelv
Az adatdefiniciós nyelv segítségével hozhatjuk létre illetve szüntethetjük meg a relációkat, az indexeket illetve a nézet táblázatokat. A nézet táblázat az adatbázisban fizikailag nem létező relációs műveletek (szelekció, projekció, összekapcsolás, halmazműveletek) segítségével létrehozott táblázat, mely a relációkhoz hasonlóan kezelhető.
A relációk létrehozására a CREATE TABLE SQL utasítás szolgál, melynek általános alakja a következő:
CREATE TABLE reláció_név
(attribútum_név adattípus [(szélesség)] [CONSTRAINT megszorítás_név] [oszlop_megszorítás],
attribútum_név adattípus [(szélesség)] [CONSTRAINT megszorítás_név] [oszlop_megszorítás],
... ) [CONSTRAINT megszorítás_név] [tábla_megszorítás];
A szélesség megadása el is maradhat. A reláció név és általában a nevek megadására a következő szabályok érvényesek:
•    a névben csak az angol ABC betűi, a számjegyek és az _, #, $ karakterek szerepelhetnek
•    a névnek betűvel kell kezdődnie
•    a neveknek hatáskörükön belül egyedinek kell lennie (például nem lehet egy adatbázisban két azonos nevű reláció, egy relációban két azonos nevű attribútum, stb.)
A nevek hossza korlátozott, az Oracle-ben például 30. Az SQL az azonosítókban és a parancs szavakban általában nem tesz különbséget a kis és nagybetűk között.
Az attribútumokra megadható adattípusok köre adatbáziskezelőnként változhat, a következők a legtöbb relációs adatbáziskezelőben használhatók:
•    CHAR [(hossz)]
megadott maximális hosszúságú karakterlánc, csak a karakterláncnak megfelelő hosszúságú területet foglalja el, szinonimája a VARCHAR. Maximum 255 karakterig.
•    NUMBER [(szélesség, tizedes)]
valós szám megadása, a szélesség mellett a tizedespont utáni jegyek száma is megadható, hasonlóan használható a FLOAT
•    INTEGER
egész típusú érték megadása, hozzá hasonló, de számábrázolási tartományában eltérő típus még a SMALLINT, szinonimája a DECIMAL
•    DATE
dátum megadása
•    RAW
a karakterhez hasonló típus, de az adatok értelmezésére nincs semmilyen feltételezés, így segítségükkel tetszőleges bináris adatokat tárolhatunk, például ábrákat is. Maximális hossza 255.
•    LONG
Maximum 64 KByte hosszú szöveg. Relációnként csak egy ilyen lehet, és csak korlátozott helyeken használható
•    LONGRAW
Mint a RAW, de 64 KByte hosszú adat.
Az attribútum típusát megadva, a reláció azon oszlopába más típusú adat nem vihető be, erről az adatbáziskezelő gondoskodik illetve szükség esetén figyelmeztet. Az opcionális oszlop megszorítás a következőket tartalmazhatja.
•    NULL az attribútum definíciójában arra utal, hogy az adat megadása nem kötelző, ez az alapértelmezés ezért a legritkább esetben írják ki.
•    NOT NULL az attribútum definíciójában arra utal, hogy az adat megadása kötelező, azaz nem vihető be olyan sor a relációban, ahol az így definiált adat nincs kitöltve.
•    PRIMARY KEY ez az oszlop a tábla elsődleges kulcsa.
•    UNIQUE ez az oszlop a tábla kulcsa.
•    CHECK(feltétel) csak feltételt kielégítő értékek kerülhetnek be az oszlopba.
•    [FOREIGN KEY] REFERENCES tábla [ (oszlop) ], ez az oszlop külső kulcs.
A tábla megszorításban több oszlopra vonatkozó korlátozásokat adhatunk meg.
•    PRIMARY KEY(oszlop1[, oszlop2, ...]) ezek az oszlopok együtt alkotják az elsődleges kulcsot.
•    UNIQUE(oszlop1[, osylop2, ...]) ezek az oszlopok együtt kulcsot alkotnak.
•    CHECK(feltétel) csak feltételt kielégítő sorok kerülhetnek be a táblába.
•    FOREIGN KEY (oszlop1[, oszlop2, ...]) REFERENCES tábla(oszlop1[, oszlop2, ...]), az oszlopok külső kulcsot alkotnak a megadott tábla oszlopaihoz.
A megszorításokhoz nevet is rendelhetünk, mely hasznos lehet a megszorítás módosítása, törlése esetén (ALTER TABLE)
A minta adatbázisban található relációk létrehozása a következő utasításokkal történhet:
CREATE TABLE Diakok
(Diak_azonosito NUMERIC (4) PRIMARY KEY,
Nev CHAR (30) NOT NULL,
Cim CHAR (40) NOT NULL,
Telefon CHAR (15)
Osztaly CHAR (3) NOT NULL);
CREATE TABLE Tanarok
(Tanar_azonosito NUMERIC (4) PRIMARY KEY,
Nev CHAR (30) NOT NULL,
Cim CHAR (40) NOT NULL,
Telefon CHAR (15));
CREATE TABLE Orarend
(Tanar_azonosito NUMERIC (4) NOT NULL REFERENCES Tanarok(Tanar_azonosito),
Tantargy CHAR (20) NOT NULL,
Idopont NUMERIC (2), NOT NULL,
Osztaly CHAR (3) NOT NULL),
Terem NUMERIC (3) NOT NULL)
PRIMARY KEY(Tanar_azonosito, Idopont)
UNIQUE(Osztaly, Idopont);
CREATE TABLE Osztalyzatok
(Diak_azonosito NUMERIC (4) NOT NULL REFERENCES Diakok(Diak_azonosito),
Tantargy CHAR (20) NOT NULL,
Datum DATE NOT NULL,
Osztalyzat NUMERIC (1) VALID(BETWEEN 1 AND 5));
CREATE TABLE Hianyzasok
(Diak_azonosito NUMERIC (4) NOT NULL REFERENCES Diakok(Diak_azonosito),
Datumtol DATE NOT NULL,
Datumig DATE,
Igazolt CHAR (1))
PRIMARY KEY (Diak_azonosito, Datumtol);
A CREATE TABLE utasítással létrehozott táblázatok definícióját csak korlátozottan módosíthatjuk, újabb attribútumot adhatunk a relációhoz vagy egy attribútum szélességét megnövelhetjük. Egy attribútum szélességének csökkentésére illetve törlésére nincs közvetlen mód. Ez csak úgy érhető el, hogy a módosításoknak megfelelő üres relációt hozunk létre, amibe a szükséges adatokat átmásoljuk, majd az eredeti relációt töröljük. A reláció újabb attribútummal való bővítésére az alábbi parancs szolgál:
ALTER TABLE reláció_név
ADD attribútum_név adattipus [(szélesség)];
Az új attribútum a reláció utolsó oszlopa lesz. Ebben az esetben a NOT NULL módosító nem adható meg.
Az attribútum értéke a már meglevő sorokban NULL (definiálatlan) lesz. Az SQL nyelv megkülönbözteti a nulla numerikus értéket és a NULL, még nem definiált értéket. Például a diákok adatai közé a születési évet felvehetjük a következő paranccsal:
ALTER TABLE Diakok ADD szul_ev INT (4);
Egy reláció attribútumának szélességét meg lehet növelni az ALTER TABLE paranccsal.
ALTER TABLE reláció_név
MODIFY attribútum_név adattipus (új_szélesség) [NOT NULL];
Abban az esetben, ha az attribútum csak NULL értékeket tartalmaz, akkor lehetőség van az adattípus módosítására és a szélesség csökkentésére is. Például a név attribútum szélességének megnövelése a következő paranccsal történhet.
ALTER TABLE Diakok MODIFY nev CHAR (40) NOT NULL;
Teljes relációk törlésére is lehetőséget biztosít az SQL nyelv a DROP TABLE utasítással. Ezután a relációban tárolt valamennyi adat és a reláció definíciója is törlődik. A diákok személyi adatait tartalmazó reláció törlése a következő paranccsal lehetséges:
DROP TABLE reláció_név;
DROP TABLE Diakok;
A nézettáblázat az adatbázisban létező reláción vagy relációkon végrehajtott művelet eredményét tartalmazó olyan új táblázat, amely mögött a valóságban nem áll megfelelő táblázat. Nézettáblát a CREATE VIEW paranccsal hozhatunk létre.
CREATE VIEW nézettábla_név [alias_név, alias_név ...
AS lekérdezés;
A lekérdező utasítás formáit a lekérdező nyelv tárgyalása során részletezzük. A 3/b osztály névsorát tartalmazó nézettáblázatot hoz létre a következő parancs.
CREATE VIEW 3b AS SELECT * FROM Diakok WHERE osztaly = '3/b';
Akár több táblázatból is vehetünk oszlopokat a nézettáblába. A nézettábla segítségével a három relációra felbontott órarend relációt összevonhatjuk egy táblázatba a kényelmesebb kezelés érdekében.
CREATE VIEW orarend FROM tanr-to_id, tantargy-osztaly, ora
AS SELECT tanar_azonosito, tantargy, osztaly, idopont, terem
FROM Tanar-to_id A, Tantargy-osztaly B, Ora C
WHERE C.to_id = B.to_id AND C.to_id = A.to_id;
Az itt szereplő lekérdező (SELECT) utasítás két összekapcsolás műveletet is tartalmaz, melyeket csak később magyarázunk meg.
A nézettáblák megszüntetése a relációkhoz hasonlóan a DROP VIEW paranccsal lehetséges.
DROP VIEW nézettábla_név;
A relációkhoz indexeket is rendelhetünk, melyek helyes megválasztása esetén a lekérdezések felgyorsíthatók. Az indexek létrehozására a következő utasítás szolgál:
CREATE [UNIQUE] INDEX index_név ON reláció (attribútum, attribútum, ...);
Az index létrehozásánál a UNIQUE módosító megadásával a reláció valamennyi sorában különbözőnek kell lennie az index kulcsnak. Általában a reláció kulcsok esetén használható csak (index kulcs = reláció kulcs).
Hozzunk létre egy indexet a Diákok reláció Diák_azonosító attribútuma alapján:
CREATE UNIQUE INDEX Diak ON Diakok (Diak_azonosito);
A parancsban megadott UNIQUE következtében a reláció minden sorában különböző Diák_azonosítónak kell szerepelnie, illetve már létező érték bevitele hibát eredményez. Ez tulajdonképpen a célunk is, mert ez a reláció kulcs. Az index létrehozása után ugyanaz a Diák_azonosító nem vihető be mégegyszer, ilyen esetben hibaüzenetet kapunk.
Az indexek megszüntetése a DROP INDEX parancs segítségével történhet.
DROP INDEX index_név ON [reláció]
Ezen a két parancson kívül nincs szükség további az indexek kezelésére szolgáló parancsra. A relációkhoz kapcsolódó indexek használatáról az adatbáziskezelő optimalizáló algoritmusok alapján dönt. Az indexeket létrehozásuktól a megszüntetésükig az adatbáziskezelő automatikusan frissíti, a módosításoknak megfelelően. Figyelem, az indexek számának növelésével a relációkon végrehajtott módosítások, törlések végrehajtási ideje növekszik.
Az adatmanipuláiciós nyelv
Az SQL adatmanipulációs része biztosítja a relációk feltöltését, az attribútumok módosítását és a sorok törlését. A relációk feltöltésére az INSERT SQL parancs szolgál, melynek általános alakja a következő:
INSERT INTO reláció [(attribútum_név, attribútum_név, ...)]
VALUES (érték, érték, ...);
Egy utasítás segítségével egy sor adható meg az adott relációhoz. Az attribútum nevek megadása csak akkor kötelező, ha nem minden attribútumhoz rendelünk értéket, vagy az attribútumok értékét nem a definiálás sorrendjében adjuk meg. A NOT NULL megjelöléssel definiált attribútumok megadása kötelező az INSERT parancsnál, ellenkező esetben hibaüzenetet kapunk. Az attribútumok és a VALUES után álló értékek sorrendjének és típusának meg kell felelnie egymásnak. A definiálatlan értékekre a NULL érték is beállítható, mely numerikus értékekre sem azonos a nullával.
Adjunk egy új sort a Diákok relációhoz
INSERT INTO Diakok (Diak_azonosito, Nev, Cim, Osztaly)
VALUES (435, 'Nagy Istvan', 'Budapest O utca 3.', '3.b');
A telefon attribútum értékét nem adtuk meg, így értéke NULL. A reláció létrehozásánál NOT NULL jelzéssel ellátott attribútumokat kötelező minden újabb sor megadásánál kitölteni. Ellenkező esetben hibaüzenetet kapunk. De bevihetjük az előző adatokat az alábbi formában is:
INSERT INTO Diakok
VALUES (435, 'Nagy Istvan', 'Budapest Ó utca 3.', NULL, '3.b');
Az INSERT utasítás lehetőséget biztosít arra is, hogy a relációt egy másik relációból átvett értékekkel töltsük fel. Ekkor az értékek megadása helyén egy lekérdező utasítás állhat. A lekérdezés eredményei kerülnek be a megadott relációba, egyszerre akár több sor is. Itt is igaz, hogy a lekérdezés eredmény relációjának attribútumai sorrendjének és típusának meg kell felelnie a feltöltendő reláció definíciójának.
INSERT INTO reláció_név [(attribútum_név, attribútum_név, ...)]
lekérdező_utasítás;
A lekérdező utasítások formájával a következő alpontban foglalkozunk, de már itt is bemutatunk egy példát. Töltsük át a diákok adatai közül a 3/a osztályba járókét egy külön relációba:
INSERT INTO 3a
SELECT * FROM diakok WHERE osztaly = '3/a';
A 3a relációt természetesen először létre kell hozni a diákok relációval egyező szerkezettel, hogy a fenti parancs működjön. A diákok reláció tartalma nem változik.
A relációkban szereplő mezők tartalmát az UPDATE utasítással módosíthatjuk.
UPDATE reláció_név
SET attribútum_név = érték, attribútum_név = érték, ...
[WHERE feltétel];
Az UPDATE utasítás segítségével egyidőben a relációk több sorát is módosíthatjuk. A SET után adhatjuk meg a módosítandó attribútumot és értékeit. A WHERE után egy feltétel adható meg, az utasítás csak a reláció azon sorain dolgozik, melyekre a feltétel értéke igaz. A WHERE rész el is maradhat, ekkor a reláció összes sorára vonatkozik az UPDATE parancs. A feltételek alakjára részletesen a lekérdező nyelv ismertetésénél térünk ki, de a szokásos összehasonlító operátorok itt is használhatók. Például az Osztályzatok relációban az összes osztályzatot egyesre (vagy ötösre?) állíthatjuk egy UPDATE paranccsal:
UPDATE Osztalyzatok SET Osztalyzat = 1;
De a következő parancs már csak egy diák telefonszámát módosítja (mivel a feltétel csak egy adott kulcs érték esetén lehet igaz):
UPDATE diak SET telefon = '463-1234' WHERE diak_azonosito = 5;
Az egyenlőség jobb oldalán a reláció attribútumaiból álló kifejezés is állhat. Ilyenkor az aktuális sor tartalma alapján értékelődik ki a kifejezés. Az értékek módosítása esetén a feltételben egy lekérdező utasítás is szerepelhet, melynek segítségével egy másik relációból vett értékeket használhatunk.
UPDATE reláció
SET attribútum = (lekérdező utasítás)
[WHERE feltétel];
Ez a formája az UPDATE utasításnak lehetővé teszi, hogy egy másik reláció adataiból frissítsünk egy táblát. A WHERE utáni feltétel is tartalmazhat zárójelek közé tett lekérdező utasítást.
Az újabb SQL implementációk lehetővé teszik, hogy az UPDATE utasítás táblák közötti összekapcsolást is tartalmazzon, de továbbra is csak egy tábla tartalmát lehet aktualizálni egy UPDATE utasítással. Ez azonban még nem része az SQL szabványnak, így szintaktikája eltérő lehet az egyes adatbáziskezelőkben.
A relációk sorait törölhetjük a DELETE parancs segítségével.
DELETE FROM reláció_név
[WHERE feltétel];
A feltételben az UPDATE parancshoz hasonlóan egy zárójelek közé tett lekérdező utasítás is megadható. Töröljük ki a Diákok közül a 1234 azonosítójút.
DELETE FROM Diakok WHERE Diak_azonosito = 1234;
A kérdés csak az, hogy megtehetjük-e ezt az adatbázis konzisztenciájának elvesztése nélkül? Ha az Orarend vagy a Hianyzasok relációban szerepel a törölt diák azonosítója, akkor ezek inkonzistenssé teszik az adatbázisunkat. Helyesebb az alábbi három törlő parancsot kiadni, ha semmi szin alatt sem szeretnénk elveszteni az adatbázis konzisztenciáját.
DELETE FROM Hianyzasok WHERE Diak_azonosito = 1234;
DELETE FROM Osztalyzatok WHERE Diak_azonosito = 1234;
DELETE FROM Diakok WHERE Diak_azonosito = 1234;
A WHERE alparancs elmaradása esetén a reláció összes sora törlődik. Tételezzük fel, hogy az iskolából kicsapott diákok nevét egy kicsapottak relációban őrizzük a kics oszlopban. Ennek alapján a diákok relációból a következő paranccsal törölhetjük őket:
DELETE FROM Diakok WHERE nev IN (SELECT kics FROM kicsapottak);
A vezérlő nyelv
A SQL vezérlő nyelv több funkciót lát el, ezek közül most csak a tranzakciók, párhuzamos hozzáférés és a jogosultságok kezeléséhez szükséges parancsokat ismertetjük.
Tranzakciók:
A logikailag egybe tartozó SQL utasításokat tranzakcióknak nevezzük. Az adatbázis ellentmondás mentes tartalmának megőrzéséhez a tranzakcióknak maradéktalanul végre kell hajtódniuk. Azonban egy tranzakció megszakadása esetén is gondoskodni kell az adatbázis konzisztenciájának megőrzéséről. Erre a COMMIT és ROLLBACK parancs pár szolgál. Az ORACLE nem az eredeti relációkon dolgozik. A sikeresen végrehajtott tranzakciók után a COMMIT parancs kiadásával véglegesíthetjük a tranzakció során végrehajtott változtatásokat a relációkban. A ROLLBACK parancs segítségével pedig visszaléphetünk az előző véglegesített állapothoz. Bizonyos parancsok automatikusan COMMIT-ot eredményeznek (CREATE TABLE, QUIT stb.). De az AUTOCOMMIT rendszerváltozó beállításától függően minden parancs kiválthat egy COMMIT-ot is.
SET AUTOCOMMIT IMM | ON | OFF
Az IMM állapotban az ALTER, CREATE, DROP, GRANT, EXIT utasítások sikeres végrehajtása COMMIT-ot is jelent.
A rendszer hardver hiba utáni újraindulásakor, illetve hibás INSERT, UPDATE vagy DELETE parancs hatására automatikusan ROLLBACK-et hajt végre. Érdemes hát biztonságos helyeken COMMIT parancsot kiadni, nehogy egyhibásan kiadott parancs visszavonja a korábbi módosításokat.
Párhuzamos hozzáférés:
Az adatbázis több felhasználó egyidejűleg is használhatja. Ilyenkor az egye táblákhoz a párhuzamos hozzáférést külön-külön lehet szabályozni.
LOCK TABLE <táblanév>, …
IN [SHARE | SHARED UPDATE | EXCLUSIVE] MODE [NOWAIT];
A LOCK paranccsal egy felhasználó megadhatja, hogy az egye táblákhoz más felhasználóknak milyen egyidejű hozzáférést engedélyez. Az utasítás végrehajtásánál a rendszer ellenőrzi, hogy a LOCK utasításában igényelt felhasználási mód kompatíbilis-e a táblára érvényben lévő kizárással. Amennyiben megfelelő az utasítás visszatér és egyéb utasításokat lehet kiadni. Ha az igényelt kizárás nem engedélyezett, az utasítás várakozik, amíg az érvényes kizárást megszüntetik, ha csak a parancs nem tartalmazza a NOWAIT módosítót. Ebben az esetben a LOCK utasítás mindig azonnal visszatér, de visszaadhat hibajelzést is.
A táblához hozzáférést az első sikeres LOCK utasítás definiálja.
A SHARE módban megnyitott táblákat mások olvashatják, a SHARE UPDATE módban mások módosíthatják is, ilyenkor automatikusan kölcsönös kizárás teljesül egy-egy sorhoz hozzáférésnél. Az EXCLUSIVE mód kizárólagos hozzáférést biztosít.
Jogosultságok kezelése:
Az egyes felhasználók részint az adatbáziskezelő rendszerrel, részint az egyes objektumaival különböző műveleteket végezhetnek. Ezeknek a megadására szolgálnak a GRAN utasítások.
GRANT [DBA | CONNECT | RESOURCES]
TO <felhasználó>, …
IDENTIFIED BY <jelszó>, …;
A GRANT parancs az egyes felhasználók az adatbázishoz hozzáférésnek jogát szabályozzák. A DBA jogosultság az adatbázis adminisztrátorokak (DataBase Administrator) definiálja, akiknek korlátlan jogai vannak az összes adatbázis objektum felett, nem csak létrehozhatja, módosíthatja illetve törölheti, de befolyásolhatja az objektum tárolásával, hozzáférésével kapcsolatos paramétereket is. A RESOURCE jogosultsággal rendelkező felhasználók létrehozhatnak, módosíthatnak ill. törölhetnek új objektumokat, míg a CONNECT jogosultság csak az adatbáziskezelőbe belépésre jogosít
Az egyes objektumokhoz – táblák ill. nézetek – a hozzáférést a GRANT parancs határozza meg. A <jogosultság> az objektumon végezhető műveleteket adja meg.
GRANT < jogosultság >, …
ON < tábla vagy nézetnév>
TO <felhasználó>
[WITH GRANT OPTION];
A <jogosultság> lehetséges értékei:
ALL
SELECT
INSERT
UPDATE <oszlopnév> ,…
DELETE
ALTER
INDEX
Az utolsó két művelet nézetekre nem alkalmazható. A felhasználó neve helyet PUBLIC is megadható, amely bármelyik felhasználóra vonatkozik. A WITH GRAN OPTION-nal megkapott jogosultságokat a felhasználók tovább is adhatják.

Pascal és C eljárások, függvények. Érték és címszerinti paraméterátadás, lokális és globális változók, tárolási osztályok, láthatóság, élettartam, rekurzivitás.


- eljárás

Pascal   
Procedure eljárás neve(változó : típus);
Var lokális változók deklarálása;
Begin
     Lokális változók értékadása;
     Program…;
End;


C
void eljárás neve(típus változó)
{
     Lokális változók deklarálása és vagy értékadása
     Program…
 }


- függvény

Pascal   
Function függvény neve(változó : típus):Visszatérési típus;
Var lokális változók deklarálása;
Begin
     Lokális változók értékadása;
     Program…;
     Függvény neve := visszatérési érték;
End;


C
Visszatérési típus eljárás neve(típus változó)
{
     Lokális változók deklarálása és értékadása;
     Program…;
     Return visszatérési érték;
 }







- Érték szerinti paraméterátadás:

Pascal
Algoritmus típusa  Algoritmus neve(valtozo1 : típus)…;
Var valtozo : integer;
Begin
     ...;
     valtozo := 1;
     …;
End;

C
Visszatérési típus  Algoritmus neve(valtozo1 : típus)
{
     char valtozo;
     int i = 5;
     …;
     valtozo = ’A’;
     …;
}

- Cím szerinti paraméterátadás:

Pascal
Algoritmus típusa  Algoritmus neve(valtozo1 : típus)…;
Var valtozo2 : tipus;
Begin
     …
     parancs(valtozo);
     valtozo2 := valtozo1;
     …
End;

C
Visszatérési típus  Algoritmus neve(típus valtozo1)
{
     típus valtozo2;
     …;
     parancs(valtozo1);
     valtozo2 := valtozo1;
     …;
}








- Lokális és globális változók

Pascal program szerkezete

Program programnév;
Uses unit-ok;
Globális változók deklarálása;

Algoritmus típusa Algoritmus neve (…):…;
Var Lokális változók deklarálása;
Begin
     …
End;

Begin    (FŐPROGRAM)
     Var Lokális változók deklarálása;
     …
End.


C program szerkezete

#include <… . h>
Globális változók deklarálása

Visszatérési típus  Algoritmus neve(…)
{
     Lokális változók deklarálása;
     …;
}

Void main()    (FŐPROGRAM)
{
     Lokális változók deklarálása;
     …
}














- Láthatóság, élettartam

A globális változó láthatósága a teljes programra kiterjed, míg a lokális változó csak az adott algoritmuson belül látható. A globális változó élettartama a program végén fejeződik be, a lokális változó az eljárás befejeztével megszűnik.

Példa:

Program BalKarakter;
Uses Crt;
Var S_ : String;

Function LEFT(I_:Integer):String;
Var ret : String;
       i    : Integer;
Begin
  ret := '';
  If (I_ > 0) Then
    Begin
      If (I_ > Length(S_)) Then
        I_ := Length(S_);
      For i:=1 To I_ Do
        ret := ret + S_[i];
    End;
  LEFT := ret;
End;

Begin
   S_ := ”Globalis valtozo”;
   WriteLN(LEFT(3));
   ReadKey
End;


- tárolási osztályok

Register
A register kulcsszó megmondja, hogy egy változó a gép regiszterében tárolódjon-e.
Ezt csak akkor teszi meg, ha lehetséges, ha van hely a regiszterben a változó számára.
A fordító dönt róla, hogy odateszi-e vagy nem, ha nincs hely, ugyanúgy a memóriát fogja
helyette használni. Azért szoktuk megpróbálni általában ciklusoknál, mert gyorsíthatja
a kód futását.

Auto
Ez a tárolási osztály módosító megmondja a fordítónak, hogy a változó elesztheti a
láthatóságát akkor, ha az adott blokkot elhagyja. Ez lehet függvény, osztály, struktúra
vagy sima blokk a kódon belül. Általában ezt nem szoktuk kitenni, mivel minden változó
így jön létre c++ -ban.


Static
Ezt a változó módosítót akkor szoktuk használni, amikor azt akarjuk, hogy egy változó
egyszer jöjjön létre, ne veszítse el az értékét menet közben és minden példány számára
ugyanazt az értéket kéviselje. Itt a példa:

void Valami_Static_Function()
{
  static int x = 0;
  x++;
  cout << x <<endl;
}

Ezt ha 10 -szer meghívjuk akkor folyamatosan növekedő számsort kapunk,
Míg normál esetben mindig 1 -et kapnánk.

Extern
Ez módosító lehetővé teszi, hogy egy változót olyan állományokból is lássunk, ahol
nem deklaráltuk a változót és normál esetben nem lenne látható a másik állományból.
Akkor kap memóriaterületet a változó amikor a program kezdődik, és akkor törlődik,
amikor a program véget ér.

Volatile
Ez a kulcsszó lehetővé teszi, hogy a változót külső szálakból, operációs rendszerből,
hardware -ből vagy egy azonos időben futó szálból elérjük és értékét módososíthassuk.
Egyik használati területe például a megszakítás kezelés, amik aszinkron processzusok
és ezzel a módosítóval elérést biztosítunk ezek memóriaterületeire. Az értékük bármikor
megváltozhat, mert a rendszer mindig kiolvassa egy volatile objektum értékét amikor
utasítást kap rá, még akkor is, ha egy előző utasítás már kikérte az értékét.


- rekurzivitás
Rekurzivitás az, ha egy algoritmus önmagát hívja meg. Erre a legmegfelelőbb példa a faktoriális (TP):

Program faktorialis;

Function Fakt(Szam : integer) : integer;
Var ret : integer;
Begin
  Ret := Szam;
  If (Szam > 1) Then
    Ret := ret * Fakt(ret-1);
  Fakt := ret;
End;

Begin
  WriteLN(Fakt(5));
End.

Pascal filekezelés, fájlok szerkezete, megnyitása, irása olvasása
A programok a bemeneti adataikat nem csak a billentyûzetrõl, hanem a háttértárolókon lévõ állományokból is kaphatják, valamint kimeneti adataikat a képernyõn történõ megjelenítés mellett állományokban is tárolhatják. A Pascal nyelvben három összetett típus és az ezekhez kapcsolódó szabványos eljárások és függvények valósítják meg az állományok kezelését.
1.    Típusos állomány
2.    Text
3.    Típusnélküli állomány
9.1 Típusos állomány   
Deklarálása: FILE OF alaptípus
Összetett típus, fizikailag egy lemezes állomány. Egyforma méretû elemekbõl (komponensekbõl) áll. Az elemek számának csak a lemez mérete szab határt. A típusos állományból való olvasás illetve az állományba való írás egysége a komponens.Az elemekhez a rendszer sorszámot rendel 0-tól kezdõdõen. Az elérés szekvenciálisa (Read, Write) vagy a komponensek sorszáma szerint direkt módon történhet (az állomány mutató mozgatásával).
A program mindig egy logikai állományt kezel, melyet hozzá kell rendelnünk egy fizikai állományhoz (Assign), majd használat elõtt meg kell nyitnunk.
A Rewrite eljárás létrehozza, és megnyitja a logikai fájlhoz rendelt fizikai állomány. Ha a fizikai fájl már létezett, akkor törli annak tartalmát.
A Reset eljárással egy már létezõ állományt nyithatunk meg. Ekkor az állománymutató az 0. komponensre áll. (Ezért ezt az eljárást használhatjuk egy nyitott állomány elejére való ugrásra is.) Használat után a Close eljárással zárjuk le fájlunkat!
A típusos állományból a Read eljárás olvas be változókba adatokat. Ügyeljünk arra, hogy a változó típusa egyezzen meg a fájl alaptípusával! Beolvasás után az állomány mutató automatikusan a következõ komponensre lép (szekvenciális elérés).
Egy változó (vagy kifejezés) értékét a Write eljárással írhatjuk ki egy fájlba. Hasonlóan az olvasáshoz a változó típusának meg kell egyeznie a fájl elemeinek a típusával, valamint az eljárás után az állomány mutató továbblép.
Ha az állomány mutató a fájl végén (az utolsó elem mögött) áll, akkor az Eof függvény értéke True. Nézzünk egy példát a fájl szekvenciális feldolgozására:
Reset(f)
    while not Eof(f) do
    begin
    Read(f,v);
    {a v változóban lévõ adat feldolgozása}
end;
Az állomány mutató direkt pozicionálását a Seek eljárás valósítja meg.
A FilePos függvénnyel lekérdezhetjük az aktuális pozíciót, a FileSize függvény pedig az állomány elemeinek a számát (méretét) adja vissza.
Az I/O mûveletek során nagy a hibalehetõség (pl. a lemezegység, fájl nem elérhetõ). Az esetleges futási hibákat tudnunk kell kezelni, ha megbízhatóan mûködõ programot szeretnénk írni. Ha az I/O mûveletek ellenõrzése aktív (ez az alapértelmezés), akkor programunk futási hibával leáll egy I/O hiba esetén. Ezért I/O mûveletek ellenõrzését inaktívvá kell tennünk a {$I-} fordítási direktívával a kényes mûveletek esetén.
 A mûvelet után az esetleges hiba kódját az IOResult függvénnyel kérdezhetjük le. Erre egy példa:
Assign(f, 'adatok.dat');
{$I-}
Reset(f);        {megpróbáljuk megnyitni a fájlt}
{$I+}
if IOResult <> 0 then    {ha hiba történt, tehát a fájl nem létezik, }
Rewrite(f);        {akkor létrehozzuk az állományt}
A Truncate eljárással levághatjuk a fájl komponenseit az aktuális pozíciótól kezdõdõen.
Lezárt állományokra használhatjuk a Rename valamint az Erase eljárásokat a fájlok átnevezésére illetve törlésére.
9.2 Szöveges állomány - Text
Deklarálása: TEXT
A Pascal programban szöveges állományként kezelhetjük az egyszerû ASCII szövegeket. (Például a .pas kiterjesztésû forrásprogramjainkat.) A szöveges állomány változó hosszúságú sorokból áll, melyeket a sorvégjel zár le (CR/LF). Az állományt az állományvégjel zárja(^Z). Az Eoln illetve az Eof függvény értéke True, ha az aktuális pozíció egy sorvégjelen vagy az állomány végén áll. A SeekEoln illetve a SeekEof függvények az állomány következõ TAB szóköz illetve TAB szóköz és sorvégjel karaktereit átugorva tájékoztatnak arról, hogy sorvégjelen illetve az állomány végén állunk-e.
A szöveges állományt csak szekvenciálisan érhetjük el. Az állomány csak olvasásra vagy csak írásra lehet megnyitni.
Az állományból olvasni a Read, ReadLn, illetve írni a Write, Writeln eljárásokkal tudunk. Ha az eljárásoknak a fájl azonosító paraméterét elhagyjuk, akkor az olvasás / írás az alapértelmezett input / output szöveges állományból / -ba történik, ami a billentyûzet illetve a monitor. Szöveges állományból (azaz a billentyûzetrõl is) olvashatunk egész, valós, karakteres és sztring típusú változokba adatokat. Az állományba az elõbbi típusokon kívül még logikai értéket is kiírathatunk. Az fizikai állományhoz az Assign eljárással rendelhetünk egy Text típusú változót, azaz a logikai állományt. A Rewrite eljárás csak írásra nyitja meg a szöveges állományt, ha nem létezett létrehozza, egyébként törli a tartalmát. A Reset eljárással csak olvasásra nyithatunk meg egy már létezõ fájlt. Az Append eljárás egy létezõ állományt nyit meg írásra, és az állománymutató a fájl végére állítja. Az állományt a Close eljárással zárhatjuk be. Az I/O mûveletek hibakódját az IOResult függvény adja vissza (bõvebben ld. Típusos állományok). Lezárt állományokra használhatjuk a Rename valamint az Erase eljárásokat a fájlok átnevezésére illetve törlésére. A Fluss és a SetTextBuf eljárásokkal az írás, olvasás során a rendszer által használt átmeneti tárolóhoz (pufferhez) férhetünk hozzá.
9.3 Típusnélküli állomány
Deklarálása: FILE
Általában gyors adatmozgatás vagy ismeretlen állomány esetén használjuk. Hasonló a típusos állományhoz, de az elemeinek nem a típusa, hanem a hossza a lényeges. A komponensek hosszát a fájl megnyitásakor adhatjuk meg (Reset, Rewrite), az alapértelmezés 128 bájt. Az állomány írható, olvasható, az elérés szekvenciálisan (BlockRead, BlockWrite eljárásokkal) vagy az elemek sorszáma szerint direkt módon történhet.
Állomnykezelő függvények eljárások:
Assign(var f:file, DOSNÉV:string) Fájlazonosító hozzárendelése DOSNÉVhez


Pascal és C mutatók, Láncolt listák, bináris fa kezelési algoritmusok, láncolt listák struktúrákkal.

A mutató olyan speciális változó, mely más objektumok memóriacímét tartalmazza. Esetünkben helyfoglalása 4 bájt. Az első 2 bájt az offszet, a 2. két bájt a szegmens címet tárolja. Az objektum bármi lehet, úgy egy változó, mint egy függvény címe. Mindkét nyelv lehetőséget biztosít az úgynevezett dinamikus memóriakezelésre, melynek segítségével optimális tárfelhasználást valósíthatunk meg. A dinamikus memóriakezelés a mutatók használatára épül. A lényeg, hogy futási időben foglalhatunk memóriát, majd ha nincs többé szükségünk rá visszaadhatjuk azt az operációs rendszernek.

A Pascal mutatók:

A Pascal mutatót egyrészt a pointer típusnévvel, másrészt változónév: ^típus alakú típusleírás segítségével deklarálhatunk.

var
    barmiremutato: pointer;
    integerremutato: ^integer;
    realramutato: ^real;
    i: integer;
   
Az első esetben pointer típusú mutatót hoztunk létre, mely csak egy címet tartalmaz, bármire mutathat. Második esetben egy integer típusú változóra, harmadik esetben egy real típusú változóra mutathat. A deklarációt követően, ezek a mutatók még nem ismert címre mutatnak. A mutatók kezeléséhez használható standard eljárások a new, és a dispose. A mutatónak értékül adhatjuk egy objektum címét, az addr függvény, vagy a @ operátor használatával, illetve egyik mutatót ráállíthatjuk egy másik mutató által mutatott címre. Annak jelölésére, hogy egy mutató sehová nem mutat, a nil értéket használjuk. A mutatott objektumra, a változónév^ formában hivatkozhatunk.

begin
    new(integerremutato);{Helyfoglalás.}
    integerremutato^:=17;{A mutatott területre 17 kerül.}
    integerremutato^:=integerremutato^+13;{Hozzáadunk 13-at.}
    new(barmiremutato);{Helyfoglalás.}
    barmiremutato:=integerremutato;{Ugyanoda mutat.}
    writeln(integerremutato^); {30-at ír ki.}
    writeln(integer(barmiremutato^)); {30-at ír ki.}
    i:=5;{Értékadás.}
    barmiremutato:=@i;{Az i változó címét kapja értékül.}
    writeln(integer(barmiremutato^)); {5-öt ír ki.}
    dispose(integerremutato);{Ha már nem kell, felszabadítjuk.}
    dispose(barmiremutato);{Ha már nem kell, felszabadítjuk.}
    integerremutato:=nil;{Így majd tudom, hogy már felszabadítottam, nem mutat sehová.}
    barmiremutato:=nil;{Így majd tudom, hogy már felszabadítottam, nem mutat sehová.}
end.

A C mutatók:

Mivel a C nyelv a függvények hívásánál csak az érték szerinti paraméterátadást támogatja, C-ben gyakrabban használjuk a mutatókat, mint Pascal-ban. A C mutató definiálásakor, a mutató nevét a * írásjel előzi meg. Definiálhatunk void típusú mutatót, mely hasonlóan a Pascal pointer típusú mutatójához, bármire mutathat. A mutatók kezeléséhez használható standard függvények a malloc, calloc, realloc és a free. Mutatónak értéket adhatunk, a & címképző operátor használatával, illetve ráállíthatjuk más mutatóra. Annak jelölésére, hogy egy mutató sehová nem mutat, a NULL értéket használjuk. A mutatott objektumhoz való hozzáféréshez, a * operátort kell a mutató elé helyezni.

#include<alloc.h>
    void *barmiremutato;
    int  *intremutato;
    double *doubleremutato;
    int i=5;   
main(){
    intremutato=(int *)malloc(sizeof (int));/*Helyfoglalás.*/
    *intremutato=17;/*A mutatott területre 17 kerül.*/
    *intremutato+=13;/*Hozzáadunk 13-at.*/
    barmiremutato=(int *)malloc(sizeof (int));/*Helyfoglalás.*/
    barmiremutato=intremutato;/*A mutatott területre 17 kerül.*/
    printf("%d\n",*intremutato); /*30-at ír ki.*/
    printf("%d\n",*(int*)barmiremutato); /*30-at ír ki.*/
    barmiremutato=&i;/*Az i változó címét kapja értékül.*/
    printf("%d\n",*(int*)barmiremutato);/*5-öt ír ki.*/
    free(intremutato);/*Ha már nem kell, felszabadítjuk.*/
    free(barmiremutato);/*Ha már nem kell, felszabadítjuk.*/
    intremutato=NULL;/*Nem mutat sehová.*/
    barmiremutato=NULL;/*Nem mutat sehová.*/
}

Ha azt akarjuk, hogy egy a függvénynek átadott változón végzett módosítások a függvényből kilépve is megmaradjanak, akkor nem magát a változót, hanem annak címét adjuk át argumentumként.

#include<stdio.h>
/*Ez nem fog működni.*/
void nemmukodocsere(int p, int q){
    int temp=p;
    p=q;
    q=temp;
}
/*Ez a jó megoldás, mutatókkal dolgozunk.*/
void mukodocsere(int *p, int *q){
    int temp=*p;
    *p=*q;
    *q=temp;
}
main(){
    int x=7, y=30;
    printf(”A hívás előtt: x=%d y=%d\n”, x, y);/*x=7 y=30*/
    nemmukodocsere(x, y);
    printf(”A hívás után: x=%d y=%d\n”, x, y); /*x=7 y=30*/
    mukodocsere(&x, &y);
    printf(”A hívás után: x=%d y=%d\n”, x, y); /*x=30 y=7*/
}

A Láncolt listák:

A listastruktúra segítségével annyi memóriát használhatunk, amennyire éppen szükségünk van. A láncolt listát többféle módon megvalósíthatjuk. Készíthetünk végjeles, ciklikus, kétirányú, stb. listát. A lényeg az önhivatkozó struktúrán van. A megvalósítás dinamikus memóriahasználatot igényel. A legegyszerűbb esetben a lista csak egy irányba bejárható, és végjel jelzi a végét. Erre mutatok most példát Pascal és C nyelven. Persze konkrét esetekben szükség lehet még további algoritmusokra, elemek beszúrásához, törléséhez, a lista rendezéséhez. Ezek megvalósítására itt nem térek ki, aki ezt érti, érti a többit is.

type
      plist=^tlist;{Előre hivatkozás.}
    tlist=record{Az önhivatkozó struktúra Pascalban egy rekord.}
    adat: integer;{A hasznos adat.}
    kovetkezo: plist;{Mutató a lista következő elemére.}
    end;
var
    horgony: plist;{Mutató az első elemre. Lehetne pointer is, csak a cím a lényeg.}
    i: integer;{Általános változó.}
{Inicializálom a listát.}
procedure init;
begin
    new(horgony);{Helyfoglalás a horgonynak}
    horgony^.kovetkezo:=nil;{A lista végét nil jelzi.}
end;
{Felszabadítom a lista által foglalt területet.}
procedure takarit;
var temp: plist;
begin
    temp:=horgony;{Az elejére állok.}
    while temp^.kovetkezo<>nil do{Elmegyek a lista végére.}
    begin
        temp:=temp^.kovetkezo;{Ráálok a következőre.}
        dispose(horgony);{Felszabadítom az előzőt.}
        horgony:=temp;
    end;
    dispose(horgony);
    horgony:=nil;
end;
{A lista végére helyezi az elemet.}
procedure rafuz(elem: integer);
var temp: plist;
begin
        temp:=horgony; {Az elejére állok.}
        while temp^.kovetkezo<>nil do temp:=temp^.kovetkezo; {Elmegyek a lista végére.}
        new(temp^.kovetkezo);{Helyfoglalás a következő listaelemnek.}
    temp^.kovetkezo^.adat:=elem;{Beteszem a hasznos adatot.}
    temp^.kovetkezo^.kovetkezo:=nil;{A következő a vége.}
end;
{A lista feldolgozása.}
procedure feldolgoz;
var temp: plist;
begin
    temp:=horgony;{A lista elejére állok.}
    while temp^.kovetkezo<>nil do{Elmegyek a lista végére.}
    begin
        temp:=temp^.kovetkezo;{Ráálok a következőre.}
        writeln(temp^.adat);{Feldolgozom az adatot.}
    end;
end;
{A főprogram.}
begin
    init;{Inicializálom a listát.}
    for i:=1 to 100 do rafuz(i*2);{Felfűzök 100 elemet.}
    feldolgoz;{Feldolgozom.}
    takarit;{Eltakarítom.}
end.

Ha oda vissza be akarom járni a listát, teszek a rekordba még egy mutatót, mely az előző elem címére mutat.

tlist=record{Az önhivatkozó struktúra Pascalban egy rekord.}
adat: integer;{A hasznos adat.}
elozo, kovetkezo: plist;{Mutató a lista előző és következő elemére.}
end;

Ha az utolsó elem következő elemre mutató mezőjét nem nil-re állítom, hanem a horgonyra, a listám körbe ér, ciklikusan láncolt listát kapok. Ekkor persze változnak a listakezelő algoritmusok.

#include<stdio.h>
#include<alloc.h>
typedef struct tlist* plist;/*Előre hivatkozás.*/
typedef struct tlist{/*Így néz ki az önhivatkozó struktúra C-ben.*/
    int adat;/*A hasznos adat.*/
    plist kovetkezo;/*Mutató a lista következő elemére.*/
}tlist;
plist horgony;/*Mutató az első elemre. Lehetne void is, csak a cím a lényeg.*/
/*Inicializálom a listát.*/
void init(){
    horgony=(plist)malloc(sizeof(tlist));/*Helyfoglalás a horgonynak*/
     horgony->kovetkezo=NULL;/*A lista végét NULL jelzi.*/
}
/*Felszabadítom a lista által foglalt területet.*/
void takarit(){
    plist temp=horgony;/*Az elejére állok.*/
    while (temp->kovetkezo!=NULL){/*Elmegyek a lista végére.*/
        temp=temp->kovetkezo;/*Ráálok a következőre.*/
        free(horgony);/*Felszabadítom az előzőt.*/
        horgony=temp;
    }
    free(horgony);
    horgony=NULL;
}
/*A lista végére helyezi az elemet.*/
void rafuz(int elem){
    plist temp=horgony;/*Az elejére állok.*/
      while (temp->kovetkezo!=NULL) temp=temp->kovetkezo;/*Elmegyek a lista végére.*/
      temp->kovetkezo=(plist)malloc(sizeof(tlist));/*Helyfoglalás a következő listaelemnek.*/
    temp->kovetkezo->adat=elem;/*Beteszem a hasznos adatot.*/
    temp->kovetkezo->kovetkezo=NULL;/*A következő a vége.*/
}
/*A lista feldolgozása.*/
void feldolgoz(){
    plist temp=horgony;/*A lista elejére állok.*/
    while (temp->kovetkezo!=NULL){/*Elmegyek a lista végére.*/
        temp=temp->kovetkezo;/*Ráálok a következőre.*/
        printf("%d\n",temp->adat);/*Feldolgozom az adatot.*/
    }
}
/*A főprogram.*/
main(){
    int i;
    init();/*Inicializálom a listát.*/
    for (i=1;i<=10;i++) rafuz(i*2);/*Felfűzök 100 elemet.*/
    feldolgoz();/*Feldolgozom.*/
    takarit();/*Eltakarítom.*/
}

Sok alkalmazás megköveteli a lista rendezettségét. Ilyenkor választhatunk, hogy újabb elemek felvitelénél eleve a helyére tesszük az elemet, vagy külön rendezőalgoritmust írunk listánkhoz. A kereséseket jelentősen nem gyorsítja a rendezettség, mivel láncolt listára nem alkalmazható a bináris keresés, hiszen nem tudjuk közvetlenül megcímezni a középső elemet.

Bináris fa kezelési algoritmusok:

Azt a fát, amelyben minden csomópontnak legfeljebb két gyereke van, binárisfának nevezzük. A bináris fák kezeléséhez használt alapvető algoritmusok nem sokban különböznek a hagyományos listákban használtaktól, hiszen a bináris fa is csak egy speciális láncolt lista. Lényeges eltérés, a bejárásban van, mivel a szerkezet miatt egy elemről két irányba indulhatunk tovább. A bináris fa bejárásának nevezzük azt a folyamatot, amikor a fa minden elemét pontosan egyszer érintve feldolgozzuk. Lényegében három rekurzív módszert használunk a fa bejárásához. Az első módszerhez forráskódot is adok Pascalban, a másodikhoz C-ben. A harmadik algoritmust egyszerű implementálni az elméleti leírás alapján.

Preorder bejárás:
-gyökérelem feldolgozása
-bal részfa preorder bejárása
-jobb részfa preorder bejárása

{Pascalban ilyesmi lehet a kód.}
type
      plist=^tlist;
    tlist=record
    adat: integer;
    bal, jobb: plist;{Mutató a lista következő elemeire.}
    end;

{Rekurzív preorder bejárás.}
procedure preorder(p: plist);
begin
    if (p<>nil) then
     begin
          writeln(p^.szam);{Az adat feldolgozása.}
          preorder(p^.bal);{Végig a bal részfán.}
          preorder(p^.jobb);{Végig a jobb részfán.}
     end;
end;


Inorder bejárás:
-bal részfa inorder bejárása
-gyökérelem feldolgozása
-jobb részfa inorder bejárása

/*C-ben valahogy így nézhet ki.*/
typedef struct tlist* plist;
typedef struct tlist{
    int adat;
    plist bal, jobb;/*Mutató a lista következő elemeire.*/
}tlist;

/*Rekurzív inorder bejárás.*/
void inorder(plist p){
    if (p!=NULL){
        inorder(p->bal);{Végig a bal részfán.}
          printf(”%d\n”,p->szam);{Az adat feldolgozása.}
          inorder(p->jobb);{Végig a jobb részfán.}
     };
};


Postorder bejárás:
-bal részfa postorder bejárása
-jobb részfa postorder bejárása
-gyökérelem feldolgozása

A Java program alkotóelemei

Azonosítóban betűk, számjegyek, a _ jel és a valuta szimbólumok szerepelhetnek. Számjeggyel nem kezdődhet. Akár ékezetes betűt is tartalmazhat (unikód), de ezt inkább kerüljük.
Kulcsszó
Literál: állandó, amely beépül a program kódjába. Lehet: egész, valós, logikai (true, false), karakter (pl. ’?’), szöveg (pl. "valami"), null.
Vezérlő szekvenciák: \n, \t, \", \’, \\,
pl. println("Egy idézet: \”Talpra magyar!\””)

Java típusok

– Primitív típusok: (numerikus vagy logikai)
byte    1 b.    -128 .. 127
short    2 b.    -32768 .. 32767
int    4 b.    kb -2*109 .. 2*109
long    8 b.    kb. -1019 .. 1019
float    4 b.
double    8 b.
char    2 b.
boolean

– Referencia típus: olyan mutató, mely egy objektum hivatkozását tartalmazza.
Változó deklarálás: deklaráló utasítás, adható kezdőérték is (inicializálás).

Forrásprogram szerkezete

A forrásállomány (fordítási egység) egy vagy több osztályból állhat. A forrásállomány neve a main metódust tartalmazó, egyetlen publikus osztály neve lesz.
pl.

import java.utils.*;
import extra.*;

//Egy vagy több osztály deklarálása, a sorrend mindegy

class C1{
  ...
}

class C2{
  ...
}
...

public class Prog{
  ...
  public static void main(String[] args){
    ...
  }
  ...
}

Fordításkor több class kiterjesztésű állomány keletkezik.

Operátorok

Egy kifejezés operandusokból és operátorokból (műveletekből) áll.

Java operátorok:

– Unáris postfix és prefix operátorok
[ ]             tömbképző
.             minősítő
( )             metódus képző
~, !             ld. később
new             példányosító
(típus) kifejezés     típuskényszerítő
+, -              előjel
++, --        léptető, pl. i++ vagy ++i   mindkettő növeli i értékét, de az első értéke i eredeti, míg a második i megnövelt értéke lesz.

– Multiplikatív operátorok
*, /, %  Ha az operandusok egészek, akkor az eredmény is egész, ha legalább az egyik operandus valós, akkor az eredmény is valós.

– Additív operátorok
+, -

– Relációs operátorok
<, <=, >, >=,==, !=

– Logikai operátorok
!, &, |, &&, || (ez utóbbi kettő rövid kiértékelésű), ^

– Bitenkénti operátorok
~, &, |, ^, (illetve léptetések: <<,>>,>>>)

– Feltételes operátorok
(feltétel) ? kifejezés1: kifejezés2   pl. kamat = (fiz>200000)?10:0;

– Értékadó operátorok
=, +=, -=, *=, /=, %= …

Az összetett értékadás szintaktikája: változó operátor = kifejezés
szemantikája: változó = (típus) változó operátor kifejezés
ahol típus a változó típusa, amelyet rákényszerítünk a jobboldalra.

Vigyázzunk az összetett ill. a „hagyományos értékadó utasítások nem minden esetben teljesen egyformák!
Pl.
int a=10;
a+=5;  //megegyezik az a=a+5 ut.-al, mindkét oldal int
a+=1.5  // nem egyezik meg az a=a+1.5 ut.-al, mely szintaktikai hibás, a jobb oldal double

Lehetséges a többszörös értékadás: pl: a=b=5;


Egy kifejezés kiértékelési sorrendjét meghatározzák:
•    zárójel
•    prioritás
•    asszociativitás (balról – jobbra vagy jobbról – balra szabály)

Java utasítások

•    deklaráló; pl. int a;
•    értékadó; pl. a = b * 2;)
•    postfix és prefix növelő és csökkentő; pl. a++)
•    metódushívás; pl. System.out.println("Hahó!");
•    példányosítás pl. auto = new Auto("ABC123");
•    programvezérlő pl. elágazások, ciklusok
•    üres: ;

Minden utasítást pontosvessző zár le.
Blokk (vagy összetett utasítás): { ... }

Értékadó utasítás, típuskonverziók

változó = kifejezés;
A kifejezés típusának értékadás szerint kompatíbilisnek kell lenni a változó típusával:
•    azonos típusok
•    a jobb oldal szűkebb, akkor implicit bővítő konverzió
•    a bal oldal byte, short vagy char, a jobb oldal int, és a fordító el tudja dönteni, hogy a jobboldal belefér a baloldalba, akkor implicit szűkítő konverzió. pl. byte b = 100; (az egész literál automatikusan int típusú).
•    minden más esetben fordítási hiba keletkezik

pl.
    int i;
    double d;
    d = i;         //implicit bővítő konverzió
    i = d;         //szintaktikai hiba
    i = (int)d;     //explicit szűkítő konverzió
Metódushívás

Osztály.metódus(paraméterek)    pl. y=Math.sin(x);
Objektum.metódus(paraméterek)    pl. hossz=szoveg.length();

Saját osztályból elég csak a metódus neve: metódus(paraméterek)

Egy metódus lehet eljárás- vagy függvényszerű.

Túlterhelés (overloading): lehet több azonos nevű metódus, melyek a paraméterezésben és/vagy a visszatérési érték típusában térhetnek el egymástól.
Pl. float max(float a, float b)  illetve  int max(int a, int b)

Szelekciók

1. if utasítás

if(feltétel)
  utasítás1;
else
  utasítás2;

•    feltétel: logikai kifejezés
•    az else ág elhagyható
•    a feltétel után nincs pontosvessző
•    az utasítás esetén viszont van pontosvessző
•    minden feltétel zárójelben
•    egy ágban több utasítás: blokk {...}
•    egymásba ágyazás

Pl.
if(a>b)
  c=a;
else
  c=b;

2. switch utasítás

switch(kifejezés){
  case érték1:    utasítások;
            break;
  case érték2:    utasítások;
            break;
  ...
  default:        utasítások;
}

•    akkor alkalmazható, ha egy kifejezés jól meghatározott, különálló értékeire szeretnénk bizonyos utasításokat végrehajtani
•    kifejezés: byte, short, int vagy char
•    a break hatására a switch blokk végére kerül a vezérlés, e nélkül a következő case ágra kerülne a vezérlés
•    egy case kulcsszóhoz csak egy érték tartozhat

Pl:
switch(pont){
  case 1:
  case 2:
  case 3:    System.out.println("Elégtelen");
        System.out.println("Készüljön tovább!");
        break;
  case 4:    System.out.println("Elégséges");
        break;
  case 5:    System.out.println("Közepes");
        break;
  case 6:    System.out.println("Jó");
        break;
  default:    System.out.println("Jeles");
}

Iterációk

1. while utasítás

while(feltétel)
  utasítás;

Amíg a feltétel igaz, újból végrehajtja az utasítást, ha hamis, akkor a ciklust követő utasításra lép.
Több utasítás esetén: blokk { ... }

Példa: Bankba tesszük a pénzünket kamatozni, és addig tartjuk bent, amíg milliomosok nem leszünk. A program számolja ki, hogy hány évet kell várnunk.

import extra.*;
public class Milliomos1{
  public static void main(String[]args){
    final double KAMAT=8.5; //konstans
    int ev=0;
    int penz=Console.readInt("Mennyi penzt teszunk be a bankba: ");
    while(penz<1000000){
      penz*=1+KAMAT/100; //Ft-ra kerekít
      ev++;
    }
    System.out.println(ev+" ev mulva leszunk milliomosok!");
  }
}



2. do...while utasítás

do
  utasítás;
while(feltétel)

Amíg a feltétel igaz, újból végrehajtja az utasítást, ha hamis, akkor a ciklust követő utasításra lép.
Több utasítás esetén: blokk { ... }

Példa: Ugyanaz, mint a while ciklus esetén.

import extra.*;
public class Milliomos2{
  public static void main(String[]args){
    final double KAMAT=8.5; //konstans
    int ev=0;
    int penz=Console.readInt("Mennyi penzt teszunk be a bankba: ");
    do{
      penz*=1+KAMAT/100; //Ft-ra kerekít
      ev++;
    }while(penz<1000000);
    System.out.println(ev+" ev mulva leszunk milliomosok!");
  }
}

3. for utasítás

for(inicializálás; feltétel; léptetés)
  utasítás;

inicializálás: egy vagy több utasítás vesszővel elválasztva, mely(ek) egyszer hajtódik végre a ciklusmagba való első belépés előtt. Pl. ciklusváltozó deklarálása, inicializálása. A ciklusváltozó típusa tetszőleges.
feltétel: amíg igaz, újból végrehajtja az utasítást, ha hamis, akkor a ciklust követő utasításra lép.
léptetés: egy vagy több utasítás vesszővel elválasztva, mely(ek) a ciklusmag minden egyes lefutása után automatikusan végrehajtódik. Általában a ciklusváltozót szokás itt növelni vagy csökkenteni.

A while ciklus egy speciális esetének tekinthető:

inicializálás;
while(feltétel){
  utasítás;
  léptetés
}

Példák:
for(int i=1; i<=10; i++)
  System.out.print("*");

for(int i=1; i<=10; i++){
  for(int j=1; j<=10; j++)
    System.out.print("*");
  System.out.println();
}

for(char c='A'; c<='Z'; c++)
  System.out.print(c+" ");    //(c+’ ’) esetén a kódokat írja ki

for(char n='A',k='a'; n<='Z'; n++,k++)
  System.out.print(n+" "+k+" ");

for(double d=500000; d<=1000000; d*=1.1)
  System.out.println(d);



Kiugrás a ciklusból

Break utasítás: az aktuális utasításblokkból (pl. ciklusból) való azonnali kiugrást eredményezi.

Continue utasítás: hatására a vezérlés az utasításblokk (ciklus) végére kerül.

Tömbök, String osztály, Vector osztály a Javaban


Tömbök
A tömb referencia típusú változó, melyet deklarálnunk kell. Az elemtípus lehet akár primitív, akár referencia (osztály típusú vagy tömb típusú).
Deklarálás:

elemtípus [] tömbazonosító;
vagy
elemtípus tömbazonosító [];

pl:     int [] a;
    int b[];

Az így deklarált változó képes egy, a megadott elemtípusú tömbre mutatni. Még csak a referenciának (memóriacímnek) foglaltunk helyet, a tömböt külön létre kell hoznunk.

Létrehozás (futás közben):
new elemtípus [méret]

pl:     a = new int[10];
    b = new int[20];

Természetesen történhet rögtön a deklaráláskor is a létrehozás:
String[] sArray = new String[50];

Minden tömbnek van egy length konstansa.
Indexelés: 0 .. length-1

int[] iArray=new int[10];
for(int i=0; i<iArray.length; i++)
  iArray[i]=Console.readInt("Az "+(i+1)+". szam: ");
System.out.println("A tomb elemei visszafele: ");
for(int i=iArray.length-1; i>=0; i--)
  System.out.print(iArray[i]+" ");

Inicializáló blokk: deklaráláskor a tömb elemeinek kezdeti értékek adhatók, pl:
int[] iArray={2, 4, 6, 8, 10};
char[] szamjegyek={'0','1','2','3','4','5','6','7','8','9'}
Ekkor nem kell a tömböt a new operátorral létrehozni, a {} blokk képző operátor megteszi ezt helyettünk. A tömb mérete pontosan akkora lesz, amennyi a felsorolt értékek száma.

A t2 tömb értékadás szerint kompatibilis a t1 tömbbel (azaz t1=t2 megengedett), ha
•    primitív elemtípus esetén t1 és t2 elemtípusa azonos;
•    referencia elemtípus esetén t2 elemtípusa t1 elemtípusával azonos, vagy annak leszármazottja.
Értékadáskor a tömb referenciája kap értéket, nem pedig az elemei (a tömb nem másolódik, hanem átíródik a mutatója), így különböző hosszúságú tömbök és értékül adhatók egymásnak.

Kétdimenziós tömb:
Deklarálás:
elemtípus [][] tömbazonosító;

Teljes kétdimenziós tömb létrehozása:
new elemtípus [méret0] [méret1]
Pl: int[][] matrix = new int[3][4];

Lépésenkénti (soronkénti) létrehozás. A sorok különböző méretűek lehetnek:
Pl:     double[][] atlagok = new double[4][];
    atlagok[0] = new double[20];
    atlagok[1] = new double[18];
    atlagok[2] = new double[25];
    atlagok[3] = new double[22];

Analóg a helyzet a többdimenziós tömbök esetén.

Tömb paraméter.
Formális paraméterként egy tömbreferenciát kell deklarálnunk, amely fogadja az aktuális tömb referenciáját. Az aktuális tömbnek értékadás szerint kompatíbilisnek kell lennie a formális tömbbel.


Példa: Írjunk osztályt, amelynek adata egy int tömb. Az objektum létrehozásakor a konstruktor paraméterében adhassuk meg a tömb hosszát. Tartalmazzon egy bekér, kiir és egy osszeg nevű metódust!

import extra.*;
class Tomb{
  private int[]t;
 
  public Tomb(int hossz){
    t=new int[hossz];
  }
 
  public void beker(){
    for(int i=0;i<t.length;i++)
      t[i]=Console.readInt(i+1+". szam: ");
  }
 
  public void kiir(){
    for(int i=0;i<t.length;i++)
      System.out.print(t[i]+" ");
    System.out.println();
  }
 
  public int osszeg(){
    int s=0;
    for(int i=0;i<t.length;i++)
      s+=t[i];
    return s;
  }
}//Tomb




public class Tombok{
  public static void main(String[] args){
    Tomb t1=new Tomb(5);
    Tomb t2=new Tomb(7);
    System.out.println("Adja meg az elso tomb elemeit (5):");
    t1.beker();
    System.out.println("Adja meg a masodik tomb elemeit (7):");
    t2.beker();
    System.out.println("Az elso tomb:");
    t1.kiir();
    System.out.println("Az elemek osszege: "+ t1.osszeg());
    System.out.println("A masodik tomb:");
    t2.kiir();
  }
}

Konténerek
A konténer olyan objektum, amely objektumokat tárol, és alkalmas különböző karbantartási, keresési és bejárási funkciók megvalósítására. A java.util csomagban helyet foglaló kollekció keretrendszer egy általános konténereket tartalmazó osztálygyűjtemény. Általánosan jellemző rájuk: ha bármilyen objektumot beteszünk egy konténerbe, az „elveszti az osztálytudatát”.

Vector osztály
„Változtatható méretű tömb”, amely rendelkezik a fenti funkciókkal.
Mérete az elemek hozzáadásával automatikusan bővül.
Elemei indexelhetőek.
Elemei rendezetlenek (a Collections osztállyal lehet rendezni).

Néhány metódusa:
 void    add(int index, Object element)
          Inserts the specified element at the specified position in this Vector.
 boolean    add(Object o)
          Appends the specified element to the end of this Vector.
 void    clear()
          Removes all of the elements from this Vector.
 boolean    contains(Object elem)
          Tests if the specified object is a component in this vector.
 Object
get(int index)
          Returns the element at the specified position in this Vector.
 int    indexOf(Object elem)
          Searches for the first occurence of the given argument, testing for equality using the equals method.
 int    indexOf(Object elem, int index)
          Searches for the first occurence of the given argument, beginning the search at index, and testing for equality using the equals method.
 boolean    isEmpty()
          Tests if this vector has no components.
 Object
remove(int index)
          Removes the element at the specified position in this Vector.
 boolean    remove(Object o)
          Removes the first occurrence of the specified element in this Vector If the Vector does not contain the element, it is unchanged.
 Object
set(int index, Object element)
          Replaces the element at the specified position in this Vector with the specified element.
 int    size()
          Returns the number of components in this vector.
 String
toString()
          Returns a string representation of this Vector, containing the String representation of each element.

Példa:
import extra.*;
import java.util.*;

class Ember {
  private String nev;
  private int magassag;

  public Ember(String nev, int magassag) {
    this.nev = nev;
    this.magassag = magassag;
  }

  public Ember(String nev) {
    this(nev,0);
  }

  public String getNev() {
    return nev;
  }

  public int getMagassag() {
    return magassag;
  }

  public void setMagassag(int mag) {
    if (mag>0)
      magassag = mag;
  }

  public boolean equals(Object obj) {
    return nev.equals(((Ember)obj).getNev());
  }

  public String toString() {
    return Format.left(nev,10) + Format.right(magassag,3);
  }
}//Ember osztály vége


public class TorpeProgram {
  private Vector torpek = new Vector();

  // A torpék bevitele:
  void bevitel() {
    Ember torpe;
    String nev = Console.readLine("\nTorpe neve: ");
    while (!nev.equals("")) {
      if (torpek.contains(torpe = new Ember(nev)))
        System.out.println("Van mar ilyen torpe!");
      else {
        torpe.setMagassag(Console.readInt("magassaga : "));
        torpek.add(torpe);
      }
      nev = Console.readLine("Torpe neve: ");
    }
  }

  // Egyszerű lista, beépített módon:
  void lista1() {
    System.out.println("\nBeepitett lista:");
    System.out.println(torpek);
  }

  // torpek listázása index szerint, toString()-gel:
  void lista2() {
    System.out.println("\nLista index szerint:");
    for (int i=0; i<torpek.size(); i++) {
      System.out.println(torpek.get(i));
    }
  }

  // Listázás toString() nélkül:
  void lista3() {
    Ember e;
    System.out.println("\nEgyeni lista:");
    for (int i=0; i<torpek.size(); i++) {
      e = (Ember)(torpek.get(i));
      System.out.println("Nev: "+e.getNev()+
             "  Magassag: "+e.getMagassag());
    }
  }

  // Egy törpe megkeresése:
  void kereses() {
    System.out.println("\nKereses:");
    Ember keresettEmber = new Ember(
      Console.readLine("Torpe neve: "));
    int poz = torpek.indexOf(keresettEmber);
    if (poz >= 0)
      System.out.println("Van, magassaga:"+
        ((Ember)(torpek.get(poz))).getMagassag());
    else
      System.out.println("Nincs ilyen");
  }

  public static void main(String[] args) {
    TorpeProgram tp = new TorpeProgram();
    tp.bevitel();
    tp.lista1();
    tp.lista2();
    tp.lista3();
    tp.kereses();
  }
}


Megjegyzések:

1. A Vector osztály számos metódusa (pl. keresés a vektorban: indexOf) használja a benne lévő objektumok equals (egyenlő-e) metódusát az objektumok összehasonlítására. Ha a törpék vektorban név alapján akarok megkeresni egy törpét, akkor olyan equals metódust kell készítenem, mely a nevek azonosságát figyeli (van alapértelmezett equals metódus is, mely akkor ad igaz értéket, ha a két metódus azonos):

  public boolean equals(Object obj) {
    return nev.equals(((Ember)obj).getNev());
  }

A paraméter (obj) általános Object típusú, ezt Ember típusúvá kell konvertálnunk: (Ember)obj . (Kér sztring összehasonlítása a String osztály equals metódusával történik.)

A vektorban való kereséshez egy keresőobjektumot hozunk létre, mely csak a nevet tartalmazza (egyébként is csak azt ismerjük).

Ember keresettEmber = new Ember(Console.readLine("Torpe neve: "));
    int poz = torpek.indexOf(keresettEmber);


2. A vektorba betett, majd onnan kivett objektum elveszti az osztályát. Ha dolgozni szeretnénk vele, akkor vissza kell konvertálnunk a típusára (osztályára)

  e = (Ember)(torpek.get(i));//e már Ember típusú
  System.out.println("Nev: "+e.getNev() +"  Magassag: "+e.getMagassag());

vagy tömörebben:

    ((Ember)(torpek.get(poz))).getMagassag());


Az SQL select utasítása.

A lekérdező nyelv egyetlen utasításból áll, mely számos alparancsot tartalmazhat, és a lekérdező utasítások többszörös mélységben egymásba ágyazhatók A szelekció művelete és a SELECT utasítás csak nevében hasonló, egymásnak nem felelnek meg.
A projekció műveletét a következő utasítással valósíthatjuk meg:
SELECT [DISTINCT]
attribútum_név, attribútum_név, ... FROM reláció_név;
A megadott reláció felsorolt attribútumai jelennek meg az utasítás hatására soronként. A DISTINCT módosító megadása esetén csak az egymástól különböző sorok láthatók
Pl.: Diakok reláció Diak_azonosito és Nev attribútumainak lekérdezése:
 SELECT Diak_azonosito, nev FROM Diakok;
A különböző tanár-tantárgy párosítások lekérdezése az Orarend relációból a következő paranccsal történhet:
SELECT DISTINCT Tanar_azonosito, Tantagy FROM Orarend;
A szelekció művelet megvalósítása esetén a SELECT utasítást egy feltétellel egészítjük ki:
SELECT attribútum_név, attribútum_név, ... FROM reláció_név
WHERE feltétel;
Ha az attribútum nevek helyett csak "*"-ot adunk meg, akkor az eredményben a reláció valamennyi attribútuma szerepelni fog:
SELECT * FROM Diakok WHERE osztaly = '3/b';
Megadott attribútumok esetén a projekció és a szelekció művelete összevonható egy utasítással:
SELECT idopont, tantargy FROM orarend WHERE osztaly = '3/b';
Összehasonlító operátorok        Összehasonlító operátorok halmazokra
=    egyenlő        BETWEEN x AND y    adott értékek közé esik
!= <> ^=    nem egyenlő        IN (a, b, c, ...)    az értékek között található
>    nagyobb        LIKE minta    hasonlít a mintára
>=    nagyobb egyenlő           
"<"    kisebb           
"<="    kisebb egyenlő           
Az összehasonlító operátorok segítségével attribútumokat és konstansokat hasonlíthatunk össze. A szöveg és dátum konstansokat idézőjelek között kell megadni. Az alapértelmezés szerinti dátum formátum nap-hónap-év. A hónap a hónap nevének három betűs angol rövidítése, az év pedig évezred és évszázad nélkül értendő. Az SQL tartalmaz olyan összehasonlító operátorokat is, melyek nem egy adott értékkel, hanem az értékek egy halmazával történő összehasonlítást eredményeznek.
Az IN esetén egy halmazt adhatunk az elemek felsorolásával. A LIKE operátort karakteres mezők összehasonlítására alkalmazhatjuk. Két speciális karakter adható meg a mintában, a % jel tetszőleges hosszúságú karakter sorozatot helyettesít, az _ aláhúzás karakter pedig egy tetszőleges karaktert.
Szöveges minta megadása
Operátor    Értelmezés
LIKE 'a%'    minden 'a' betűvel kezdődő
LIKE 'x_'    minden 'x'-el kezdődő kétbetűs
LIKE '%a%'    minden 'a' betűt tartalmazó
LIKE '_a%x'    második betű 'a' és 'x'-re végződő
Az attribútumokra használható még egy speciális összehasonlító operátor, az IS NULL, melyek segítségével eldönthetjük, hogy a mező ki van-e töltve. Több keresési feltételt is összekapcsolhatunk a logikai operátorokkal, illetve segítségükkel a halmaz műveleteket valósíthatjuk meg.
Logikai operátorok
Operátor    Értelmezés
NOT    Logikai tagadás
AND    Logikai és
OR    Logikai vagy
Az összehasonlító operátorok precedenciája (végrehajtási sorrendje) csökkenő sorrendben:
1.    =, !=, <>, ^=, >, >=, <, <=
2.    NOT
3.    AND
4.    OR
Az SQL lehetőséget biztosít a lekérdezés eredménysorainak rendezésére az ORDER BY alparancs segítségével.
SELECT attribútum, attribútum, ... FROM reláció
[WHERE feltétel]
ORDER BY attribútum [ASC|DESC], attribútum
[ASC | DESC], ...;
Az ORDER BY után megadott attribútumok alapján ASC esetén (ez az alapértelmezés) növekvő, vagy DESC esetén csökkenő sorrendbe rendezi az eredmény sorait. Ha több attribútumot adunk meg a rendezési feltételben, akkor a megadás sorrendje alapján történik a rendezés, azaz először az elsőnek megadott attribútum alapján rendezi sorba a sorokat, ha ez az attribútum azonos két sorra, akkor a másodikként megadott attribútum alapján, és így tovább. Karakteres attribútumoknál a rendezés a karakterek kódjai alapján történik (ASCII vagy EBCD), azaz például nevek esetén az angol ABC szerint. Például a 3/a osztály órarendje időrendi sorrendben az alábbi lekérdezéssel kapható meg:
SELECT Idopont, Tantargy, Terem FROM Orarend WHERE Osztaly = '3/a'
ORDER BY Idopont;
A lekérdezés eredményét csoportosíthatjuk és a csoportok között is további szelekciót alkalmazhatunk a GROUP BY és HAVING alparancsokkal.
SELECT attribútumok FROM reláció
[WHERE feltétel]
GROUP BY attribútum
[HAVING csoport_feltétel];
A GROUP BY alparancs után megadott attribum azonos értékei alapján csoportosítja az SQL a lekérdezés eredményeit és a csoport feltételnek megfelelő sorok kerülnek az eredménybe. A csoportok képzésekor az eredmények között az azonos csoportba tartozó sorokból levezetett további eredmények megjelenítésére is lehetőséget biztosít az SQL. Ez a következő függvényekkel valósítható meg:
Függvények halmazokra és eredményeik
az alábbi adatok esetén: 1, 2, 3, 4, 1, 4, 4, NULL, 5
Függvény    Értelmezés    Eredmény
        ALL    DISTINCT
AVG (attribútum)    átlag    3    3
COUNT (attribútum)    nem NULL elemek száma    8    5
COUNT (*)    sorok száma NULL is    9    6
MAX (attribútum)    maximális elem    5    5
MIN (attribútum)    minimális elem    1    1
SUM (attribútum)    összeg    24    15
STDDEV(attribútum)    szórás        
A függvények argumentuma előtt megadható a DISTINCT vagy ALL módosító. DISTINCT esetén csak a különböző értékek, ALL esetén minden érték részt vesz a számításban. Az alapértelmezés az ALL. A definiálatlan, NULL értékek nem szerepelnek a számításban.
Pl: Az ötnél nagyobb létszámú osztályok:
SELECT Osztály, COUNT (*) FROM Diakok GROUP BY Osztaly
HAVING COUNT (*) > 5
Diákok tanulmányi átlaga matematikából:
SELECT Diak_azonosito, AVG (Osztalyzat) FROM Osztalyzatok WHERE tantargy = 'matematika' GROUP BY Diak_azonosito;
A lekérdezésekben az attribútumok és a csoportokra vonatkozó függvények mellett az attribútumok aritmetikai kifejezéseit is használhatjuk. A kifejezésekben az alapműveletek használhatók, illetve zárójelek a műveletek végrehajtási sorrendjének módosítására. A karakteres adatok konkatenálására a || operátor használható.
Osztályzatok kiírása fordítva, vagyis az egyes a legjobb:
SELECT Diak_azonosito, 6 - Osztályzat FROM Osztalyzatok;
A kifejezésekben az alapműveletek mellett számos függvényt is használhatunk a karakteres, numerikus és dátum tipusú adatokra.
Karakteres függvények
Függvény    Magyarázat    Példa
ASC (szöveg)    A szöveg első karakterének ASCII kódja    ASC ('abc') = 65
CHR (egész)    A számnak megfelelő kódú karakter    CHR (65) = 'a'
INITCAP (szöveg)    A szavak kezdőbetűit nagybetűvé    INITCAP ('ló pál') = 'Ló Pál'
INSTR (szöveg1, szöveg2, kezdet, hányadik)    A szöveg1-ben a szöveg2 hányadik előfordulása a kezdettől. Hányadik és kezdet elmaradhat    INSTR ('abcd', 'cd') = 3
LENGTH (szöveg)    A szöveg hosszát adja    LENGTH ('abc') = 3
LOWER (szöveg)    Kisbetűssé alakítja a szöveget    LOWER ('ABC') = 'abc'
LPAD (szöveg, hossz, karakterek)    A szöveget kiegészíti balról a megadott karakterekkel az adott hosszig, Karaktereket nem kötelező megadni, ekkor szóköz.    LPAD ('x', 3) = ' x'
LPAD ('x', 5, '12') = '1212x'
LTRIM (szöveg, karakterek)    A szöveg elejéről levágja a karakterekkel egyező részt. Karaktereket nem kötelező megadni, ekkor szóköz.    LTRIM (' x') = 'x
LTRIM 'KUKURIKU', 'UK' = 'RIKU'
RPAD (szöveg, hossz, karakter)    A szöveget kiegészíti jobbról a megadott karakterekkel az adott hosszig, Karaktereket nem kötelező megadni, ekkor szóköz    RPAD ('x', 3) = 'x '
RPAD ('x', 5, '12') = 'x1212'
RTIM (szöveg, karakter)    A szöveg végéről levágja a karakterekkel egyező részt. Karaktereket nem kötelező megadni, ekkor szóköz.    LTRIM ('x ') = 'x'
LTRIM ('KUKURIKU', 'UKI' = 'KUKUR'
SUBSTR (szöveg, kezdet, hossz)    A szöveg része a kezdet pozíciótól adott hosszban. Hossz nélkül a szöveg végéig    SUBSTR ('abcd', 2, 1) = 'b'
SUBSTR ('abcd', 3) = 'cd'
TRANSLATE (szöveg, mit, mire)    A szövegben előforduló mit karaktereket kicseréli a mire karaktereire    TRANSLATE ('abc', 'ab', 'AB') = 'ABc')
UPPER (szöveg)    Nagybetűssé alakítja a szöveget    UPPER ('abc') = 'ABC'
Nem minden függvény található meg minden adatbáziskezelőben, előfordulhat, hogy más névvel találja meg.

Numerikus függvények
Függvény    Magyarázat    Példa
ABS (érték)    Abszolút érték)    ABS (-1) = 1
CEIL (érték))    Az értéknél nagyobb vagy egyenlő legkisebb egész)    CEIL (6.12) = 7
FLOOR (érték))    Az értéknél kisebb vagy egyenlő legnagyobb egész)    FLOOR (3.95) = 3
MOD (érték, osztó))    Osztási maradék)    MOD (8, 3) = 2
POWER (érték, kitevő))    Hatványozás)    POWER (3, 4) = 81
ROUND (érték, pontosság))    Kerekítés a megadott jegyig. Negatív pontosság is megadható.)    ROUND (123.456, 1) = 123,5 ROUND (163.456,-2) = 200
SIGN (érték))    Előjel függvény)    SIGN (-3) = -1
SQRT (érték))    Négyzetgyök vonás)    SQRT (144) = 12
TRUNC (érték, pontosság))    Csonkítás a megadott jegyig. (Negatív pontosság is megadható.)    TRUNC (123.456, 1) = 123.4 TRUNC (163.456,-2) = 100
Nem minden függvény található meg minden adatbáziskezelőben, előfordulhat, hogy más névvel találja meg.
Dátum függvények
Függvény    Magyarázat    Példa
ADD_MONTH (dátum, n)    A dátumhoz n hónapot ad    ADD_MONTH ('10-MAY-93',2) = '10-JUL-93'
LAST_DAY (dátum)    A dátumban szereplő hónap utolsó apja    LAST_DAY ('1-JAN-93') = '31-JAN-93')
MONTH_BETWEEN (dátum1, dátum2)    A két dátum közötti idő hónapokban    MONTH_BETWEEN (
NEXT_DAY (dátum, nap)    A dátum utáni első nap nevű napra eső dátum    NEXT_DAY ('10-MAY-93','TUESDAY') = '11-MAY-93')
ROUND (dátum, formátum)    Dátum kerekítése a megadott formátum szerint   
TO_CHAR (dátum, formátum)    Dátum megadott karakteres formátumba konvertálása    TO_CHAR (4-DEC-58, 'YY.MM.DD') = '58.12.04'
TO_DATE (szöveg, formátum)    A szöveg dátummá alakítása a formátum szerint    TO_DATE ('58.12.04', 'YY.MM.DD') = 4-DEC-58
TRUNC (dátum, formátum)    Dátum csonkítása a megadott formátum szerint   
A SELECT utasítás a relációk közötti szorzás művelet végrehajtására is alkalmas. Ehhez több reláció nevét kell megadni a FROM után. Például az összes lehetséges diák és tanár azonosító pár visszaírása:
SELECT diak_azonosito, tanat_azonosito FROM Diakok, Tanarok;
Ennél komplikáltabb szorzás műveletet is megfogalmazhatunk. Például a 3/a osztályban rendezendő körmérkőzéses sakk bajnokság összes lehetséges párosításának előállítása:
SELECT A.nev, B.nev
FROM Diakok A, Diakok B WHERE A.osztaly = '3/a' AND B.osztaly = '3/a' AND
A.diak_azonosito <> B.diak_azonosito;
Az összekapcsolás segítségével még komplexebb kérdéseket oldhatunk meg egy lépésben.
SELECT [reláció.]attribútum, [reláció.]attribútum, ...
FROM relációk
WHERE kapcsoló_attribútum operátor
kapcsoló_attribútum;
Az összekapcsolás esetén mindig legalább két relációval dolgozunk. Ha a két relációban azonos az attribútumok neve, akkor minősített névvel, reláció.attribútum segítségével hivatkozhatunk a kivánt elemre.
A diákok neve mellé írjuk ki az osztály, tantárgy és osztályzat értéket:
SELECT Nev, Osztaly, Tantargy, Osztalyzat FROM Diakok, Osztalyzatok
WHERE Diakok.Diak_azonosito = Osztalyzatok.Diak_azonosito;
Az előző egy egyen összekapcsolás volt, de például a 12 azonosítójú diák osztályzatainál jobbat szerzők listája is előállítható az egy reláción végrehajtott összekapcsolással:
SELECT DISTINCT A.Diak_azonosito, A.Osztalyzat
FROM Osztalyzatok A, Osztalyzatok
WHERE B.Osztalyzat < A.Osztalyzat AND B.Diak_azonosito = 12;
Ebben a lekérdezésben az 'A' és 'B' ugyanannak a relációnak az alias nevei, melyek segítségével két sort vizsgálhatunk ugyanabból a relációból. Az előző lekérdezést módosítsuk úgy, hogy a diákok neve is megjelenjen:
SELECT Nev, A.Osztalyzat FROM Osztalyzatok A, Osztalyzatok B, Diakok
WHERE B.Osztalyzat < A.Osztalyzat AND B.Diak_azonosito = 12; AND
Diakok.Diak_azonosito = A.Diak_azonosito;
Az SQL szabvány egy másik megoldást is biztosít a belső összekapcsolásra az INNER JOIN kulcsszavakkal:
SELECT [reláció.]attribútum, [reláció.]attribútum, ...
FROM első_tábla INNER JOIN második tábla
ON első_tábla.kulcs_mező = második_tábla.kulcs_mező;
A korábbi példa, a diákok neve mellé írjuk ki az osztály, tantárgy és osztályzat értéket, így is megfogalmazható:
SELECT Nev, Osztaly, Tantargy, Osztalyzat FROM Diakok INNER JOIN Osztalyzatok
ON Diakok.Diak_azonosito = Osztalyzatok.Diak_azonosito;
A LEFT JOIN illetve RIGHT JOIN kulcsszavakkal az úgynevezett külső összekapcsolás is megvalósítható. Ebben az esetben az egyik tábla minden sora megjelenik az eredményben, akkor is, ha nincs az összekapcsolás feltételének megfelelő sor a másik táblában. A LEFT JOIN esetén az első tábla, míg a RIGHT JOIN esetén a második tábla minden sora bekerül az eredmény táblába. A külső összekapcsolás nem fogalmazható meg a WHERE feltételben.
SELECT [reláció.]attribútum, [reláció.]attribútum, ...
FROM első_tábla LEFT JOIN második tábla
ON első_tábla.kulcs_mező = második_tábla.kulcs_mező;
Az összekapcsolás művelete mellett a lekérdezések további egymásba ágyazása is lehetséges. A WHERE alparancsban az összehasonlítás egyik oldalán szerepelhet egy újabb, zárójelbe tett SELECT utasítás. A mélyebben elhelyezkedő SELECT utasítás több sort is visszaadhat a relációból. Ezeket az eseteket az ANY, ALL és EXISTS segítségével is kezelhetjük. Az ANY és ALL esetén az összehasonlítás egyik oldalára egy listát írhatunk, mely származhat egy beágyazott lekérdezésből is. A legrosszabb osztályzat matematikából:

SELECT DISTINCT Osztalyzat FROM Osztalyzatok
WHERE Tantargy = 'matematika' AND Osztalyzat <= ALL
(SELECT Osztalyzat FROM Osztalyzatok
WHERE Tantargy = 'matematika');
Az ANY és ALL használható a WHERE részben fix listákkal is, például x > ALL (12,21,8), x nagyobb, mint a lista legnagyobb eleme vagy y < ANY (5,4,7), y kisebb, mint a lista egyik eleme. Ezeket a feltételeket általában egyszerűbben is le tudjuk írni, az előző példák esetén x > 21 illetve y < 7. Az EXISTS esetén mindig egy újabb beágyazott lekérdezés következik. Ha egy beágyazott lekérdezés talál a feltételt kielégítő sort, akkor igaz értéket kapunk, különben hamisat. Például kinek nincs még osztályzata matematikából a 3/b-ben:
SELECT Nev FROM Diakok D WHERE NOT EXISTS
(SELECT * FROM Osztalyzatok
WHERE D.Diak_azonosito = Diak_azonosito AND
tantargy = 'matematika');
Az egyenlőség vizsgálat esetén a belső lekérdezés csak egy értéket adhat vissza. A relációkon értelmezett halmazműveletek bizonyos esetekben az OR, AND, NOT és IN operátorok segítségével is elvégezhetők. Az SQL ezek mellett az INTERSECT, UNION és MINUS műveleteket is biztosítja. Ezek segítségével két lekérdezést kapcsolhatunk össze a következő formában:
Halmaz muveletek megvalósítása az SQL-ben
Unió    Metszet    Különbség
SELECT ....
UNION
SELECT ...    SELECT ...
INTERSECT
SELECT ...    SELECT ...
MINUS
SELECT ...
Pl: Válasszuk ki azokat a termeket, ahol a 3/b-nek vagy a 3/a-nak vannak órái:
SELECT Tanterem FROM Orarend WHERE Osztaly = '3/b'
UNION
SELECT Tanterem FROM Orarend WHERE Osztaly = '3/a';






Nincsenek megjegyzések:

Megjegyzés küldése