MQL4 könyv   Operátorok   A 'for' ciklusoperátor

A ’for’ ciklusoperátor

Egy másik ciklusoperátor a ‘for' operátor.

A ' for' operátor formátuma

A 'for' ciklusoperátor teljes formátuma áll  - a fejlécből, ami tartalmazza az 1.Kifejezést a Feltételt és a 2.Kifejezést - és áll a végrehajtható ciklustörzsből, amelyet kapcsos zárójelek közé zárunk.

for (1.Kifejezés; Feltételt; 2.Kifejezés) // Ciklusoperátor fejléc
 { // Nyitó kapcsos zárójel
 Operátor blokk.. // A ciklustörzs állhat ...
 ..alkotja a ciklustörzset //... több operátorból is
 } // Záró kapcsos zárójel

Ha a 'for' operátorban a ciklustörzs csak egy operátorból áll a zárójeleket elhagyhatjuk.

 
for (1.Kifejezés; Feltételt; 2.Kifejezés) // Ciklusoperátor fejléc
Egy operátor a ciklustörzs

Az 1.Kifejezés a Feltétel és a 2.Kifejezés hiányozhatnak a kódból. Azonban az elválasztó karakternek ";” (pontosvessző) maradnia kell a kódban.

 for ( ; Feltétel; 2.Kifejezés) // Nincs 1.Kifejezés
{      // Nyitó kapcsos zárójel
Operátor blokk..    // A ciklus test állhat ...
..alkotja a ciklus testet //... több  operátorból is
}     // Záró kapcsos zárójel
// - ---------------------------------------------------------------------------------
for (1.Kifejezés; ; 2.Kifejezés) // Nincs Feltétel
{      // Nyitó kapcsos zárójel
Operátor blokk..     // A ciklus test állhat ...
 ..alkotja a ciklus testet  //... több operátorból is
}     // Záró kapcsos zárójel
// - ---------------------------------------------------------------------------------
for ( ; ; )   // Nincsenek Kifejezések sem Feltétel
{      // Nyitó kapcsos zárójel
Operátor blokk..   // A ciklus test állhat ...
..alkotja a ciklus testet //... több  operátorból is
}   // Záró kapcsos zárójel


A 'for' operátor végrehajtási szabálya

Figyelem!

Amint a vezérlést megkapja a ’for' operátor, a program végrehajtja az 1.Kifejezést. Mindaddig, amíg az operátor Feltétele (Condition) igaz: a vezérlést megkapja az első operátor a ciklus testben; amint minden operátort a ciklus testben végrehajtottak, a programnak végre kell hajtania a 2.Kifejezést és át kell adni a vezérlést a fejlécbe, hogy az tesztelhesse a feltételt. Ha a ‘for' operátor feltétele hamis: a programnak át kell adnia a vezérlést annak az operátornak, amelyik követi a ‘for' operátort.

Gondolkozzunk, hogyan működik a 'for' ciklusoperátor. Oldjunk meg egy feladatot.

Feladat

13. feladat: Nekünk van egy egész számsorunk: 1 2 3 4 5 6 7 8 9 10 11 ... Alkossunk egy programot, ami kiszámítaná ezen sorozat elemeinek az összegét, N1-töl N2-ig.


Ezt a problémát matematika szempontból könnyű megoldani. Tételezzük fel azt, hogy harmadik elemtől a hetedik elemig ki akarjuk számítani az elemek összegét. A megoldás ez lenne: 3 + 4 + 5 + 6 + 7 = 25. Azonban, ez a megoldás csak egy speciális esetben jó, amikor az összeadandó elemek első és utolsó eleme 3 illetve 7. Egy programot, ami ezt a feladatot elvégzi úgy kell megalkotni, hogy a számsor bármely elemét választhassuk kezdő illetve végső értéknek (például 15-től 23-ig), és könnyen megváltoztathassuk a kezdő és végső értéket anélkül, hogy a programsorokat egyéb helyen módosítanánk. Lent van egy ilyen programváltozat (script sumtotal.mq4):

//-----------------------------------------------------------------------------
// sumtotal.mq4
// The code should be used for educational purpose only.
//-----------------------------------------------------------------------------
int start() // Special function start()
 {
//-----------------------------------------------------------------------------
 int
 Nom_1, // Number of the first element
 Nom_2, // Number of the second element
 Sum, // Sum of the numbers
 i; // Formal parameter (counter)
//-----------------------------------------------------------------------------
 Nom_1=3; // Specify numeric value
 Nom_2=7; // Specify numeric value
 for(i=Nom_1; i<=Nom_2; i++) // Cycle operator header
 { // Brace opening the cycle body
 Sum=Sum + i; // Sum is accumulated
 Alert("i=",i," Sum=",Sum); // Display on the screen
 } // Brace closing the cycle body
//------------------------------------------------------------------------------
 Alert("After exiting the cycle, i=",i," Sum=",Sum);// Display on the screen
 return; // Exit start()
 }
