fel
le

Bejáró ciklusok

A vektorok esetén tapasztaljatjuk, hogy gyakoriak azok a feldolgozások, amikor a vektor minden elemét egyesével elő kell venni, meg kell vizsgálni.

Erre alkalmas a for ciklus, szokásos alakja ilyenkor:

double[] t = new double[80];
// ..
for(int i=0;i<t.Length;i++)
{
  // t[i] elem feldolgozása
}
 

Ebben elég sok a hibalehetőség. Először is a for ciklus fejrésze túl bonyolult, mert három részből is áll. Ezen felül tudni kell, hogy az elemek sorszáma 0-tól indul (nem 1-től), és hogy Length-1-ig megy. Más nyelveken (pl. Basic) az elemek sorszámozása 1-től indul, Length-ig tart. A kód olvashatósága e miatt is alacsony. A ciklusmagban sem szabad elfeledkezni arról, hogy a vektor elemekre a t[i] szintaktikával kell hivatkozni.

Nyilván érezhető, hogy ezek a problémák kezelhetőek. De a problémák akkor is problémák, ha kicsinek tűnnek. Egy nagyobb projekt esetén minden kis hibalehetőség számottevő méreteket ölthet. Valamint ha egy problémát tudunk orvosolni - ne habozzunk.

A megoldást egy újabb ciklusfajta bevezetése jelenti. A foreach ciklus a fenti jellegű for ciklusok kiváltására szolgál, de nem minden esetben alkalmazható. Ezekre ki fogunk térni.

double[] t = new double[80];
// ..
foreac(double x in t)
{
  // x elem feldolgozása
}
 

A foreach ciklus fejrésze 4 részből áll, melyeket szóközök határolnak (ez növeli az olvashatóságot). Az első 2 rész változódeklaráció, melyben (ez esetben) egy double típusú x nevű változót deklarálunk. Ennek a változónak a szerepe hasonló a for ciklusban szereplő i változó szerepére. Ezen x változó nevét mi választjuk meg, de a típusa mindíg egyezik a vektor alaptípusával. Mivel a t vektorunk egy double vektor, így az x típusa is double kell egyen ez esetben.

1. ábra: A foreach ciklus általános felépítése

A harmadik rész a foreach fejrészben mindíg kötelezően in szócska (in=ban,ben angolul). A negyedik pedig a feldolgozandó vektor neve. Eképpen ez úgy olvasandó járja be x a t vektort (legyen x a t-ben). Az x szerepe ez esetben nem az, hogy hordozza azt az információt, hogy "hanyadik vektor elem a soron következő", hanem magát a vektor elem értékét hordozza!

2. ábra: A foreach ciklus működése

Az x változó fizikailag a memória egy külön (saját) ponton foglal helyet. A foreach ciklus működése során a maga komótos tempójában átmásolja ezen x változóba a vektor elemeit. Minden egyes átmásolás után lefuttatja a ciklusmagot. Nem kell tehát törődnünk a vektor indexelésével, nem tudunk alá- vagy túlindexelni, a foreach-re bízhatjuk a munka nagy részét. A ciklusmagban nekünk csak az x aktuális értékével kell törődnünk. Előre bocsájtjuk hogy a foreach a listák esetén is teljesen hasonlóan működik, és ezen működése ki is terjeszthető megfelelő OOP technikákkal akár saját adattípusra is.

Hátrányok

A for ciklus esetén a ciklusmagban nem csak a vektor elemhez lehet hozzáférni, de azt is lehet tudni, hol tartunk a feldolgozásban - az i ciklusváltozó aktuális értéke is ismert. Ugyanakkor a foreach belsejében csak az aktuális vektorelem értéke ismert, nem lehet tudni ez hanyadik elem a sok közül. Ezen persze lehet segíteni, de mint látjuk, innentől kezdve akár for ciklust is írhatnánk akár:

double[] t = new double[80];
// ..
int i=0;
foreac(double x in t)
{
  // x elem feldolgozása
  i++;
}
 

Másik probléma - a for ciklus belsejében nem csak lekérdezhető a t vektor aktuális eleme, de meg is változtatható annak értéke. A foreach esetén ez nem igaz. Sajátságos működése miatt a foreach kimásolja az x-be a soron következő értéket, de a ciklusmahban hiába módosítanánk az x értékét, azt nem másolja vissza a vektorba. E miatt az x-en keresztül a vektor elemeinek értéke nem módosítható!

double[] t = new double[80];
// ..
// feltöltjük a vektort 0-kal
foreac(double x in t)
{
  x = 0; // de ez sajnos hibás!
}
 

A fordító ügyel erre, vagyis nem enged a ciklusmagban x-re vonatkozó értékadó utasítást kiadni. E miatt a foreach ciklus nem alkalmas a vektorok feltöltésére, csak a már "kész" vektorok feldolgozására.

Összegzés megvalósítása

Határozzuk meg egy t vektorban lévő értékek összegét. Oldjuk meg foreach-el és for-al is.

double[] t = new double[80];
// ..
double sum = 0;
foreac(double x in t)
  sum = sum+x;
 
double[] t = new double[80];
// ..
double sum = 0;
for(int i=0;i<t.Length;i++)
  sum = sum+t[i];
 
Hernyák Zoltán
2013-01-24 10:59:00