A program utasítások egy sorozata

BecomeAnXcoder – A program utasítások egy sorozata

Bevezetés

Amikor autót tanulsz vezetni, meg kell tanulnod egyszerre több dologra is figyelni: a gáz, a fék pedálra, a kuplungra. A programozásnál is hasonló a helyzet, több dologra is oda kell figyelni, különben a program lefagyhat. Ugyanakkor az autóvezetés elkezdéséhez szükséges, hogy megismerd az autó belsejét, de a programozáshoz nem feltétlenül kell rögtön az Xcode környezet megismerése. Az egyszerűség kedvéért ezt egy kicsit később mutatjuk majd be. Első lépésben néhány nagyon egyszerű matematikai példán keresztül bevezetünk az Objective C programozás alapjaiba.

Már az elemi iskolában találkoztál olyan egyszerű számítási feladatokkal, ahol az eredményt egyszerűen be kell helyettesíteni a pontok helyére:
2 + 6 = ...
... = 3 * 4 (a csillag a szorzás elfogadott jelölése a számítástechnikában)

Felsőbb iskolai osztályokban a pontok kimentek a divatból, helyükre x, y változók kerültek, és már algebrai feladatként kezdtük becézni a korábbi számítási feladatokat. Ma már talán érdekesnek tűnik, miért is okozott sokaknak komoly problémát ez a kis változtatás.
2 + 6 = x
y = 3 * 4

Változók

Az Objective C szintén változókat használ. A változó nem más, mint egy meghatározott adat, például egy szám neve, amivel hivatkozni tudunk rá. Íme egy Objective C utasítás, egy egyszerű programsor, ahol egy változónak konkrét értéket adunk.

//[1]
 x = 4;

A pontosvessző

Itt az x nevű változónak a 4 értéket adjuk.
Fontos megfigyelni, hogy az utasítás végén pontosvessző van. Minden utasítás végére pontosvesszőt kell tenni. Miért van erre szükség? Nos az [1]-es példában látható kódrészlet nyilvánvalónak tűnhet számodra, de a számítógép ezt még közvetlenül nem érti meg. Egy segédprogram, amit fordítóprogramnak nevezünk, lefordítja a szükséges 0-kból és 1-esekből álló utasításokra, amelyek már érthetők a Mac számára is. Az ember által beírt utasítások olvasása és értelmezése komplikált feladat a fordítóprogram számára, szükség van arra, hogy bizonyos jelölésekkel segítsünk neki. Ilyen például az, hogy az utasításokat pontosvesszővel zárjuk le.

Ha elfelejted a pontosvesszőt kitenni, akkor a fordítóprogram nem tudja lefordítani a programkódot, abból bizony nem lesz a Mac által futtatható változat. Azért nem kell emiatt nagyon aggódni, mert a fordítóprogram panaszkodni fog, ha nem tudja értelmezni az általad beírt kódot. Ahogy a későbbiekben látni fogjuk, még abban is segít, hogy megpróbálja kitalálni, hogy hol van a hiba.

Változónevek

Ugyan a változónevek teljesen közömbösek a fordítóprogram számára, mégis érdemes beszédes változóneveket használni. Ez sokat segíthet akkor, ha szeretnénk megérteni egy programkódot, vagy éppen hibakeresés közben is.

Hagyományosan bug-nak (bogár, poloska) nevezünk egy programhibát és innen származik a debugging elnevezés a hibakeresésre és a hibák javítására.

Ezért nem javasoljuk az olyan egyszerű és nem túl beszédes változónevek használatát, mint például az x. Ha mondjuk egy kép szélességére szeretnénk utalni, akkor használjuk a pictureWidth [2] elnevezést (pictureWidth = képszélesség).

//[2]
 pictureWidth = 8;

Azt már láttuk, hogy a fordítóprogram számára már egy apró pontosvessző is milyen fontos. Meg kell még ismernünk néhány hasonlóan egyszerű szabályt, mint például azt, hogy a programkód érzékeny a kis és nagy betűk használatára. Tehát megkülönbözteti a kis és a nagy betűket. A pictureWidth változónév különbözik a pictureWIDTH-től, vagy a PictureWidth-től. Egy általánosan elfogadott konvenció alapján a változónevekben több szót is egybeírhatunk, az elsőt kis betűvel, míg a többi szót nagy betűvel kezdve, ahogy azt a [2]-es példában már láttuk. Ezt a stílust teveEsetnek is szokták nevezni. Ha ehhez hozzászokik valaki és következetesen alkalmazza, akkor jelentősen csökkenni fognak a kis és nagy betűk felcseréléséből adódó programhibák.

