|
|
1. sor: |
1. sor: |
| <cim | | <cim |
- | cim3="Előírt lépésszámú ciklusok" | + | cim3="Vektorok" |
| cim2="Magasszintű Programozási Nyelvek I." | | cim2="Magasszintű Programozási Nyelvek I." |
| cim1="Imperatív, procedurális nyelvek alapjai" | | cim1="Imperatív, procedurális nyelvek alapjai" |
15. sor: |
15. sor: |
| | | |
| | | |
- | = Előírt lépésszámú ciklusok = | + | = Vektorok = |
| | | |
- | Tekintsük meg az alábbi kódot:
| |
- |
| |
- | <code lang="csharp">
| |
- | int i=0;
| |
- | while (i<10)
| |
- | {
| |
- | ...
| |
- | i++;
| |
- | }
| |
- | </code>
| |
- |
| |
- | 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.
| |
- |
| |
- | <box type="warn">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.</box>
| |
- |
| |
- |
| |
- | = 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:
| |
- |
| |
- | <code lang="csharp">
| |
- | for(int i=0; i<10; i++)
| |
- | {
| |
- | Console.Write(i);
| |
- | }
| |
- | </code>
| |
- |
| |
- | 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).
| |
- |
| |
- | <box type="warn">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.</box>
| |
- |
| |
- | = 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:
| |
- |
| |
- | <code lang="csharp">
| |
- | 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--;
| |
- | }
| |
- | </code>
| |
- |
| |
- | 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:
| |
- |
| |
- | <code lang="csharp">
| |
- | 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++;
| |
- | }
| |
- | </code>
| |
- |
| |
- | 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:
| |
- |
| |
- |
| |
- | <code lang="csharp">
| |
- | 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);
| |
- | }
| |
- | </code>
| |
- |
| |
- | 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:
| |
- |
| |
- | <code lang="csharp">
| |
- | int db=0;
| |
- | for(int i=0;i<10 && db<3; i++)
| |
- | if (tomb[i]>0) db++;
| |
- | </code>
| |
- |
| |
- | 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:
| |
- |
| |
- | <code lang="csharp">
| |
- | 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 ) { ... }
| |
- | </code>
| |
- |
| |
- | = 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:
| |
- |
| |
- | <code lang="csharp">
| |
- | int ossz=0;
| |
- | for( int i=0; i<10; {ossz=ossz+t[i];i++}) {}
| |
- | Console.WriteLine("Az összeg={0}",ossz);
| |
- | </code>
| |
- |
| |
- | Ezzel szemben helyes az alábbi:
| |
- |
| |
- | <code lang="csharp">
| |
- | int ossz=0;
| |
- | for( int i=0; i<10; ossz=ossz+t[i],i++) {}
| |
- | Console.WriteLine("Az összeg={0}",ossz);
| |
- | </code>
| |
- |
| |
- | 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:
| |
- |
| |
- | <code lang="csharp">
| |
- | int ossz=0;
| |
- | for( int i=0; i<10; ossz=ossz+t[i],i++) ;
| |
- | Console.WriteLine("Az összeg={0}",ossz);
| |
- | </code>
| |
- |
| |
- | 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ó:
| |
- |
| |
- | <code lang="csharp">
| |
- | int i=int.Parse(Console.ReadLine());
| |
- | for( ;i<10; i++)
| |
- | {
| |
- | ...
| |
- | }
| |
- | </code>
| |
- |
| |
- | 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.
| |
- |
| |
- | <code lang="csharp">
| |
- | int i=0;
| |
- | for( ;i<10; )
| |
- | {
| |
- | ...
| |
- | i++;
| |
- | }
| |
- | </code>
| |
- |
| |
- | 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.
| |
- |
| |
- |
| |
- | <code lang="csharp">
| |
- | for(int i=0;i<10; )
| |
- | {
| |
- | ...
| |
- | i++;
| |
- | }
| |
- | </code>
| |
- |
| |
- | 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.
| |
| | | |
| <alairas>Hernyák Zoltán</alairas> | | <alairas>Hernyák Zoltán</alairas> |
| __NOTOC__ | | __NOTOC__ |