• Nem Talált Eredményt

Szelekciós utasítások

4. Vezérlő utasítások

4.2. Szelekciós utasítások

}

4.2. Szelekciós utasítások

A szelekciós utasításokkal (if, switch) feltételtől függően jelölhetjük ki a program további futásának lépéseit.

Megvalósíthatunk leágazást, kettéágaztatást vagy többirányú elágaztatást. A szelekciókat egymásba is ágyazhatjuk. A feltételek megfogalmazásakor a már megismert összehasonlító (relációs) és logikai műveleteket használjuk.

4.2.1. Az if utasítás

Az if utasítás segítségével valamely tevékenység (utasítás) végrehajtását egy kifejezés (feltétel) értékétől tehetjük függővé. Az if utasítás három formában szerepelhet a programunkban

Leágazás

Az if alábbi formájában az utasítás csak akkor hajtódik végre, ha a feltétel értéke nem nulla (igaz, true).

(Felhívjuk a figyelmet arra, hogy a feltételt mindig kerek zárójelek között kell megadni.) if (feltétel)

utasítás

Blokk-diagram segítségével a különböző vezérlési szerkezetek működése grafikus formában ábrázolható. Az egyszerű if utasítás feldolgozását akövetkező ábrán(I.7. ábra - Az egyszerű if utasítás működése) követhetjük nyomon.

I.7. ábra - Az egyszerű if utasítás működése

A következő példában csak akkor számítjuk ki a beolvasott szám négyzetgyökét, ha az nem negatív:

#include <iostream>

#include <cmath>

using namespace std;

int main() { double x = 0;

cout << "x = "; cin >> x;

if (x >= 0) {

cout<<sqrt(x)<<endl;

} }

Kétirányú elágazás

Az if utasítás teljes formájában arra az esetre is megadhatunk egy tevékenységet (utasítás2), amikor a feltétel kifejezés értéke nulla (hamis, false) (I.8. ábra - Az if-else szerkezet logikai vázlata). (Ha az utasítás1 és az utasítás2 nem összetett utasítások, akkor pontosvesszővel kell őket lezárni.)

if (feltétel) utasítás1

else

utasítás2

I.8. ábra - Az if-else szerkezet logikai vázlata

Az alábbi példában a beolvasott egész számról if utasítás segítségével döntjük el, hogy páros vagy páratlan:

#include <iostream>

using namespace std;

int main() {

int n;

cout<<"Kerek egy egesz szamot: "; cin>>n;

if (n % 2 == 0)

cout<<"A szam paros!"<<endl;

else

cout<<"A szam paratlan!"<<endl;

}

Az if utasítások egymásba is ágyazhatók. Ilyenkor azonban körültekintően kell eljárnunk az else ág(ak) használatával. A fordító mindig a legközelebbi, megelőző if utasításhoz kapcsolja az else ágat.

Az alábbi példában egy megadott egész számról megmondjuk, hogy az pozitív páratlan szám-e, vagy nem pozitív szám. A helyes megoldáshoz kétféleképpen is eljuthatunk. Az egyik lehetőség, ha a belső if utasításhoz egy üres utasítást (;) tartalmazó else-ágat kapcsolunk:

if (n > 0)

if (n % 2 == 1)

cout<<"Pozitiv paratlan szam."<< endl;

else;

else

cout<<"Nem pozitiv szam."<<endl;

A másik járható út, ha a belső if utasítást kapcsos zárójelek közé, azaz utasításblokkba helyezzük:

if (n > 0) {

if (n % 2 == 1)

cout<<"Pozitiv paratlan szam."<< endl;

} else

cout<<"Nem pozitiv szam."<<endl;

A probléma fel sem vetődik, ha eleve utasításblokkokat használunk minkét if esetén, ahogy azt a biztonságos programozás megkívánja:

if (n > 0) {

if (n % 2 == 1) {

cout<<"Pozitiv paratlan szam."<< endl;

} } else {

cout<<"Nem pozitiv szam."<<endl;

}

Ebben az esetben bármelyik ág biztonságosan bővíthető újabb utasításokkal.

I.9. ábra - A többirányú elágazás logikai vázlata

Többirányú elágazás

Az egymásba ágyazott if utasítások gyakori formája, amikor az else-ágakban szerepelnek az újabb if utasítások (I.9. ábra - A többirányú elágazás logikai vázlata).

Ezzel a szerkezettel a programunk többirányú elágaztatását valósíthatjuk meg. Ha bármelyik feltétel igaz, akkor a hozzá kapcsolódó utasítás hajtódik végre. Amennyiben egyik feltétel sem teljesül, a program végrehajtása az utolsó else utasítással folytatódik.

if (feltétel1)

utasítás1 else if (feltétel2)

utasítás2 else if (feltétel3) utasítás3 else

utasítás4

Az alábbi példában az n számról eldöntjük, hogy az negatív, 0 vagy pozitív:

