C Sharp programozás/Operátorok

A Wikikönyvekből, a szabad elektronikus könyvtárból.
Ugrás a navigációhoz Ugrás a kereséshez


Amikor programozunk utasításokat adunk a számítógépnek. Ezek az utasítások kifejezésekből állnak, a kifejezések pedig operátorokból és operandusokból illetve ezek kombinációjából jönnek létre:

i = x + y;

Ebben a példában egy utasítást adunk, mégpedig azt, hogy i –nek értékéül adjuk x és y összegét. Két kifejezés is van az utasításban:

1. x + y –> ezt az értéket jelöljük * -al 2. i = * -> i –nek értékül adjuk a * -ot

Az első esetben x és y operandusok, a ‘+’ jel pedig az összeadás művelet operátora. Ugyanígy a második pontban i és * (vagyis x+y) az operandusok az értékadás művelet (‘=’) pedig az operátor. Egy operátornak nem csak két operandusa lehet. A C# nyelv egy- (unáris) és háromoperandusu (ternáris) operátorokkal is rendelkezik. A következő néhány fejezetben átvesszünk néhány operátort, de nem az összeset. Ennek oka, hogy bizonyos operátorok önmagukban nem hordoznak jelentést, egy speciális részterület kapcsolódik hozzájuk, ezért ezeket az operátorokat majd a megfelelő helyen ismerjük meg. (Pl. az indexelő operátor most kimarad, elsőként a tömböknél találkozhat vele az olvasó.)

Operátor precedencia[szerkesztés]

Amikor több operátor is szerepel egy kifejezésben a fordítónak muszáj valamilyen sorrendet (precedenciát) fölállítani köztük, hiszen az eredmény ettől is függ. Pl.:

10 * 5 + 1

Sorrendtől függően az eredmény lehet 51, vagy 60. A jó megoldás az elöbbi, az operátorok végrehajtásának sorrendjében a szorzás és osztás előnyt élvez. A legelső helyen szerepelnek pl. a zárójeles kifejezések, utolsón pedig az értékadó operátor. Ha bizonytalanok vagyunk a végrehajtás sorrendjében mindig használjunk zárójeleket, ez a végleges programra semmilyen hatással sincs. A fenti kifejezés tehát így nézzen ki:

(10 * 5) + 1

Értékadó operátor[szerkesztés]

Az egyik legáltalánosabb művelet amit elvégezhetünk az az, hogy egy változónak értéket adunk. A C# nyelvben ezt az egyenlőségjel segítségével tehetjük meg:

int x = 10;

Létrehoztunk egy int típusú változót, elneveztük x –nek és kezdőértékének 10 –et adtunk. Természetesen nem kötelező a deklarációnál (amikor tájékoztatjuk a fordítót, hogy van egy valamilyen típusú, adott nevű változó) megadni a definíciót (amikor meghatározzuk, hogy a változó milyen értéket kapjon), ezt el lehet halasztani:

int x;
x = 10;

Ettől függetlenül a legtöbb esetben ajánlott akkor értéket adni egy változónak amikor deklaráljuk. Egy változónak nem csak konstans értéket, de egy másik változót is értékül adhatunk, de csak abban az esetben, ha a két változó azonos típusú, illetve ha létezik a megfelelő konverzió (a típuskonverziókkal egy későbbi fejezet foglalkozik).

int x = 10;
int y = x; //y értéke most 10

Matematikai operátorok[szerkesztés]

A következő példában a matematikai operátorok használatát mutatjuk meg:

using System;

public class Operators
{
       static public void Main()
       {
               int x = 10;
               int y = 3;
               
               int z = x + y; //Összeadás: z = 10 + 3
               Console.WriteLine(z); //Kiírja az eredményt: 13
               z = x - y; //Kivonás: z = 10 - 3
               Console.WriteLine(z); // 7
               z = x * y; //Szorzás: z = 10 * 3
               Console.WriteLine(z); //30
               z = x / y; //Maradék nélküli osztás: z = 10 / 3;
               Console.WriteLine(z); // 3
               z = x % y; //Maradékos osztás: z = 10 % 3
               Console.WriteLine(z); // Az osztás maradékát írja ki: 1
               Console.ReadKey(); //Vár egy billentyűleütést
       }
}

Relációs operátorok[szerkesztés]

A relációs operátorok segítségével egy adott értékkészlet elemei közti viszonyt tudjuk lekérdezni. A numerikus típusokon értelmezve van egy rendezés reláció:

using System;

public class RelOp
{
       static public void Main()
       {
               int x = 10;
               int y = 23;
               
               Console.WriteLine(x > y); //Kiírja az eredményt: false
               Console.WriteLine(x == y); //false
               Console.WriteLine(x != y); //x nem egyenlő y –al: true
               Console.WriteLine(x <= y); //x kisebb-egyenlő mint y: true
               Console.ReadKey();
       }
}