Jegyezd meg, hogy a változónevek mindig egyetlen szóból állnak, tehát szóközt nem tartalmazhatnak.

Ugyan bőséges szabadsággal rendelkezel a változónevek megválasztásának területén, azért van néhány szabály amit figyelembe kell venni. Ezen a ponton eléggé unalmas lenne ezek felsorolása, de a legfontosabb szabályt feltétlenül jegyezd már most meg: a változónév nem lehet egy Objective C által lefoglalt szó, tehát olyan, amelyik speciális jelentéssel bír az Objective C számára. Amennyiben a pictureWidth-hez hasonlóan a fenti konvenciónak megfelelő összetett és beszédes változóneveket használsz, biztonságban érezheted magadat. Tehát mégegyszer összefoglalva: válassz beszédes változóneveket, használj nagy betűket közben, és biztosan kevesebb hibád lesz a programozás során.Befejezésül még két dolog: a változónév tartalmazhat számokat is, de azzal nem kezdődhet. Ugyanakkor az aláhúzás karakterrel kezdődhet. Íme néhány példa és ellenpélda:
Korrekt váltózónevek:

door8k
do8or
do_or

      Nem megengedett változónevek:

door 8 (szóközt tartalmaz!)
8door (számjeggyel kezdődik)

      Nem javasolt változónév:

Door8 (nagy betűvel kezdődik)

 

Változók használata számítási feladatokban

Miután már tudjuk, hogyan kell egy változónak értéket adni, most műveleteket fogunk végezni vele. Az alábbi [3]-as programrészlet egy kép területének kiszámítását mutatja be.

//[3] 
pictureWidth=8; 
pictureHeight=6; 
pictureSurfaceArea=pictureWidth*pictureHeight;

Szerencsére a fordítóprogram nem törődik az üres karakterekkel (eltekintve a változónevek, kulcsszavak, … stb. belsejétől), ezért nyugodtan írhatjuk a kódot szelősebben, a szemnek könnyebben olvasható formában.

//[4] 
pictureWidth = 8; 
pictureHeight = 6; 
pictureSurfaceArea = pictureWidth * pictureHeight;

Egész és valós típusú válozók

Most vessünk egy pillantást az [5]-ös példára, annak is az első két utasítására.

//[5] 
pictureWidth = 8; //[5.1] 
pictureHeight = 4.5; //[5.2] 
pictureSurfaceArea = pictureWidth * pictureHeight;

A számokat alapvetően két típusba sorolhatjuk: egész számok és tört számok. Mindegyikre mutatunk egy példát, lásd [5.1] és [5.2]. Az egész számokat elsősorban számolásra használjuk, amikor meghatározott alkalommal szeretnénk adott műveletet megismételni (részletesebben ezzel a 7. fejezetben fogunk foglalkozni). A törtszámok, vagy lebegőpontos számok például különböző sportágak átlagpontszámai alapján lehetnek ismerősek.

Az [5]-ös programrészlet nem lesz működőképes. A problémát itt az okozza, hogy a fordítóprogram megköveteli, hogy előre megmondjuk milyen változóneveket fogunk használni és azt is, hogy azokhoz milyen típusú adatok tartoznak, tehát egészek, vagy lebegőpontos számok. Ezt nevezzük a változók deklarásának.

//[6] 
int pictureWidth; //[6.1] 
float pictureHeight, pictureSurfaceArea; //[6.2]
pictureWidth = 8; 
pictureHeight = 4.5; 
pictureSurfaceArea = pictureWidth * pictureHeight;

A [6.1] sorban az int azt mutatja, hogy a pictureWidth változó egész típusú. A következő sorban egyszerre két változót is deklarálunk, neveiket egymástól vesszővel választottuk el. Egész pontosan a [6.2] utasítás szerint mindkét változó float típusú, azaz úgynevezett lebegőpontos számok, amelyek egész és törtrészt is tartalmaznak. Figyeljük meg, hogy példánkban a pictureWidth változó típusa különbözik a másik két változó típusától. Az is megfigyelhető, hogy ha összeszorzunk egy int típust egy float típussal, akkor a művelet eredménye float lesz. Ezért kell a pictureSurfaceArea változót is float típusúnak deklarálni [6.2].

