Fájlok írása Pytonban!
Elkészült a Python nyelv Szövegfájlok írása tananyagunk! Jó tanulást, jó gyakorlást!

<info9>

Eljárások és függvények

A programozásban általában arra törekszünk, hogy minden kódrészletet csak egyszer kelljen megírnunk egy projektben. Ez azért is hasznos, mert így ha az adatok tárolása, vagy a program funkcionalitása módosul, csak egy helyen kell a szükséges módosításokat végrehajtanunk. Ahhoz pedig, hogy kódrészleteket újra tudjunk hasznosítani a programunk különféle részein, általában eljárásokat, és függvényeket alkalmazunk.

Eljárások

Az újrahasznosítható kódrészletek legegyszerűbb formája az eljárás: egy olyan kódrészlet, ami végrehajt bizonyos utasításokat, azonban nincs visszatérési értéke, azaz nincs "végeredménye", amit utána visszaad az őt elindító kódrészletnek. Ezt a tényt a void kulcsszóval tudjuk jelölni a kódunkban az eljárás létrehozásakor.

Az eljárások definiálásakor a void kulcsszót használjuk, ez után kell megadnunk az eljárás nevét - erre a változók nevére vonatkozó szabályok élnek, azaz csak betűvel, vagy aláhúzás jellel kezdődhet, és tartalmazhat kisbetűt, nagybetűt, aláhúzást, és számokat is. Az eljárás neve után kerek zárójelek között adhatjuk meg, hogy legyenek-e paraméterei az eljárásnak – de fontos, hogy a kerekzárójel nem hagyható el akkor sem, ha nincsenek paraméterek! Ezt követően pedig kapcsos zárójelek között megírhatjuk az eljárás kódját.

Tipp: ha egy konzolalkalmazás Program osztályában szeretnél új eljárást készíteni, a static kulcsszót is használnod kell! Ennek okáról az Osztályok fejezetben olvashatsz részletesebben.

static void sziaVilag()
{
    Console.WriteLine("Hello World!");
}

Később, ha a kódunkban fel szeretnénk használni az eljárást, elég a nevével hivatkoznunk rá:

// Írjuk ki, hogy Hello World
sziaVilag();

Paraméterek

A paraméterek lehetővé teszik, hogy bizonyos értékeket átadjunk egy-egy eljárás, vagy függvény számára, amik utána ezeket felhasználhatják számolásokhoz, vagy bármi egyéb művelethez. Ez lehetőséget ad arra, hogy egy-egy komplexebb feladatot is megvalósítsunk eljárások formájában – például az alábbi kódrészletben egy olyan eljárást készítünk, ami egy téglalap jellemzését készíti el, két oldal hosszúsága alapján. Ehhez két darab, int típusú paramétert használunk – ezeket a zárójelen belül soroljuk fel, és ezeket az itt megadott névvel, változókként érjük el az eljáráson belül.

static void teglalap(int a, int b)
{
    Console.WriteLine("A téglalap oldalai a={0} és b={1} hosszúságúak.",a,b);
    Console.WriteLine("A téglalap kerülete: {0}",a+a+b+b);
    Console.WriteLine("A téglalap területe:  {0}",a*b);
    if(a==b)    {
        Console.WriteLine("A téglalap egy NÉGYZET.");
    }
}

Ezt az eljárást utána több különféle paraméterezéssel is fel tudjuk majd használni a kódunkban, például így:

Utasítás Kimenet
teglalap(1,5);
A téglalap oldalai a=1 és b=5 hosszúságúak.
A téglalap kerülete: 12
A téglalap területe: 5
teglalap(5,1);
A téglalap oldalai a=5 és b=1 hosszúságúak.
A téglalap kerülete: 12
A téglalap területe: 5
teglalap(4,4);
A téglalap oldalai a=4 és b=4 hosszúságúak.
A téglalap kerülete: 16
A téglalap területe: 16
A téglalap egy NÉGYZET.

Függvények

Webtárhely, 5% kedvezménnyel!

Most, hogy belevágtál a programozásba, jól jönne egy olcsó webtárhely? A SzerverPlex kedvező árú cPanel tárhelyeit most 5% kedvezménnyel igénybeveheted, és ezzel az info9 fennmaradását is támogatod.

Kattints a gombra, majd a csomag kiválasztása után aktiváld az INFO9 kuponkódot a fizetés előtt.

Szerzek webtárhelyet!

Gyakran fordul elő olyan eset is, hogy olyan újrahasznosítható kódrészletre van szükségünk, ami valamilyen számolást, eldöntést, stb. végez, aminek az eredményét utána tovább szeretnénk használni. Ezekben az esetekben eljárások helyett függvényeket használunk – ezek felépítésüket tekintve megegyeznek az eljárásokkal, azonban valamilyen értéket visszaadnak az őket meghívó kódrészletnek, így alkalmasok résszámítások, vagy egyéb részfeladatok hatékony megvalósítására.

Függvény készítésekor a void kulcsszó helyére a függvény által visszaadandó érték adattípusát kell megadnunk. Az eredményt pedig a return kulcsszó segítségével fogjuk tudni visszaadni – nézzünk egy példát egy függvényre, ami megadja egy szám osztóinak a számát:

static int osztokSzama(int szam)
{
    int osztok = 0;
    for(int i=1;i<=szam;++i)
    {
        if(szam % i == 0)
        {
            osztok = osztok + 1;
        }
    }
    return osztok;
}

Most pedig használjuk ezt fel egy apró program elkészítéséhez, amiben bekérünk egy számot a felhasználótól, és eldöntjük, hogy az adott szám egy prím szám-e.