//------------------------------------------------------------------------------

A program első soraiban a változókat deklarálunk (a megjegyzések megmagyarázzák a változók értelmét). Ezekben a sorokban:

 Nom_1 = 3; // Specify numeric value
 Nom_2 = 7; // Specify numeric value

a tartomány első és utolsó elemének számszerű meghatározása történik. Vedd észre, hogy ezeket az értékeket sehol máshol nem kell megadni a programban. Ha szükséges, könnyen meg tudod változtatni ezeket az értékeket (egy helyen) anélkül, hogy a kód bármely másik sorát megváltoztatnád. Ezek után a vezérlést megkapja a 'for' ciklusoperátor:

 for(i=Nom_1; i<=Nom_2; i++) // Cycle operator header
 { // Brace opening the cycle body
 Sum = Sum + i; // Sum is accumulated
 Alert("i=",i," Sum=",Sum); // Display on the screen
 } // Brace closing the cycle body

A kulcsmondat - a 'for' operátor végrehajtási szabálya - a következő: A kezdettől… mindaddig… lépj...  hajtsd végre a következőt: . A ”lépj…” akkor használható, ha számlálót (például: i++ vagy  i=i+2) alkalmazunk a 2.Kifejezésben. A példánkban a kulcsmondat a következő: Kezdetben i egyenlő Nom_1, mindaddig amíg i kevesebb vagy egyenlő Nom_2, lépj1-et, hajtsd végre a következőt: (a ciklustörzs végrehejtása).

A 'for' operátor végrehajtásszabálya szerint végre fogjuk hajtani ezt a blokkot a programból:

1. Az 1. Kifejezés végrehajtása:

 i=Nom_1

Az i változó felveszi a Nom_1 változó számszerű értékét, vagyis 3 egész szám értéket. Az 1. Kifejezést csak egyszer hajtjuk végre - amikor a vezérlést megkapja a 'for' operátor. Az 1.Kifejezés nem vesz részt semmilyen rákövetkező eseményben.

2. A Feltételt teszteljük:

 i<=Nom_2

A Nom_2 változó értéke az első ismétlésnél 7 (egész szám), míg az i változó egyenlő 3-mal. Ez azt jelenti, hogy a feltétel igaz (3 kevesebb 7-nél), vagyis a vezérlést megkapja a ciklustörzs, hogy azt végrehajtsa.

3. A példánkban a ciklustörzs két operátorból áll amelyeket egyenként végre fogunk hajtani:

 Sum = Sum + i; // Sum is accumulated
 Alert("i=",i," Sum=",Sum); // Display on the screen

A Sum változó az inicializálásánál nem kapott kezdőértéket, ezért az értéke az első ciklus kezdete előtt egyenlő nullával. A számítások alatt a Sum változó értékét növeljük az i értékével, tehát az első ismétlés végén i egyenlő 3-mal. Ezt az értéket látjuk az Alert() függvény ablakában:

i=3 Sum=3

4. Az utolsó esemény a ciklus operátor végrehajtása alatt  a 2.Kifejezés végrehajtása:

 i++

Az i változó értéke eggyel növekszik. Ezzel az első ismétlésnek vége, a vezérlés teszteli a feltételt.

Ezután a második ismétlés kezdődik a 2-4 lépésekkel. A számítások alatt a változók új értékeket kapnak. Esetünkben a második ismétlésnél az i változó értéke egyenlő 4-gyel, míg Sum egyenlő 7-tel. A megfelelő üzenet szintén meg fog jelenni. Általában véve, a program a lenti blokkdiagram szerint fog tovább haladni:


43. ábra: A 'for' operátor végrehajtásának a blokkdiagramja a sumtotal.mq4 programban.


A program ciklikusan ismételni fogja a ciklusoperátor végrehajtását, amíg a Feltétel (Condition) hamissá válik. Ez akkor fog megtörténni, amikor az i változó értéke egyenlő lesz 8-cal, vagyis meghaladja Nom_2 változó előre beállított értékét a 7-et. Ebben az esetben a vezérlés a 'for' operátoron kívülre kerül mégpedig ebbe a sorba:

 Alert("After exiting the cycle, i=",i," Sum=",Sum);// Display on the screen

és végül a 'return' operátor végrehajtása befejezi a start() különleges függvény munkáját.

Arra lehet használni ezt a programot, hogy bármilyen tartománynak az összegét kiszámítsa. Például, ha kicseréled a 3 és 7 állandókat 10-re és 15-re a program végrehajtása az ezen a tartományon belül értékek összegének a kiszámításával fog végződni.