Miért kell a fordítóprogramnak előre tudni, hogy egy változó egész típusú lesz, vagy törtrészeket is tartalmazni fog? Nos egy számítógépes program használni fogja a gép memóriájának egy részét. A fordítóprogram feladata, hogy lefoglalja a megfelelő memória részt (byte-okat) az összes változó számára. Mivel különböző típusú adatok, esetünkben int és float típusok, különböző memória szeletet és ábrázolást igényelnek, a fordítóprogramnak a korrekt memória területet kell beállítania és a korrekt ábrázolást kell használnia.

Felvetődik a kérdés, hogy mi történik, ha nagyon nagy számokkal, vagy igen nagy pontosságú tizedes számokkal kell dolgoznunk? Ezek ábrázolására esetleg nem lesz elegendő az a néhány byte, amit a fordítóprogram az eddigi példákban lefoglalt. A válasz kettős erre a kérdésre. Egyrészt az int és float típusoknak van olyan megfelelője, amelyik nagyobb méretű, illetve nagyobb pontosságú számok ábrázolására alkalmas. A legtöbb rendszeren megtalálható a megfelelő long long és a double típus. De ez elvezet a kérdés másik szintjéhez is bennünket. Egy programozó feladata, hogy az adott problémához megtalálja a legjobb megoldást. Ennek részletesebb tárgyalása azonban nem egy bevezető könyv első fejezetének témája.

Megjegyezzük, hogy az egész számok és a tizedes számok is lehetnek negatív előjelűek is, ahogy az ismerős lehet például a bankszámláddal kapcsolatban. Amennyiben biztos vagy abban, hogy egy változó értéke nem lehet negatív, akkor lehetőséged van jobb memória kihasználásra.

//[7] 
unsigned int chocolateBarsInStock;

Nincs sok értelme negatív számú csokoládéről beszélni az üzlet polcán, ezért egy unsigned int változót használhatunk ebben az esetben. Ahol az unsigned int típus olyan egész számot reprezentál, amelyik nulla, vagy pozitív.

Változó deklarálás

Menet közben is lehet változókat deklarálni [8].

//[8] 
int x = 10; 
float y= 3.5, z = 42;

Ezzel meg lehet spórolni egy kis gépelést.

Adattípusok

Ahogy azt láttuk, a változók által tárolt adatok különböző típusúak lehetnek, mint például int, vagy float.
Az Objective-C egyszerű adattípusait skaláris adatnak nevezzük. A gyakori skaláris adattípusok a következők:

NÉV TÍPUS PÉLDA
void Void üres
int Egész …-1, 0, 1, 2…
unsigned Előjel nélküli egész 0, 1, 2…
float Lebegőpontos -0.333, 0.5, 1.223, 202.85556
double Duplapontosságú lebegőpontos 0.52525252333234093890324592793021
char Karakter hello
BOOL Logikai 0, 1; TRUE, FALSE; YES, NO.

 

Matematikai műveletek

Az előző példákban már használtunk matematikai műveleteket. Az alapvető matematikai műveletek (operátorok) jelölése a következő:

+ összeadás 
- kivonás 
/ osztás 
* szorzás

Az operátorok segítségével nagyon sokfajta számolási feladatot tudunk elvégezni. Professzionális Objectice C programozók által írt kódokban sok rövidítést lehet találni, talán ez abból következik, hogy nem nagyon szeretnek sokat gépelni.

Ahelyett, hogy azt írnák, hogy x = x + 1; a programozók gyakran használják a [9]-es, vagy [10]-es változatot.

//[9] 
x++;
//[10]
 ++x;

Mindkét esetben az a feladat, hogy növeljük meg az x értékét 1-gyel. Azonban bizonyos körülmények között lényeges lehet, hogy a ++ jel a név előtt, vagy mögötte áll. Nézzük meg a [11]-es és [12]-es példákat.

//[11] 
x = 10; 
y = 2 * (x++); 
// az x értéke 11 a művelet elvégzése UTÁN lett megnövelve 
// az y értéke 20

 

//[12] 
x = 10; 
y = 2 * (++x); //[12.2] 
// az x értéke most is 11 és már ez volt az értéke a művelet elvégzése ELŐTT is 
// az y értéke 22

