8. fejezet: Ciklusok

Mint a nyelvekben általában, itt is léteznek ciklusok. Az alapvető három ciklus-típus: elöltesztelő, hátultesztelő és számláló. Lássuk ezeket sorban!

 

Elöltesztelő = while. A while utasítás addig hajtódik végre, amíg a feltétele hamis nem lesz. Ugye arról sem szabad megfeledkezni, hogy az elöltesztelő ciklus akkor nem fut le egyetlen egyszer sem, ha a feltétel hamis!

A ciklusokat egy igen egyszerű programmal szeretném bemutatni. Alapötlet: adjuk össze a pozitív egész számokat 10-ig (a 10-et is). Az összeg: 55. Ezt először egy elöltesztelő ciklussal oldjuk meg!

---------------------------------------------

//Elöltesztelő ciklus

#include <iostream>

using namespace std;

 

int main()

{

    cout <<"Ez egy elo:ltesztelo: ciklus!\n ";

    int szam = 1;

    int osszeg = 0;

    while (szam<11)

          {

          osszeg = osszeg + szam;  // növeljük az összeget a számmal

          szam++;                  // A számot növeljük eggyel

          }

    cout <<"O:sszeg: " <<osszeg <<endl;

    return 0;

}

---------------------------------------------

 

Látható, hogy elöl (menet közben) deklaráltuk az összeg-változót (osszeg) és a ciklusváltozót (szam). Természetesen mindkettőt egészként (int).

A ciklusmagban mindössze annyi szerepel, hogy az összeget növeljük az aktuális számmal, majd a ciklusváltozót is növeljük 1-gyel.

Mivel ez még elég kevésnek tűnik, ezért próbáljuk meg egy kicsit kidíszíteni.

Feladat: Adjuk össze a számokat 1-től 20-ig, de ezúttal úgy, hogy írja ki az összeadást is, pl.: 1+2+3+... = eredmény. Ezt már kicsit összetettebben kell megoldanunk, mivel minden egyes összeadás után ki kell írni a számot és a "+" jelet is. Így a ciklusmag a következőképpen néz ki:

         osszeg = osszeg + szam;  // növeljük az összeget a számmal

          cout <<szam <<"+";

          szam++;                  // A számot növeljük eggyel

Ez rendben is lenne, de az utolsó szám után már ne jó, hogy kiírja a "+" jelet, így ott meg kell vizsgálnunk, hogy mit is írassunk ki.

Ezt természetesen egy feltétellel lehet legegyszerűbben megtennünk.

Tehát a ciklusmag ezen verziója a következőképpen néz ki:

          osszeg = osszeg + szam;  // növeljük az összeget a számmal

          cout <<szam;

          if (szam<10) cout <<"+"; else cout <<"=";

          szam++;                  // A számot növeljük eggyel

 

Ez már majdnem jó lenne, de arról volt szó, hogy ne 10-ig, hanem 20-ig adja össze a számokat.

Ezt simán is ki lehet cserélni, de szeretnék mutatni egy lehetséges technikát. Az egész programban lehet egy új névvel helyettesíteni pár fontosabb értéket. Ezek lesznek az állandók, azaz konstansok. Itt például három állandót is definiálok: eddig, pluszjel, egyenlo.

Fontos, hogy ezeket lehetőség szerint még az int main() előtt kell definiálni. Érdekes, hogy egy-egy ilyen definíciós sor után nem kell pontosvessző!

Tehát immár a teljes program:

---------------------------------------------

//Elöltesztelő ciklus - újabb verzió

#include <iostream>

using namespace std;

#define eddig 20    // Itt definiálok egy állandót.

#define pluszjel "+"  // Ez egy újabb

#define egyenlo "="   // Ez pedig az utolsó

 

int main()

{

    cout <<"Ez egy elo:ltesztelo: ciklus!\n ";

    int szam = 1;

    int osszeg = 0;

    while (szam<eddig+1)

          {

          osszeg = osszeg + szam;  // növeljük az összeget a számmal

          cout <<szam;

          if (szam<eddig) cout <<pluszjel; else cout <<egyenlo;

          szam++;                  // A számot növeljük eggyel

          }

    cout <<osszeg <<endl;

    return 0;

}

---------------------------------------------

Második ciklusunk a hátultesztelő. Alapesete: do ciklusmag while feltétel.