Néhány programnyelvben azok a változók, amiket a ciklusoperátor fejlécében használnak elvesztik az értékeiket miután kiléptünk a ciklusból. Ez nem így van az MQL4-ben. Minden változó, ami szerepet játszik bármilyen számításban, érvényes és megtartja az értékét miután kiléptünk a ciklusból. Ugyanakkor néhány sajátosság érinti azon változók értékeit, amik a számításokban szerepeltek.

Jegyezd meg, hogy az utolsó két üzenet sor megmarad a számítások befejezése és a script eltávolítása után is:

i=7 Sum=25
After exiting the cycle, i=8 Sum=25

A fentebb két üzenet közül  az első még azelőtt megjelent, mielőtt az utolsó ciklus teljesen végrehajtódott, míg az utóbbit az Alert() függvény a program befejezése előtt küldte. Figyelmet érdemel, hogy ezekben a sorokban az i változó különböző értékei szerepelnek. A ciklus végrehajtása alatt ez az érték 7, de 8 lesz amikor kilépünk a ciklusból.Hogy megértsük ez miért történik így, nézzük meg a 43. ábrát még egyszer!

Az utolsó (ebben az esetben, az ötödik) ismétlés a feltétel tesztelésével kezdődik. Az i értéke ebben a pillanatban egyenlő 7-tel. Ez az érték nem nagyobb, mint a Nom_2 változó, a feltétel igaz és a ciklustörzset végre kell hajtani. Amint a ciklustörzset alkotó operátorok közül az utolsót is végrehajtjuk: a 2. kifejezést szintén végre kell hajtani. Ezt még egyszer hangsúlyozni kell:

Figyelem!

Az utolsó esemény, ami lejátszódik a 'for' operátor mindegyik ismétlésénél, a 2.Kifejezés kiszámítása.

Ez ahhoz vezet, hogy az i változó értéke növekszik 1-el és 8-as értéket kap. A feltétel (Condition) következő tesztje (a következő ismétlés kezdetén) azt az eredményt adja, hogy a feltétel most hamis. Ez azt eredményezi, hogy a vezérlés a teszt elvégzése után a ciklusoperátoron kívül kerül. Ugyanakkor, az i változó értékel a ciklusoperátor elhagyásakor 8, míg a Sum változó értéke egyenlő 25-tel, mert a ciklustörzs operátorait már nem hajtjuk végre. Ezt figyelembe kell venni olyan helyzetekben, ahol az ismétlések (iterációk) számát előre nem ismerjük.

Azt hihetnénk, hogy az olyan helyzet, ami hurkolódáshoz vezet kivételes. Ez különféle hibáknál könnyen lehetségessé válik. Például, ha hibásan használod a 2. kifejezést:

 i--

mindegyik ismétlésnél a számláló értéke csökkenni fog, és a Feltétel soha nem válik hamissá.

A másik hiba a helytelenül megfogalmazott Feltétel (Condition) lehet:

for(i=Nom_1; i>=Nom_1; i++) // Cycle operator header

Ebben az esetben, az i változó értéke mindig nagyobb vagy egyenlő lesz Nom_1 változó értékével, és a Feltétel mindig igaz lesz.

A 'while' és 'for' ciklus operátorok felcserélhetők

Hogy egyik vagy másik operátort használja a programozó döntésétől függ. Az egyetlen dolog, amit meg kell jegyezni, hogy ezeket az operátorokat szinonimákként használhatjuk; és a cseréjük csak egy kis finomítást jelent a kódban.

Például: a 13. feladat megoldására a 'for' ciklusoperátort használtuk:

 for (i=Nom_1; i<=Nom_2; i++) // Cycle operator header
 { // Brace opening the cycle body
 Sum = Sum + i; // Sum is accumulated
 Alert("i=",i," Sum=",Sum); // Display on the screen
 } // Brace closing the cycle body

Lent egy olyan példa látható, ahol ugyanazt a kódrészletet látjuk a 'while' operátor alkalmazásával:

 i=Nom_1; // Оператор присваивания
 while (i<=Nom_2) // Cycle operator header
 { // Brace opening the cycle body
 Sum = Sum + i; // Sum is accumulated
 Alert("i=",i," Sum=",Sum); // Display on the screen
 i++; // Increment of the element number
 } // Brace closing the cycle body

Láthatjuk, hogy az 1.Kifejezés a ciklusoperátort megelőző sorba került, míg a 2.Kifejezés bekerült a ciklustörzsbe. Meg tudod változtatni a példa programot magad is. Indítsd el és futtasd, hogy lásd, az eredménye ugyanaz mindkét verziónak.