A [11]-es példában a műveletek elvégzése után az y értéke 20, az x értéke pedig 11. Ezzel szemben a [12.2] utasításban az x értékét megnöveljük 1-gyel mielőtt még a 2-essel való szorzást elvégeznénk. Ezért a végeredményben az x értéke most is 11 lesz, de az y értéke ebben a változatban 22 lesz. A [12]-es kód iegyenértékű a [13]-assal.

//[13] 
x = 10; 
x++; //[13.2] 
y = 2 * x; 
// ebben a változatban a [13.2] sorban a ++x, vagy az x++ felcserélhető

Láthatjuk, hogy időnkét lehetőség van arra, hogy két utasítást összevonjunk, és helyettük csak egyet írjunk le. Személy szerint nekem erről az a véleményem, hogy ezáltal a program olvashatósága, áttekinthetősége lecsökken. Megfelelő billentyűkombinációk beállítása esetén a programírás közben kényelmes lehet, de jelentősen megnöveli a programhibák előfordulási lehetőségét.

Zárójelek

Emlékeztetnénk régi kedves iskolai emlékeidre, mely szerint a zárójelekkel felül lehet írni a műveletek sorrendjét. Ez így van a számítástechnikában is. A szorzás és az osztás magasabb rendű művelet, mint az összeadás és a kivonás. Ezért a 2 * 3 + 4 egyenlő 10-zel. A zárójelek használatával viszont elérhető, hogy az összeadás művelete legyen először elvégezve, ami miatt a 2 * (3 + 4) művelet eredménye 14 lesz.

Osztás

Az osztás művelete megkülönböztetett figyelmet érdemel, ugyanis másképpen működik amikor egész számokon, illetve amikor lebegőpontos számokon operál. Vessünk egy pillantást a következő két példára [14], [15].

//[14] 
int x = 5, y = 12, ratio; 
ratio =  y / x;

 

//[15] 
float x = 5, y = 12, ratio; 
ratio =  y / x;

Az első esetben [14] az eredmény 2. Csak a második esetben [15] kapjuk a 2.4-et, amire valószínűleg számítottál.

Logikai típus

A Boolean egyszerűen egy igaz (True), vagy hamis (False) érték. Az 1 és a 0 megfelel az igaz és a hamis értéknek. A két jelölés felcserélhető, egymással ekvivalens:

True False
1 0

Gyakran használják ezt a típust annak eldöntésére, hogy egy lépés elvégzésre kerüljön-e annak függvényében, hogy egy boolean típusú változó, vagy függvény értéke igaz, vagy hamis.

Modulus

A modulus képzés műveletének a jele: % (modulus). Elképzelhető, hogy ez nem annyira ismerős számodra, kicsit más eredményt adhat, mint amire számít az ember. Nem egy százalékot számoló operátorról van most szó. A % operátor egy egész tipusú osztás segítségével elosztja az első operandust a másodikkal és az eredmény a maradék. Amennyiben a második operandus 0, a művelet nincs értelmezve.

//[16] 
int x = 13, y = 5, remainder; 
remainder =  x % y;

Mivel az 5 csak 2-szer van meg a 13-ban (5 * 2 = 10), a maradék 3 (13 – 10 = 3) és ez lesz a művelet eredménye.

Álljon itt még néhány példa modulus képzésre:

21 % 7 = 0 
22 % 7 = 1 
23 % 7 = 2 
24 % 7 = 3 
27 % 7 = 6 
30 % 2 = 0 
31 % 2 = 1 
32 % 2 = 0 
33 % 2 = 1 
34 % 2 = 0 
50 % 9 = 5 
60 % 29 = 2

Bizonyos esetekben nagyon kényelmesen lehet vele dolgozni, de fontos megjegyezni, hogy csak egész típusú változókkal működik.

Egy gyakori alkalmazási területe a modulus használatának annak az eldöntése, hogy egy egész szám páros, vagy páratlan. Amennyiben páros, akkor a 2-es modulusa 0, egyébként pedig nem. Például:

//[17] 
int anInt; 
//valamilyen kód, amelyik beállatja az anInt változó értékét 
if ((anInt % 2) == 0) 
{
 NSLog(@"az anInt páros"); 
}
 else 
{
 NSLog(@"az anInt páratlan"); 
}

eredeti oldal