A ciklusmag itt egyszer mindenképpen lefut. A ciklus addig fut, amíg a záró feltétel teljesül. Magyarul kilép, ha hamis lesz. Az előző programot kicsit át kell gyúrni. Íme:

---------------------------------------------

//Hátultesztelő ciklus

 

#include <iostream>

using namespace std;

#define eddig 10      // Itt definiálok egy állandót.

#define pluszjel "+"  // Ez egy újabb

#define egyenlo "="   // Ez pedig az utolsó

int main()

{

    cout <<"Ez egy hatultesztelo: ciklus!\n ";

    int szam = 0;

    int osszeg = 0;

    do

       {

       szam++;

       osszeg = osszeg + szam;

       cout <<szam;

       if (szam<10) cout <<pluszjel;

                    else cout <<egyenlo;

       }

    while (szam <10);

    cout <<osszeg <<endl;

}

---------------------------------------------

A harmadik típusú ciklus a számláló. Mielőtt erre sor kerülne, érdemes kicsit megállni gyakorolni. Tapasztalatom szerint a diákok többsége ilyenkorra kezd kimerülni és érdemes velük még egyszer átrágni ezt a kiemelt fontosságú anyagot. Sajnos sokan nem hiszik el, hogy a matematika a legegyszerűbben gyakorolható ciklusos példa, de ilyen kevés programozói tudással mást nem nagyon találunk. Ha a társaság elég fáradt vagy agyilag elég elhasznált, akkor ilyenkor jön még két matematikai példa:

1.) Kérjen be a billentyűzetről egy pozitív egész számot és 1-től a bekért számig adja össze a számok négyzetét! Használjon elöltesztelő ciklust!

2.) Kérjen be egy számot, szorozza meg kettővel és adjon hozzá egyet és az így kapott páratlan számig adja össze a pozitív páratlan számokat! Használjon hátultesztelő ciklust!

Persze a két ciklus típusa keverhető! Lássuk most az elsőnek a megoldását! Javaslom a tisztelt olvasónak, hogy ezt először magától próbálja megoldani és csak utána nézze meg az én megoldásomat!

---------------------------------------------

//Kérjen be a billentyűzetről egy pozitív egész számot és 1-től a bekért számig adja össze a számok négyzetét!

#include <iostream>

using namespace std;

#define pluszjel "+"  // Állandó definiálása

#define egyenlo "="   // Még egy

#define szorzas "*"   // Még egy

 

int main()

{

    int eddig;

    cout <<"Ez egy elo:ltesztelo: ciklus!\n Kérek egy pozitiv egesz szamot!";

    cin >>eddig;

    int szam = 1;

    int osszeg = 0;

    while (szam<eddig+1)

          {

          osszeg = osszeg + szam*szam;  // növeljük az összeget a szám négyzetével

          cout <<szam <<szorzas <<szam;

          if (szam<eddig) cout <<pluszjel; else cout <<egyenlo;

          szam++;                  // A számot növeljük eggyel

          }

    cout <<osszeg <<endl;

    return 0;

}

---------------------------------------------

Most pedig jöjjön a második feladat megoldása!

---------------------------------------------

//Kérjen be egy számot, szorozza meg kettővel és adjon hozzá egyet és az így kapott páratlan számig adja össze a pozitív páratlan számokat!

#include <iostream>

using namespace std;

#define pluszjel "+"  // Állandó definiálása

#define egyenlo "="   // Újabb

 

int main()

{

    int x, eddig;

    cout <<"Ez egy hatultesztelo: ciklus!\n Kerek egy pozitív egesz szamot!";

    cin >>x;

    eddig = 2*x+1;  //Így biztos, hogy pozitív páratlan lesz a szám!

    int szam = 1;

    int osszeg = 0;

    do

       {

       osszeg = osszeg + szam;

       cout <<szam;

       szam = szam + 2;

       if (szam<eddig) cout <<pluszjel;

                    else cout <<egyenlo;

       }

    while (szam < eddig);

    cout <<osszeg <<endl;

}

---------------------------------------------

Harmadik típusunk a számláló ciklus.

Alapesete: for (inicializáció; feltétel; növekmény) ciklusmag;

Még mindig az alapesetet oldjuk meg, tehát adjuk össze a számokat 1-től 10-ig!

---------------------------------------------

//Számláló ciklus

 

#include <iostream>

using namespace std;