if (n > 0)

cout<<"Pozitiv szam"<<endl;

else if (n==0) cout<<"0"<<endl;

else

cout<<"Negativ szam"<<endl;

Az else-if szerkezet speciális esete, amikor feltételek egyenlőség-vizsgálatokat (==) tartalmaznak. A következő példában egyszerű összeget és különbséget számoló kalkulátort valósítunk meg:

#include <iostream>

cout <<a<<op<<b<<'='<<c<<endl;

return 0;

}

Az utolsó példában a szerzett pontszámok alapján leosztályozzuk a hallgatókat С++ programozásból:

#include <iostream>

A switch utasítás valójában egy utasításblokk, amelybe a megadott egész kifejezés értékétől függően különböző helyen léphetünk be. A belépési pontokat az ún. esetcímkék (casekonstans kifejezés) jelölik ki.

switch (kifejezés)

{

case konstans_kifejezés1 : utasítások1 case konstans_kifejezés2 : utasítások2 case konstans_kifejezés3 : utasítások3

default :

utasítások4 }

A switch utasítás először kiértékeli a kifejezést, majd átadja a vezérlést arra a case (eset) címkére, amelyben a konstans_kifejezés értéke megegyezik a kiértékelt kifejezés értékével. Ezt követően a belépési ponttól az összes utasítás végrehajtódik, egészen a blokk végéig. Amennyiben egyik case konstans sem egyezik meg a kifejezés értékével, a program futása a default címkével megjelölt utasítástól folytatódik. Ha nem adtuk meg a default címkét, akkor a vezérlés a switch utasítás blokkját záró kapcsos zárójel utáni utasításra kerül.

Ezt a kissé furcsa működést egy rendhagyó példaprogrammal szemléltetjük. Az alábbi switch utasítás képes meghatározni 0 és 5 közé eső egészszámok faktoriálisát. (A rendhagyó jelző esetünkben azt jelenti, hogy nem követendő.)

int n = 4, f(1);

switch (n) {

case 5: f *= 5;

case 4: f *= 4;

case 3: f *= 3;

case 2: f *= 2;

case 1: f *= 1;

case 0: f *= 1;

}

A switch utasítást az esetek többségében - az else-if szerkezethez hasonlóan - többirányú programelágazás megvalósítására használjuk. Ehhez azonban minden esethez tartozó utasítássorozatot valamilyen ugró utasítással (break, goto vagy return) kell lezárnunk. A break a switch blokkot közvetlenül követő utasításra, a goto a függvényen belül címkével megjelölt utasításra adja a vezérlést, míg a return kilép a függvényből.

Mivel célunk áttekinthető szerkezetű, jól működő programok készítése, az ugró utasítások használatát a programban minimálisra kell csökkenteni. Ennek ellenére a break alkalmazása a switch utasításokban teljes mértékben megengedett. Általában a default címke utáni utasításokat is break-kel zárjuk, azon egyszerű oknál fogva, hogy a default eset bárhol elhelyezkedhet a switch utasításon belül.

Az elmondottak alapján minden nehézség nélkül elkészíthetjük az előző alfejezet kalkulátor programját switch alkalmazásával:

#include <iostream>

using namespace std;

int main() {

char op;

double a, b, c;

cout<<"kifejezes :";

cin >>a>>op>>b;

cout <<a<<op<<b<<'='<<c<<endl;

return 0;

}

A következő példában bemutatjuk, hogyan lehet több esethez ugyanazt a programrészletet rendelni. A programban a válaszkaraktert feldolgozó switch utasításban az 'i' és 'I', illetve az 'n' és 'N' esetekhez tartozó case címkéket egymás után helyeztük el.

#include <iostream>

A programozási nyelveken utasítások automatikus ismétlését biztosító programszerkezetet iterációnak vagy ciklusnak (loop) nevezzük. A C++ nyelv ciklusutasításai egy ún. ismétlési feltétel függvényében mindaddig ismétlik a megadott utasítást, amíg a feltétel igaz.

while (feltétel) utasítás

for (inicializáló kifejezésopt; feltételopt; léptető kifejezésopt) utasítás do utasítás while (feltétel)

A for utasítás esetén az opt index arra utal, hogy a megjelölt kifejezések használata opcionális.

A ciklusokat csoportosíthatjuk a vezérlőfeltétel feldolgozásának helye alapján. Azokat a ciklusokat, amelyeknél az utasítás végrehajtása előtt értékelődik ki vezérlőfeltétel, az elöltesztelő ciklusok. A ciklus utasítása csak akkor hajtódik végre, ha a feltétel igaz. A C++ elöltesztelő ciklusai a while és a for.

Ezzel szemben a do ciklus utasítása legalább egyszer mindig lefut, hisz a vezérlőfeltétel ellenőrzése az utasítás végrehajtása után történik – hátultesztelő ciklus.