Az első sor egyértelmű, a másodikban az egyenlőséget vizsgáljuk a kettős egyenlőségjellel. Ilyen esetekben figyelni kell, mert egy elütés is nehezen kideríthető hibát okoz, amikor egyenlőség helyett az értékadó operátort használjuk. Az esetek többségében ugyanis így is le fog fordulni a program, működni viszont valószínűleg rosszul fog. Minden ilyen operátor logikai típussal tér vissza. A relációs operátorok összefoglalása:

Operátor Jelentés
x > y x nagyobb mint y
x >= y x nagyobb vagy egyenlő mint y
x < y x kisebb mint y
x <= y x kisebb vagy egyenlő mint y
x == y x egyenlő y -nal
x != y x nem egyenlő y -nal

Logikai/feltételes operátorok[szerkesztés]

Akárcsak a C++, a C# sem rendelkezik „igazi” logikai típussal, ehelyett 1 és 0 jelzi az igaz és hamis értékeket:

using System;

public class RelOp
{
       static public void Main()
       {
               bool l = true;
               bool k = false;
               if(l == true && k == false)
               {
                       Console.WriteLine("Igaz");
               }
              
               Console.ReadKey();
       }
}

Először felvettünk két logikai (bool) változót, az elsőnek „igaz” a másodiknak „hamis” értéket adtunk. Ezután egy elágazás következik, erről bővebben egy későbbi fejezetben lehet olvasni, a lényege az, hogy ha a feltétel igaz, akkor végrehajt egy bizonyos utasítás(oka)t. A fenti példában az „és” (&&) operátort használtuk, ez két operandust vár és akkor ad vissza „igaz” értéket, ha mindkét operandusa „igaz” vagy nullánál nagyobb értéket képvisel. Ebből következik az is, hogy akár az előzö fejezetben megismert relációs operátorokból felépített kifejezések, vagy matematikai formulák is lehetnek operandusok. A program maga kiírja, hogy „Igaz”. Nézzük az „és” igazságtáblázatát:

A B Eredmény
hamis hamis hamis
hamis igaz hamis
igaz hamis hamis
igaz igaz igaz

A második operátor a „vagy”:

using System;

public class RelOp
{
       static public void Main()
       {
               bool l = true;
               bool k = false;
              
               if(l == true || k == true)
               {
                       Console.WriteLine("Igaz");
               }
              
               Console.ReadKey();
       }
}

A „vagy” (||) operátor akkor térít vissza „igaz” értéket, ha az operandusai közül valamelyik „igaz” vagy nagyobb mint nulla. Ez a program is ugyanazt csinálja, mint az előző, a különbség a feltételben van, „k” biztosan nem „igaz” (hiszen épp előtte kapott „hamis” értéket).

A „vagy” igazságtáblázata:

A B Eredmény
hamis hamis hamis
hamis igaz igaz
igaz hamis igaz
igaz igaz igaz

Az eredmény kiértékelése az ún. „lusta kiértékelés” (vagy „rövidzár”) módszerével történik, azaz a program csak addig vizsgálja a feltételt amíg muszáj. Pl. a „vagy” példában a „k” soha nem fog kiértékelődni, mivel „l” van az első helyen (balról jobbra haladunk) és ő „igaz”, vagyis a feltétel „k” értékétől függetlenül mindenképpen teljesül.

A harmadik a „tagadás” (!()):

using System;

public class RelOp
{
       static public void Main()
       {
               int x = 10;
               
               if(!(x == 11))
               {
                       Console.WriteLine("X nem egyenlo 11-gyel!");
               }
              
               Console.ReadKey();
       }
}

Ennek az operátornak egy operandusa van, akkor ad vissza igaz értéket, ha az operandusban megfogalmazott feltétel hamis vagy egyenlő nullával. A „tagadás” (negáció) igazságtáblája (Női logika):

A Eredmény
hamis igaz
igaz hamis

Ez a három operátor ún. feltételes operátor, közölük az „és” és „vagy” operátoroknak létezik a „csonkolt” logikai párja is. A különbség annyi, hogy a logikai operátorok az eredménytől függetlenül kiértékelik a teljes kifejezést, nem élnek a „lusta” kiértékeléssel. A logikai „vagy” művelet:

if(l == true | k == true)
{
         Console.WriteLine("Igaz");
}

A logikai „és”:

if(l == true & k == true)
{
        Console.WriteLine("Igaz");
}

A logikai operátorok családjához tartozik (ha nem is szorosan) a feltételes operátor. Ez az egyetlen háromoperandusu operátor, a következőképpen működik:

feltétel ? igaz-ág : hamis-ág;

using System;

public class RelOp
{
       static public void Main()
       {
               int x = 10;
               int y = 10;
              
               Console.WriteLine( (x == y) ? "Egyenlo" : "Nem egyenlo");
              
               Console.ReadKey();
       }
}

Bit operátorok[szerkesztés]

Az előző fejezetben említett logikai operátorok bitenkénti műveletek elvégzésére is alkalmasak numerikus típusokon. A számítógép az adatokat kettes számrendszer –beli alakban tárolja, így pl. ha van egy byte típusú változónk (ami egy byte azaz 8 bit hosszú) aminek a „2” értéket adjuk, akkor az a következőképpen jelenik meg a memóriában:

2 -> 00000010

A bit operátorok ezzel a formával dolgoznak. Az eddig megismert kettő mellé még jön négy másik operátor is. A műveletek:

Bitenkénti „és”: veszi a két operandus bináris alakját és a megfelelő bitpárokon elvégzi az „és” műveletet azaz ha mindkét bit 1 állásban van akkor az adott helyen az eredményben is az lesz, egyébként 0:

01101101
00010001 AND
00000001

Példa:

using System;

class Program
{
       static public void Main()
       {
               int x = 10;
               Console.WriteLine(x & 2);
               //1010 & 0010 = 0010 = 2
               Console.ReadKey();
       }
}

Bitenkénti „vagy”: hasonlóan működik mint az „és”, de a végeredményben egy bit értéke akkor lesz 1, ha a két operandus adott bitje közül az egyik is az:

01101101
00010001 OR
01111101
using System;

class Program
{
       static public void Main()
       {
               int x = 10;
               Console.WriteLine(x | 2);
               //1010 | 0010 = 1010 = 10
               Console.ReadKey();
       }
}

Biteltolás balra: a kettes számrendszerbeli alak „felső” bitjét eltoljuk és a jobb oldalon keletkező üres bitet nullára állítjuk. Az operátor: <<:

10001111 LEFT SHIFT
100011110
using System;

class Program
{
       static public void Main()
       {
               int x = 143;
               Console.WriteLine(x << 1);
               //10001111 (=143) << 1 = 100011110 = 286
               Console.ReadKey();
       }
}

Biteltolás jobbra: most az alsó bitet toljuk el és felül pótoljuk a hiányt. Az operátor: >>:

using System;

class Program
{
       static public void Main()
       {
               int x = 143;
               Console.WriteLine(x >> 1);
               Console.ReadKey();
       }
}

Rövid forma[szerkesztés]

Vegyük a következő példát:

x = x + 10;

Az x nevű változót megnöveltük tízzel. Csakhogy van egy kis baj: ez a megoldás nem túl hatékony. Mi történik valójában? Elsőként értelmezni kell a jobb oldalt, azaz ki kell értékelni x –et, hozzá kell adni tízet és eltárolni a veremben. Ezután ismét kiértékeljük x –et, ezúttal a bal oldalon. Szerencsére van megoldás, mégpedig az ún. rövid forma. A fenti sorból ez lesz:

x += 10;

Rövidebb, szebb és hatékonyabb. Az összes aritmetikai operátornak létezik rövid formája.

A probléma ugyanaz, de a megoldás más a következő esetben:

x = x + 1;

Szemmel láthatóan ugyanaz a baj, azonban az eggyel való növelésre-csökkentésre van önálló operátorunk:

++x/--x;
x++/x--;

Ebből az operátorból rögtön két verziót is kapunk, prefixes (++/-- elől) és postfixes formát. A prefixes alak pontosan azt teszi amit elvárunk tőle, azaz megnöveli(csökkenti) az operandusát egyel. A postfixes forma egy kicsit bonyolultabb, elsőként létrehoz egy átmeneti változót, amiben eltárolja az operandusa értékét, majd megnöveli eggyel az operandust, végül visszaadja az átmeneti változót. Ez elsőre talán nem tűnik hasznosnak, de vannak helyzetek amikor lényegesen megkönnyíti az életünket a használa. Attól függően, hogy növeljük vagy csökkentjük az operandust inkrementális illetve dekrementáló operátorról beszélünk.

Egyéb operátorok[szerkesztés]

Unáris -/+: az adott szám pozitív illetve negatív értékét jelezzük vele. Csakis előjeles típusokon működik.

Typeof: az operandusa típusát adja vissza:

using System;

class Program
{
       static public void Main()
       {
               int x = 143;
               if(typeof(int) == x.GetType())
               {
                       Console.WriteLine("X tipusa int");
               }
               Console.ReadKey();
       }
}

A változón meghívott GetType() metódus (amit mellesleg minden típus a System.Object –től örököl) a változó típusát adja vissza.