Személyes eszközök
Keresés

 

A InfoWiki wikiből


Előírt lépésszámú ciklusok

Tekintsük meg az alábbi kódot:

int i=0;
while (i<10)
{
  ...
  i++;
}

A fenti while ciklus a ciklusmagját 10-szer fogja végrehajtani, mivel az i változó induló értéke 0, minden menetben az i értéke pontosan 1-el nő, és akkor fogja elhagyni a ciklust, ha az i értéke elérte (vagy meghaladta) a 10 értéket.

Gyakoriak azok az esetek, amikor előre ismert, hogy a ciklusmag hányszor kerül majd végrehajtásra. Ez esetben a fentihez hasonló while ciklus alkalmazható, de nem túl szerencsés az alkalmazása. Az információk, amelyből a kiderül, hogy ez a ciklus 10-szer ismétlődik majd - a kódban szétszórtan helyezkedik el. Ráadásul az i változó deklarációja meg kell előzze a while ciklus indulását, így hatásköre (és az élettartama) nem a ciklusra korlátozódik, hanem a ciklus lefutása után is megmarad.

A fenti problémák kezelésére speciális ciklusfajta szolgál, a for ciklus.

A FOR ciklus akkor alkalmazható, ha a ciklus futása előre ismert darabszámú, mely darabszám a ciklus indításakor már kiszámolható, és később sem változik. Ha a ciklus futási darabszáma nem előre kiszámítható, vagy esetleg az változhat, akkor inkább WHILE ciklust kell alklamazni.


FOR fejrésze