Console.Write("Írj be egy számot: ");
int bekert = Convert.ToInt32(Console.ReadLine());

if(osztokSzama(bekert)==2)
{
    Console.WriteLine("Ez a szám prím.");
}
else
{
    Console.WriteLine("Ez a szám nem prím.");
}

Több eljárás/függvény azonos néven

Egyes nyelvekben, többek között a C# nyelvben is, létrehozhatunk több eljárást, vagy függvényt megegyező néven, egészen addig, ameddig ezek eltérő számú, vagy típusú paramétereket használnak, azaz eltérő az ún. aláírásuk. A függvény/eljárás aláírása annak a nevéből, valamint a paraméterek számából, sorrendjéből, és adattípusaiból áll. Fontos, hogy a paraméterek neve nem része a függvény/eljárás aláírásának! Nézzünk néhány példát:

Függvény/eljárás definíciójaAláírás
int terulet(int a, int b) terulet(int, int)
int terulet(int b, int a) terulet(int, int)
int terulet(int a, bool negyzet) terulet(int, bool)
int terulet(int a) terulet(int)
int terulet(string a, int b) terulet(string, int)

Mivel azonos nevű függvényeket csak akkor hozhatunk létre, ha ezek aláírása eltérő, így láthatjuk, hogy a táblázatból az első és a második függvény például nem hozható létre egyszerre egy osztályon belül, azonban az első és a harmadik például igen. Ebben az esetben a C# az átadott paraméterek száma, illetve adattípusa alapján tudja kiválasztani, hogy melyik függvény/eljárás fog lefutni.

Ha például az előző táblázatból a második kivételével az összes többi eljárást elkészítjük, akkor…

Láthatjuk tehát, hogy ezért fontos az aláírások eltérősége: ez alapján tudja a fordító egyértelműen kiválasztani a megfelelő függvényt egy adott híváskor.

A return művészete

Mint fentebb láthattuk, a return utasítást függvények esetében a visszatérési érték visszaadására tudjuk használni – érdemes azonban megemlítenünk a return egyéb lehetséges felhasználásait.

A ciklusoktól talán már ismerős break kulcsszóhoz hasonlóan a return utasítás is azonnal "elvágja" az adott eljárás, vagy függvény futását. Ez tehát azt jelenti, hogy ha a kód eljut egy return utasításig, akkor az utána található kódrészlet nem fog már lefutni. Ezt egyes esetekben felhasználhatjuk például eldöntési feladatok leegyszerűsítésére, vagy else ágak elhagyására:

static bool negyzetE(int a, int b)
{
    if(a==b)
    {
        return true;
    }
    return false;
}

Ez a kódrészlet pl. tökéletesen működik, mert ha az első return utasítás lefut, az utána lévő utasításig a kód el sem jut már, így az egy else-hez hasonlóan viselkedik. Érdekesség, hogy a return kulcsszót önmagában felhasználhatjuk eljárásokban is a kód futásának leállítására:

static void fizetes(int haviFiz, int honapokSzama)
{
    if(haviFiz < 1 || honapokSzama < 1)
    {
        Console.WriteLine("Hiba");
        return;
    }
    Console.WriteLine(haviFiz * honapokSzama);
}

Ebben a kódban pl. a hibaüzenet kiírása után a return kulcsszó megállítja az eljárást, így a hibás számérték már nem kerül megjelenítésre.

Biztonságos kód

A függvényeknek minden esetben, bármilyen (megfelelő adattípusú) bemeneti érték esetén kell, hogy visszaadjanak értéket. Amennyiben ez nem teljesük, úgy a fejlesztő környezetünk hibát jelez, miszerint a kódunknak nem minden része ad visszatérési értéket. Ez a hiba azonban időnként akkor is előfordul, ha mi biztosak vagyunk abban, hogy egy adott kódrészlet garantáltan fog visszaadni valamit.

Ilyen leggyakrabban akkor fordul elő, ha a return utasítás egy olyan ciklusban, elágazásban, vagy egyéb bonyolultabb vezérlési szerkezetben van elrejtve, ahol mi az adatok ismeretében tudjuk, hogy le fog futni, de a fordító nem tudja 100%-os bizonyossággal "megjósolni" azt, hogy ne létezhetne olyan eset, amikor a kód nem jut el a returnig (mert pl. az if feltétele sosem lesz igaz, vagy mert a ciklus nem fut le egyszer sem). Az egyszerűbb if-else helyzeteket általában megérti a fordító, a bonyolultabb szerkezeteknél azonban ilyen figyelmeztetések időnként ok nélkül is előfordulnak.

Ez esetben a legegyszerűbb, ha a függvény végére elhelyezünk egy return utasítást, ami visszaad egy valami alapértelmezett értéket. Így a fordítónk is boldog lesz, és ha nekünk is igazunk volt, és a kód tényleg sosem jut el idáig, akkor az érték miléte miatt sincs okunk aggódni.

Másik lehetőség, hogy a VS beállításaiban, vagy ha kézzel/parancssorból fordítjuk a kódot, akkor az MSBuild-nek egy plusz parancssori paraméterrel beállítjuk, hogy engedélyezze a nem biztonságos kódok fordítását – ezt a megoldást azonban csak akkor érdemes alkalmaznunk, ha a programot biztosan csak mi magunk, fogjuk lefordítani, mert ha a kódot megosztjuk másokkal, és náluk ez a beállítás nincs megfelelően módosítva, ők fordítási hibát kaphatnak.