2012. március 25., vasárnap

C ++ 004 Vezérlőszerkezetek

   A programunk utasítás-sorozatokból épül fel. Vannak összetettebb utasítások is, amiket utasításblokkokba foglalunk, ezeket a blokkokat a kapcsos nyitó-, és zárójel közé helyezzük: {utasítássorozatok}. Ezeket egymásba is ágyazhatjuk, mintegy szinteket létrehozva. A kapcsos záójeleket a függvénytörzseknél is, és az összetett típusok definíciójában is használjuk majd. Ezeknek a blokkoknak sajátossága, hogy "láthatóságuk" és hatókörük van, ami azt jelenti, hogy az utasításblokkokon belül definiált változókat csak azon blokkon belül használhatjuk és érhetjük el, amiben létrehoztuk, sőt, utasításblokkokon belül felül is írhatunk egy felsőbb szinten definiált változót, melynek élettartama saját blokkjának végéig létezik, majd a külső blokk
változóját fogjuk tudni csak elérni.
{
int szam;
<utasítások>
{
float szam;
string szoveg;
<utasítások>
// itt, ha bárhol hivatkozunk a szam változóra,
// az float típus lesz, és semmi köze az egész-
// ként definiált számhoz
}
<utasítások>
// Ha itt használjuk a szam változót, az már csak
// az egész típusú szám lehet, és a szoveg stringre
// nem hivatkozhatunk
}

Vezérlőszerkezetek

   A vezérlőszerkezetek elnevezés az elágazást (szelekció) és a ciklusokat (iteráció), illetve az ugróutasításokat foglalja össze. Az elágazással egy feltétel alapján eldönthetjük, hogy a programunk merre haladjon tovább, mit tegyen, ha az adott feltétel teljesül, azaz igaz, vagy ha nem teljesül, azaz hamis lesz. A ciklus pedig megkönnyati munkánkat azzal, hogy többször végrehajtandó művleteket, utasítássorozatokat rövid formába írjunk. Az ugróutasítások, vagy másnéven vezérlőátadó utasításokat részletezzük az alábbiakban. Minden vezérlőszerkezethez készítettem egy szemléltető folyamatábrát (flowchart).

Elágazás (Szelekció)

   Az elágazás lehet egyszerű elágazás (mikor csak egy feltétel alapján döntjük el, hogy hogyan lépjünk tovább), vagy összetett (mikor egy feltétel-kifejezés kimenetei alapján többféleképp folytathatjuk a programot).

Egyszerű elágazás (if)

Az egyszerű elágazások egyetlen feltételkifejezés alapján adják át a vezérlést valamely utasítássorozatok ágára. 
Formája a következő:

if ( <feltételkifejezés> )
{
  <utasítások>
}
   Ennél a formánál csak akkor hajtódik végre bármilyen változás a programban, ha a feltételünk igaz lesz, egyébként tovább folytatódik a program. Emlékezzünk, hogy az igaz érték valójában azt jelenti a c++-ban, hogy a kifejezés értéke nem 0. Így pl. ha egy aritmetikai kifejezést teszünk meg feltételnek, akkor ha 0-át kapunk, akkor az if-blokkban szereplő utasítás nem hajtódik végre.
if-else (ha-egyébként) pár:
if ( <feltételkifejezés> )
{
<utasítások1>
}
else
{
<utasítások2>
}
   Ha a feltételünk igaz, végrehajtódik az utasítások1 sorozata, ha hamis, akkor az utasítások2 sorozata hajtódik végre. Ezzel a feltételkifejezés minden lehetséges kimenetelét lefedjük.

   Természetesen ezek az utasítások is egymásba ágyazhatók, pl. előfordulhat, hogy egy feltételt többféle szempontból is vizsgálunk, ekkor beékelhetünk újabb if-eket, vagy if-else párokat:
if  ( x > 5 )
{
// utasítások, ha x>5
if  ( x > 7 )
      {
// Ide jönnek azok az utasítások, mikor
// x nem csak 5-nél, de hétnél is
// nagyobb
      }
}
else
{
  // ha x<=5-nél, akkor mi történjen
if ( x < -5 )
{
// Végrehajtódnak a -5-nél is kisebb
// x-re vonatkozó utasítások
}
}
   Az if-es elágazások egyik legjobban használható formája az else-if szerkezet: itt egyfajta kizáró feltételeket fogalmazunk meg,azaz olyan esetekben használható, mikor egy feltétel alapján sok különböző esetet vizsgálunk, ám azok mind elkülönülnek egymástól:
if ( x == 5 )
{
// utasítások, ha x értéke 5
}
else if ( x == 7 )
{
// utasítások, ha x értéke 7
}
else if ( x == -5 )
{
// utasítások, ha x értéke -5
}
else
{
// utasítsok minden más esetben,
// tehát, ha x nem 5, nem 7 és nem is -5
    Az utolsó else ágat (ami egyfajta alapértelmezés, azaz default) elhagyhatjuk, ha nem kívánjuk lefedni az összes esetet, itt pl, ha x értéke csak akkor jelentős a program futásában, mikor 5, 7, -5 lesz.

Többszörös elágazás ( switch )

   Kulcsszavai a switch (kapcsoló), case (eset-címke), opcionálisan a default (alapeset-címke) és az egyik legfontosabb a break (törés,szünet).
Formája:

switch <kifejezés> )
{
case konstans1 :
<utasítások1>
case konstans2 :
<utasítások2>
case konstans3 :
<utasítások3>
...
default :
<utasításokn>
}
   A switch után álló kifejezés konstans értékeiből sorolhatunk fel a case címkék után, s a megfelelő konstansértékhez tartozó utasítást hajtjuk végre. A program az összes eseten végigmegy, tehát, ha konstans1 teljesül, végrehajtódik az utasítások1, majd tovább vizsgálja a címkéket, és ha konstans3 is teljesül, akkor az utasítások3 is végrehajtódnik. Ha ezt nem szeretnénk, hogy tovább vizsgálja a switch a lehetőségeket, akkor egy break kulcsszót illesztünk az adott case végére. 