A for ciklus fejrésze három részre osztható, melyeket kettő darab pontosvessző határol. A részek szerepe:

  • az inicializáló utasítás (mely a ciklus kezdetekor egyszer hajtódik végre
  • a ciklus vezérlő feltétele (pozitív vezérlésű a for ciklus)
  • a léptető utasítás (mely a ciklusmag lefutása után automatikusan kerül végrehajtásra)

Példa:

for(int i=0; i<10; i++)
{
  Console.Write(i);
}

A fenti példa teljesen megfelel a korábban ismertetet while ciklus példában szereplő kód működésével. Az i változó azonban itt a ciklusra lokális, tehát a for ciklus törzsén túl már nem terjed a hatásköre. A ciklusmag minden lefutása után végrehajtódik az inkrementáló utasítás, vagyis az i értéke nő 1-el.

A példában szereplő for ciklus fejrészében minden információ szerepel, melyből meghatározható, hogy ez a for ciklus pontosan 10-szer fog lefutni. A ciklusmagban az i változó értéke kiolvasható, de megváltoztatása tilos. Ennek oka, hogy az i változó értékének átírása a pontos 10 ismétlést módosítaná (vagy kevesebbszer, vagy többször kerülne végrehajtásra).

A ciklusváltozó ciklusmagon belüli módosítása nem szintaktikai, hanem elvi hiba. A fordító eltűri, de ezen tevékenység ellentmond a for ciklus lényegének. Akinek ilyenre van szüksége, az használjon while ciklust.


Példa

Hibás tehát az alábbi példa (bár nem szintaktikailag, hanem elvi, stílusbeli hiba). A programban a 10 elemű tömböt csak pozitív számokkal kívánjuk feltölteni. Amennyiben a program kezelője valamely elem értékének negatív számot kíván megadni, azt az elemet újra bekérjük:

int[] tomb = new tomb[10];
for(int i=0;i<10;i++)
{
  Console.Write("{0}. szám értéke:");
  tomb[i] = int.Parse(Console.ReadLine());
  if (tomb[i]<0) i--;
}

A feltételben az i-- utasítás az i értékét csökkenti 1-el, amit az inkrementáló utasítás (i++) meg fog növelni 1-el. E miatt negatív szám beírása esetén az i értéke gyakorlatilag nem fog változni - a ciklus következő lefutásakor is ugyanazon i tömbelem kerül feltöltésre.

Ez elegánsabban megoldható while ciklussal:

int[] tomb = new tomb[10];
int i=0;
while (i<10)
{
  Console.Write("{0}. szám értéke:");
  tomb[i] = int.Parse(Console.ReadLine());
  if (tomb[i]>0) i++;
}

Vagyis csak akkor lépünk a következő tömbelem bekérésére, ha ezen tömbelemmel elégedettek vagyunk.

Másik lehetséges megoldás:


int[] tomb = new tomb[10];
for(int i=0;i<10;i++)
{
  do
  {
    Console.Write("{0}. szám értéke:");
    tomb[i] = int.Parse(Console.ReadLine());
  } 
  while (tomb[i]<0);
}

Ez esteben az i-edik tömbelem bekérésől addig nem lépünk tovább, amíg annak értékével elégedettek nem vagyunk.

Trükkösebb ciklusok (a)

A for ciklus fejrészében szereplő vezérlő feltétel tetszőlegesen összetett lehet, hiszen az gyakorlatilag megfelel a while ciklus vezérlő feltételének szerepkörével:

int db=0;
for(int i=0;i<10 && db<3; i++)
  if (tomb[i]>0) db++;

Ez a for ciklus legkésőbb 10 menetben leáll. Korábban is leállhat, ha a tömbben találtunk 3 pozitív számot.

Ez a működés némiképp ellentmond a korábban említett elvvel: a for ciklus működésének darabszáma előre kiszámított kell legyen. Nos, a ez a határeset kategória. Az i változó szerepe a tömb elemeinek indexelése, és ez a ciklus sorra veszi a tömbelemeket. A ciklus maximális végrehajtási száma a fejben adott (ez 10 darab). A korábbi kilépő feltétel belefér.

Trükkösebb ciklusok (b)

Az inkrementáló lépés nem mindíg az 1-el növelés. Tetszőleges utasítás megadható azon a ponton:

for(double a=0;a<1.5; a=a+0.1) { ... }
 for(int i=10;i>0; i-- ) { ... }
 for(int i=2;i<100; i=i+2 ) { ... }
 for(int i=2;i<100; i=i*2-1 ) { ... }

Trükkösebb ciklusok (c)

A C nyelvben szerepel egy misztikus jellemzőjű vessző operátor (, operátor). A vessző operátorral lehetséges egyetlen utasítást megengedő helyre több utasítást is szerepeltetni. Erre szükség lehet olyan esetekben, amikor adott pontján a programnak tilos programblokkot alkalmazni, mégis szeretnénk több utasítást is végrehajtani. Ilyen hely a for ciklus léptető (inkrementáló) utasítsása. Helytelen az alábbi:

int ossz=0;
 for( int i=0; i<10; {ossz=ossz+t[i];i++}) {}
  Console.WriteLine("Az összeg={0}",ossz);

Ezzel szemben helyes az alábbi:

int ossz=0;
 for( int i=0; i<10; ossz=ossz+t[i],i++) {}
 Console.WriteLine("Az összeg={0}",ossz);

A vessző operátor súlyos megkötése, hogy a vesszővel elválasztott utasítások adott sorrendben hajtódnak végre (szekvencia szabály speciális esetre alkalmazása). Ezért a fenti for ciklus még jól is működik.

Vegyük észre, hogy ebben az esetben a for ciklus magja üres. Ez megfelel annak az esetnek, amikor a for ciklus magja egyetlen üres utasítást tartalmaz. Ez esetben a pontosvessző írása a for ciklus fejrésze után nem hiba, hanem ezen üres utasítás lezárása:

int ossz=0;
 for( int i=0; i<10; ossz=ossz+t[i],i++) ;
 Console.WriteLine("Az összeg={0}",ossz);

A vessző operátor azonban a C nyelv azon misztikus, és sokat vitatott megoldása, amely (mint kiderült) több baj forrása, mint amennnyi problémát megold. Ezért a fenti kód a C# nyelvben bár működik, de kerülendő.

A for fejrésze

A for ciklus fejrésze minden esetben három részből áll, akkor is, ha valamely utasítás az üres utasítás. A for ciklus fejrészéből csak a vezérlő feltétel nem lehet üres, de mind a kezdőértékbeállítás, mind a léptetés üresen hagyható:

int i=int.Parse(Console.ReadLine());
 for(  ;i<10; i++) 
 {
    ... 
 }

A for ciklus fejrésze ekkor is három részből kell álljon! Vagyis az üres utasítást is le kell zárni a pontosvesszővel.

int i=0;
 for(  ;i<10; ) 
 {
    ... 
    i++;
 }

Ebben a példában szereplő for ciklus fejrészéből már mindkét elhagyható utasítás elhagyásra is került. Ez már gyakorlatilag megfelel a korábban felírt while ciklus működésének.


for(int i=0;i<10; ) 
 {
    ... 
    i++;
 }

Ezek a hiányos for ciklus fejrészek szintaktikai hibát nem okoznak, de mivel szintén ellentétben állnak a for ciklus lényegét leíró működésnek, használatuk stílustalan, nem javasolt.

Hernyák Zoltán
A lap eredeti címe: „http://wiki.ektf.hu/wiki/Mp1/page400
Nézetek
nincs sb_3.140.186.241 cikk