#define eddig 10      // Itt definiálok egy állandót.

#define pluszjel "+"  // Ez egy újabb

#define egyenlo "="   // Ez pedig az utolsó

int main()

{

    cout <<"Ez egy szamlalo ciklus!\n ";

    int osszeg = 0;

    for (int szam = 1; szam <eddig+1; szam++)

       {

       osszeg = osszeg + szam;

       cout <<szam;

       if (szam<eddig) cout <<pluszjel;

                    else cout <<egyenlo;

       }

    cout <<osszeg <<endl;

}

---------------------------------------------

A diákjaim általában kezdő programozók, így tapasztalatom szerint ezt szeretik a legjobban. Ne felejtsük el, hogy ez a ciklus pontosan annyiszor fut le, ahányszor megszabtuk a feltételben! De kérem, hogy senki ne bajmolódjon, ha mégis a másikakat kell választania!

Kicsit bonyolítsuk a feladatot! Kérjünk be a billentyűzetről egy számot, ameddig a gép adja össze az összes pozitív egészet!

Itt a ciklusmaghoz nem kell nyúlni, csak a program legelejét kell kicsit átszerkeszteni. Íme:

    int eddig;

    cout <<"Ez egy szamlalo ciklus!\n ";

    cout <<"Kerek egy pozitiv egesz szamot!";

    cin >> eddig;

Ez szépen le is fut, feltéve, ha pozitív egészet (megfelelő nagyságrendig) írunk be. De mi van, ha nem? Nos, az ilyen balesetek kiküszöbölésére érdemes az elejére egy feltételt írni, melyben megvizsgáljuk a beírt számot. Érdemes egy beírható legnagyobb számot definiálni (maxximum), mivel ezt a legkönnyebb átírni.

---------------------------------------------

//Számláló ciklus - bonyolítva

 

#include <iostream>

using namespace std;

#define pluszjel "+" 

#define egyenlo "="  

#define maxximum 10000 // A beírható legnagyobb egész szám!

int main()

{

    int eddig;

    cout <<"Ez egy szamlalo ciklus!\n ";

    cout <<"Kerek egy pozitiv egesz szamot!";

    bool ujrafut = false;

    do

       {

       if (ujrafut) cout << "Rossz szamot adott meg! Probalja ujra!";

       ujrafut = true;

       cin >> eddig;

       }

    while ((eddig < 0) or (eddig > maxximum));

    int osszeg = 0;

    for (int szam = 1; szam <eddig+1; szam++)

       {

       osszeg = osszeg + szam;

       cout <<szam;

       if (szam<eddig) cout <<pluszjel;

                    else cout <<egyenlo;

       }

    cout <<osszeg <<endl;

}

---------------------------------------------

 

További lehetőségek:

Hirtelen kilépés a ciklusból: break;

Adott ciklusmag kihagyása: continue;

---------------------------------------------

// continue-break példa

#include <iostream>

using namespace std;

int main ()

{

  for (int n=10; n>0; n--) {

    if (n==5) continue; //Itt maradt ki az 5

    cout << n << ", ";

  }

  cout << "Kilepes!\n";

  return 0;

}

---------------------------------------------

 

Van egy olyan lehetőség is, amit én őszintén szólva nem ajánlok, mert használata meggondolatlan címkézés esetén veszélyes lehet; ez a goto. Fontos kiemelni, hogy ez látszólag igen kényelmes és jó lehetőség, de gyakorlatlan kezekben komoly gondokat és sok-sok kellemetlen program-összeomlás eredményezhet.

 

---------------------------------------------

// goto-loop példa

#include <iostream>

using namespace std;

int main ()

{

  int n=10;

  loop:                     //címke

  cout << n << ", ";

  n--;                      //n 1-gyel csökkentése

  if (n>0) goto loop;   //ugrás a címkére

  cout << "FIRE!\n";

  return 0;

}

---------------------------------------------

 

Kérdés: itt hol van a ciklus? Sehol! Mert a ciklust a goto-loop helyettesíti.

 

Az exit függvény a cstdib könyvtár része. Lényege: a program bizonyos hibakódú kilépését vezérli.

Minta: void exit (int exitcode);

Az exitcode függvényt nem használja minden operációs rendszer és alkalmazói program, de egyre gyakoribb a használata. Még valami: a 0-ás kilépési kód azt jelenti, hogy minden rendben folyt le.