Például.:
enum edesseg cukorka, rago, sutemeny, csokolade };
switch ( edesseg )
{
case cukorka:
szopogat();     // fgv
break;
case rago:
ragozik();
break;
default:
eszik();
}
   Megeshet, hogy valaki egyszerre eszik cukorkát és rágózik is, de semmiképp nem eszik csokit és süteményt is mellé, ekkor a break-et elég egy pontra kitenni:
switch ( edesseg )
{
case cukorka:
szopogat(); // fgv
case rago:
ragozik();
break;
default:
eszik();
}

Ciklusok (Iterációk)

   A ciklusok vagy iterációk egy művelet, vagy utasítás-sorozat többszöri, általában adott számszori végrehajtását teszik lehetővé egymás után. Az ismételni kívánt utasítások az úgynevezett ciklusmagban hajtódnak végre, és a ciklusból valamilyen feltétel, illetve egy kifejezés igaz vagy hamis volta alapján lépünk ki. A ciklusból való kilépést egy változó növelésével vagy csökkentésével érjük el, amíg az a ciklusfeltételben lévő kifejezéssel meg nem egyezik. Ezt a változót a ciklusváltozó névvel illetjük. Több típusuk van: az elöltelsztelős, számlálós, hátulteltesztelős. Az elöltesztelős és számlálós ciklusok könnyen át is írhatók egymásba.

Előltesztelős ciklus (while ciklus)

   Az előltesztelős ciklus a nevében is hordozza, hogy még a ciklusba, ciklusmagba való belépés előtt ellenőrizzük a ciklusfeltételt. Így, ha az hamis, be sem lépünk a ciklusmagba. Amíg a ciklusfeltétel igaz, addig a ciklusmag újra és újra végrehajtódik. Fontos, hogy ennél a ciklusfajtánál a ciklusváltozót mi magunk kell, hogy inícializáljuk, ellássuk egy kezdőértékkel a ciklus előtt, valamint, hogy a ciklusmag belsejében növeljük vagy csökkentsük.
Formája:

ciklusváltozó = kezdőérték;
while ( <feltételkifejezés> )
{
<utasítások> // ciklusváltozó növelésével/csökkentésével, azaz egy léptetőkifejezéssel
}

Számlálós ciklus (for ciklus)

   A számlálós ciklus az előltesztelős egy speciális formája, melyben pontosan tudjuk a ciklusmag végrahajtási számát. Ilyenkor a for kulcsszó megadása után egy zárójelben felsorolva adjuk meg a ciklusváltozó inícializálását, a feltételt és a ciklusváltozó növelésének/csökkentésének mértékét.
Formája:

for ( <inícializálókifejezés>; <feltételkifejezés>; <léptetőkifejezés> )
{
<utasítások>
}

A folyamatábra számlálós ciklus szimbólumával egyszerűbben:

Hátultesztelős ciklus (do-while ciklus)

A hátultesztelős ciklus olyan ciklus, mely a ciklusmag végrehajtása után ellenőrzi csak a kilépő feltételt, így a ciklusba belépve a mag legalább egyszer biztosan végrehajtódik.
Formája:
do
{
<utasítások>
}
while ( <feltételkifejezés> )

Ugró utasítások

A programunkba (ciklusokba is) becsempésztethetünk ugró utasításokat is, melyeknek vezérlésátadó szerepük van. Ugyanezt tettük a switch utasításnál is, mikor a break kulcsszóval megakadályoztuk, hogy újabb címkét vizsgáljon a fordító. A break (szünet, vagy törés) utasítás a saját blokkjában leállítja a további utasítások végrehajtását.
A continue (folytatás) utasítás ciklusmagban való elhelyezésével pl. egy ciklusra erőltethetjük annak továbbfutását egy adott ponttól, ez azt fogja eredményezni, hogy a ciklusmag további részeit átugorva a ciklus újabb futtatása következik. Ezt legtöbbször vmilyen feltétel alapján tesszük, és csak igen indokolt esetben.
Végül, van nekünk egy goto utasításunk is, melyet azonban ajánlatos elkerülni, mert gyakori használata áttekinthetetlen kódot eredményezhet. A goto utasítást címkékkel együtt használjuk. A címke szintaxisa igen egyszerű, egy név és utána kettőspont, a vezérlés a címke utáni utasításokra fog kerülni. Az alábbi módon, ha van egy x változónk, melynek értéke az <utasítások1> hatására 5 lesz, akkor kihagyjuk az <utasítások2>-t, és csak az <utasítások3> hajtódik végre.
A goto formája:
<utasítások1>
if (x==5)
     goto cimke1;
}
<utasítások2>
cimke1:
<utasítások3>

Nincsenek megjegyzések:

Megjegyzés küldése