Tartalomjegyzék

< CSharp

A C# nyelv

A C# nyelvről

Bevezetés

A C# nyelv egy objektumorientált programozási nyelv. Angolos kiejtése szí-sárp. A nyelvet először MS valósította meg a .Net keretrendszeren belül.

A .Net keretrendszer teljes értékű szabad szoftveres alternatívája a Mono. A Monot eredetileg a Ximian nevű cég hozta létre, amelyet felvásárolt a Novell. A Mono tehát most a Novell kezelésében áll. A Mono rendszer telepíthető a Linux, Mac OS X és Windows operációs rendszerekre.

A C# nyelv szigorúan osztályok halmaza, kis és nagybetű érzékeny, minden utasítást pontosvesszővel zárunk.

Fogalmak

Kezelt kód

Managed code

A C# forráskód lefordítása után kapjuk. Ez egy közbenső nyelv, amely az alacsony szintű gépi kód és a magas szintű C# kód között van. A közbenső nyelvet hívjuk angolosan: intermediate language (IL, CIL, MSIL). A Java bájtkódjának feleltethető meg.

CLR

Közös nyelvű futási idejű környezet

Common Language Runtime

Ebben a környezetben értelmezi a kezelt kódot futási időben a JIT (Just-in-time) fordító, alacsony szintű gépi kódként.

Garbage collector GC

Szemétgyűjtő. Felszabadítja helyettünk a nem használt memóriaterületeket.

Gyakorlat

  1. Mi az a kezelt kód?
  2. Telepíthető-e a Mono rendszer Solaris operációs rendszerre?
  3. Ki fejlesztette ki a .Net keretrendszert?
  4. Hogyan nevezik angolul a Közös nyelvű futási idejű környezetet?
  5. Nyílt forrású-e a Mono rendszer?
  6. Mire jó a Garbage collector?

Első program

Helló Világ nevű program

Egy szövegszerkesztő programmal készítsd el a következő állományt, az alábbi tartalommal:

Az állomány mentése után a fordítsuk le a forráskódot, futtatható állománnyá.

Program01.cs
using System;
 
class Program01
{
   static void Main()
   {
       Console.WriteLine("Helló Világ!");
   }
}

Fordítás Windows alatt:

csc Program01.cs

Fordítás Linux alatt 3.x monoval:

gmcs Program01.cs

Fordítás Linux alatt 4.x monoval:

dmcs Program01.cs

A program ami kiírja a Helló Világ! feliratot.

A program megírható, fordítható például Visual 2010 C# Express fejlesztői környezetben is. Ha parancssorból fordítunk, akkor ügyeljünk arra, hogy a csc fordítónak útvonalban kell lenni, vagy fordításkor meg kell adnunk az egész elérési útvonalát, ami nem kényelmes.

Linux operációs rendszer alatt a gmcs vagy a dmcs fordítót kell használnunk, amely a Mono keretrendszer része. 2013-ban a LinuxMint rendszereken már telepíthető a mono-dmcs csomag, amely Mono 4.x verzióját tartalmazza. Minimum ennek a csomagnak a használata ajánlott.

Elemzés

Létrehoztunk egy Program01 nevű osztályt és abban egy Main metódust. A nyelvben az osztály használata kötelező. A kiinduló osztályunk neve tetszőleges. Egy egyszerű konzolos program esetén a kiinduló osztályunknak van egy kötelező metódusa ez a „Main”. A program végrehajtása ezzel kezdődik.

A példaprogramból látszik, hogy a System névtérben lévő osztályokat szeretnénk használni. Létrehoztunk egy prog nevű osztályt, amelynek egyetlen metódusa van a „Main”. A Main metódus egyetlen utasítást tartalmaz, amely kiírja a „Helló Világ!” szöveget.

Ha „using System;” sort ha nem használjuk, akkor az utasítást a névtér megadásával kell kezdenünk:

Program01.cs
class Program01
{
   static void Main()
   {
       System.Console.WriteLine("Helló Világ!");
   }
}

A példában az utasítást a „System” kulcsszóval kezdjük, amellyel jelezzük, hogy a Console osztály ebben a névtérben van.

Gyakorlat

  1. Mit csinál a System.Console.WriteLine(„H”); utasítás?
  2. Milyen parancsot használunk a fordításhoz, ha Mono keretrendszert használunk?
  3. Milyen parancsot használunk a fordításhoz, ha .Net keretrendszert használunk?
  4. Kötelező a C# nyelvben az osztály használata?
  5. Írjon programot, amely saját névjegyét írja a képernyőre (Név, Cím, Telefonszám, e-mail cím, webcím, munkakör)
  6. Milyen névteret használtunk eddig.

Névterek

A programok névterekbe szervezhetők. Ilyenkor egyetlen névtérbe több osztályt helyezünk el. Egyes fejlesztői programok sablonjaiban azonnal névtérben jön létre az osztály, de mint láttuk ez nem kötelező. A fenti program névtérrel:

Program01.cs
using System;
 
namespace Nagyegyseg {
	class Program01 {
		static void Main() {
			Console.WriteLine("Helló Világ!");
		}
	}
}

Kivitel

A System névtéren belül, a Console osztály WriteLine() metódusa a paraméterként megadott kifejezés értékét írja a képernyőre, majd egy sortörést:

Program01.cs
class Program01
{
   static void Main()
   {
       System.Console.WriteLine("abc");
   }
}

A fenti példában egy karaktersorozat állandót küldünk a képernyőre és utána sortörés.

A szimpla Write() metódus sortörés nélkül ír a képernyőre:

Program01.cs
class Program01
{
   static void Main()
   {
       System.Console.Write("abc");
   }
}

Escape szekvenciák

Literálok

Ha több karaktert akarunk a képernyőre íratni, fentebb láttuk, hogy a karaktereket egyszerűen idézőjelek között felsorolom, mint azt az alábbi program is szemlélteti.

Program01.cs
class Program01
{
   static void Main()
   {
       System.Console.WriteLine("abc");
   }
}

Az idézőjelek helyett tehetünk egyszerű aposztrófokat, így azonban csak egy darab karaktert írhatunk közéjük.

Program01.cs
class prog
{
   static void Main()
   {
       System.Console.WriteLine('a');
   }
}

Ha számokat szeretnénk kiíratni, akkor nem szükséges se aposztróf, se idézőjel.

kiszam.cs
class Program
{
   static void Main()
   {
       System.Console.WriteLine(3);
   }
}

Amikor megadok egy számot, karaktert vagy egy karaktersorozatot ezeket állandóknak hívom. Azért állandó, mert ilyen formában a forráskódba írva, a program további részében az nem változtatható meg. Nem is akármilyen állandóknak, „literális” állandóknak hívjuk őket. Hogy egy állandó literális, annyit jelent, hogy nincs neve, „az ami”.

Literális állandó példák:

35
'a'
"abc"

Helyettesítő karakter

Helyettesítő karakterek vagy Escape sorozatok. Néhány karakternek speciális jelentése is lehet az eredeti szerepe helyett. Ilyen például az „a” karakter. Karaktersorozatban, vagy egy önálló karakterként kiíratva, szimplán megjelenik a képernyőn. Néha lehet azonban más jelentése is. Ha más jelentéssel kívánjuk használni azt valamilyen módon jelezni kell. Erre szolgál a visszaperjel. Ha egy karakterállandóban visszaperjel következik, ezzel jelezzük hogy a következő karakter speciális értelmezésű. A „\a” például megszólaltatja a beépített hangszórót.

Hajtsuk végre például a következő programot:

Program01.cs
using System;
class Program01
{
   static void Main()
   {
       Console.WriteLine("\a");
   }
}

Vagy az új sor karakter használata:

Program01.cs
using System;
class prog
{
   static void Main()
   {
       Console.WriteLine("Első sor\nMásodik sor");
   }
}

Vegyük észre hogy az idézőjel a karakter sorozatok kezdését és befejezését jelzi. Így annak kiíratása is problémás lenne escape szekvenciák nélkül:

idezojel.cs
using System;
class prog
{
   static void Main()
   {
       Console.WriteLine("\"idézet\"");
   }
}

Az alábbi táblázatban láthatod néhány karakter speciális értelmezését.

Escape szekvencia Jelentés
\a Csengőhang
\f Lapdobás
\n Új sor
\r Kocsi vissza
\t Vízszintes tabulátor
\v Függőleges tabulátor
\' Aposztróf
\„ Idézőjel
\\ Visszaperjel
\? Literális kérdőjel
\ ooo ASCII karakter oktális jelölése
\x hh ASCII karakter hexadecimális jelölés
\x hhhh Unicode jelölés

Gyakorlat

  1. Mi a literális állandó.
  2. Mondjon példát két escape szekvenciára.
  3. Hogyan íratunk escape szekvenciával sortörést?
  4. Hogyan mondjuk meg C# nyelven, hogy a következő karakter escape szekvenciaként lesz értelmezve?
  5. Írjon programot, amely a következőt írja a képernyőre, egyetlen utasítással:
Petőfi „Még nyílnak a völgyben”
kezdetű verse

Változók, állandók és a típusok

Változó

Általában szeretnénk adatokat eltárolni a programírás során. Ezt a memóriában tehetjük meg. A memória egy helyét elnevezem, majd elhelyezek egy értéket az adott helyen. Egy programban mi ennek a memóriahelynek csak a nevével találkozunk és változónak hívjuk. Változónak, mert az adott memóriahely tartalmát lecserélhetem.

A változókban többféle típusú értéket tárolhatunk. Lehetnek egész vagy valós számok, karakterek, karaktersorozatok.

A C# nyelv típusos nyelv, a változókat használatuk előtt deklarálni kell, ahol megadjuk milyen típusú értéket kívánunk tárolni az adott változóban.

valtozok.cs
using System;
class Prog
{
    static void Main()
    {
        int a = 3;
        int b = 4;
        int c;
 
        c = a + b;
 
        Console.Write("Összeg: " + c);
 
    }  
}

A C# nyelvben a változók deklarációja a típus megadásával kezdődik. Ezt követi a változó neve.

Típus változónév;

A változó első karaktere csak betű vagy alulvonás jel (_) lehet. A név többi részében szám is szerepelhet. A C# megengedi az ékezetek használatát is, ezt azonban kerüljük.

A változónak rögtön kezdőértéket is adhatunk. Az érték adás egy darab egyenlőség jellel történik.

A C# típusai

A C#-ban a következő típusokat imserjük:

Mi most csak az értéktípusokkal foglalkozunk. Az érték típusok lehetnek egyszerűek és összetettek:

Egyszerű értéktípusok

Típusok
C# kulcsszó .Net típus Tartomány Mérete (byte)
sbyte SByte -128 .. 127 1
byte Byte 0 .. 255 1
short Int16 -32768 .. 32767 2
ushort UInt16 0 .. 65535 2
int Int32 -2147483648 .. 2147483647 4
uint UInt32 0 .. 4294967295 4
long Int64 -263 .. 263-1 8
ulong UInt64 0 .. 264-1 8
float Single ±1.5E-45 .. ±3.4E38 4
double Double ±5E-324 .. ±1.7E308 8
decimal Decimal ±1E-28 .. ±7.9E28 (128 Bit) 16
bool Boolean true, false 1
char Char Unicode karakter 2
string String Unicode karaktersorozat

A bool típusban eltárolhatjuk logikai kifejezések eredményét. Legyen például a következő programrész:

int a = 3;
bool b = a > 5;

Az „a > 5” kifejezése értéke hamis, így a b változóban a „false” érték lesz eltárolva. A bool típusú változóknak ennél több haszna van. Egy if()-ben megvizsgálhatjuk az értékét:

int a = 3;
bool b = a > 5;
if(b)
  Console.WriteLine("Nagyobb 5-nél");
else
  Console.WriteLine("Kisebb vagy egyenlő 5-tel");

A vizsgálat működött volna a „b == true” formában is, de felesleges kiírni a teljes kifejezést.

A decimal típusban kisebb értékintervallum tárolható a float típushoz képest, de nagyobb pontossággal tudunk vele számolni. 28-29 értékes jeggyel számolhatunk. Ha egy lebegőpontos típust (float, double) átalakítunk az elvesző pontosság miatt visszaalakítva már nem lesz egyenlő önmagával. Ekkor használhatjuk a deciaml típust. Pénzügyi számításoknál hasznos lehet.

Ha állandóként szeretnénk decimálist típussal dolgozni, akkor egy „m” karaktert kell a szám végére tenni:

decimal penz = 300.5m;

Az egész állandók automatikusan decimalként vannak értelmezve, tört számok esetén használhatjuk az „m” vagy „M” utótagot.

Összetett típusok

Az összetett típusokat a felhasználók definiálják

Természetesen használhatunk sztringeket és tömböket is, de azok nem típusként vannak deklarálva, hanem osztályként.

enum
enum.cs
using System;
class Program
{
    enum MunkaNapok  {Hetfő, Kedd, Szerda, Csütörtök, Péntek};
    static void Main()
    {
        Console.WriteLine(MunkaNapok.Hetfő);
    }
}
struct

A struct szerkezetet különböző típusú értékek tárolására találták ki. A létrehozása metóduson kívül engedélyezett. A metódusban mint egy típust használhatjuk fel.

struct.cs
using System;
 
class Program
{
    struct Pelda
    {
        public string Nev;
        public int Kor;
    }
    static void Main()
    {
        Pelda Joska;
        Joska.Nev = "Nagy József";
        Joska.Kor = 35;
        Console.WriteLine(Joska.Nev);
        Console.WriteLine(Joska.Kor);
    }
}

Példa az osztályhoz hasonló használatra:

struct2.cs
using System;
 
class Program
{
    struct Pelda
    {
        string Nev;
        public int Kor;
        public string lekerNev()
        {
            return Nev;
        }
        public void beallitNev(string atvettNev)
        {
            Nev = atvettNev;
        }
    }
    static void Main()
    {
        Pelda Joska = new Pelda();
        Joska.beallitNev("Nagy József");
        Joska.Kor = 35;
        Console.WriteLine(Joska.lekerNev());
        Console.WriteLine(Joska.Kor);
    }
}

Állandók

Ha már változókról beszélünk, beszélhetünk állandókról is. Az állandókkal a foglalkoztunk már az Escape szekvenciák kapcsán. Ott megtanultuk, hogy ha csak úgy leírok egy számot, karaktert vagy karaktersorozatot akkor az egy literális állandó. Azért is tettük a literális jelzőt az állandó elé, mert nem csak literális állandók vannak. Az állandók két félék lehetnek:

A literális állandókról tehát már volt szó, de mi a nevesített állandó? Természetesen az amikor egy állandónak nevet adunk. Egy állandó nevének meghatározása hasonló, mint a változóé. Az állandó neve előtt megadjuk annak típusát és a típus előtt egy „const” módosítót írok:

const int a = 10;

A példában az „a” állandót deklaráljuk. Amikor használom a const módosítót, akkor tulajdonképpen azt vállalom (mint programozó), hogy az „a” értékét a program további részében sosem változtatom meg. Erre persze a fordító sem ad lehetőséget.

A változókkal ellentétben az állandók számára azonnal kötelező kezdőértéket megadni.

Az alábbiakban egy rossz példát látunk:

De új értéket sem adhatunk:

Azonosítók

Mint láttuk az általunk létrehozott változók és állandók számára valamilyen nevet, azaz azonosítót kell megadnunk. Van a C# nyelven 77 kulcsszó, amelyet nem használhatunk azonosító létrehozására, mert azt maga a nyelv használja. Szokás ezeket foglalt szavak néven is emlegetni.

Foglalt szavak

Gyakorlat

  1. Írja le, hogyan deklarál egy valós típusú változót, amelynek neve: „homerseklet”.
  2. Írja le, hogyan deklarál egy dupla-pontosságú változót, amelynek neve „oszto”.
  3. Milyen állandók vannak?
  4. A változó deklarálásánál hova tesszük a típust, a változó neve után vagy elé?
  5. Írjon példát a literális állanódra!
  6. Mik azok a foglalt szavak?

Operátorok

Aritmetikai operátorok

* szorzás
/ osztás
% maradkék képzés
+ összeadás
- kivonás

Általános

. mező- vagy metódus-hozzáférés Console.WriteLine()
() zárójel (a + b) * 2
[] tömbindex tomb[0]
++ inkrementáló utasítás szam++
-- dekrementáló szam--
new Helyet foglalunk egy objektumnak Object objektum = new Object();
typeof() típusmeghatározó operátor Type tipus = typeof(int); Console.WriteLine(tipus.Name);
sizeof() méretmeghatározó int meret = sizeof(long)
checked() túlcsordulás ellenőrzés checked(a * b)
unchecked() túlcsordulás ellenőrzés mellőzése unchecked(a * b)

Ha a checked() operátort használjuk és túlcsordulás történik a következő hibaüzenet kapjuk:

"The operation overflows at compile time in checked mode"

Például:

Console.WriteLine(checked(50000 * 50000));

De unchecked() operátort használva, nem kapunk hibaüzenetet.

Console.WriteLine(unchecked(50000 * 50000));

Egyoperandusú operátorok

+ pozitív szám
- negatív szám
! negálás, ellentétbe fordítás
~ egyes komplemens képzés
(típus)x kasztolás
true igaz
false hamis
& egy objektum címét adja vissza
sizeof() típus mérete

Írjunk programot például, amely egy „a” nevű logikai változót deklarál, adjuk kezdőértéknek „true”-t, majd kiíratásnál fordítsuk meg az értékét:

bool a = true;		
Console.WriteLine(!a);

A fenti operátorok közül talán a kasztolás a legérdekesebb. Tulajdonképpen típuskonverzióról van szó. Adott például egy egész szám, amit valóssá szeretnénk alakítani, ez problémamentesen megtehető így:

int a = 3;
double b = a;

Ha azonban fordítva szeretnénk, a valós számot akarjuk egésszé alakítani hibaüzenetet kapunk. Ezért kasztolnunk kell:

double a = 3.5;
int b = (int) a;

Az „a” változó tartalmát „b” változóba szeretnénk konvertálni, ezért az „a” változó elé zárójelbe megjegyzem, milyen típusúvá szeretnénk átkonvertálni. Ezt nevezzük kasztolásnak.

A táblázatból lássuk a sizeof() operátort. Egy típus méretét tudjuk megnézni vele. Eredményül megkapjuk hány bájton tárolódik az adott típus. Lássuk hány byton tárolja értékeit például az int:

Console.WriteLine(sizeof(int));

Logikai operátorok

^ Logikai XOR
& Logikai AND
| Logikai OR
int a = 3;
int b = 5;
int c = a ^ b;
Console.WriteLine(c); //6

Feltételes operátorok

&& Feltételes AND
|| Feltételes OR
int a = 3;
if(a > 0 && b > 0)
    Console.WriteLine("Pozitív szám");
else
    Console.WriteLine("Nulla vagy negatív");

Összerendelő operátorok

= legyen egyenlő
+= a = a + b
-= a = a - b
*= a = a * b
/= a = a / b
%= a = a % b
&= a = a & b
|= a = a | b
^= a = a ^ b
«= a = a « b
»= a = a » b
?? Ha b null, akkor -1 lesz a (a = b ?? -1)

Gyakorlat

  1. Melyik operátorral negálunk?
  2. Melyik operátorral képezzük egy szám egyes komplemensét?
  3. Melyik operátorral kérjük le egy objektum címét?
  4. Hogyan jelezzük egy állítás valós (igaz) létét?
  5. Mi a kasztolás?

Formátumozott kivitel

Egy vagy akár több változónak megadható a kiírás formátuma. A formátum egy karaktersorozat, ami mindig az első paraméter. Az első paraméterben egy változóra vonatkozó formátum karaktersorozat mindig ”{„ nyitó kapcsos zárójellel kezdődik és egy ”}„ záró kapcsos zárójellel záródik. Minimálisan megadandó karakter egy index. Annak a változónak az indexe, amelyet az adott helyen meg akarunk jeleníteni.

Változók indexe

Az alábbi kiíró utasításban az „a” változó indexe 0, a „b” változó indexe 1, mivel az „a” változó előrébb van mint a „b”, az indexelés pedig 0-ától kezdődik.

int a = 3, b = 4;
Console.WriteLine("{0} {1}", a, b);

A kiírás eredménye tehát:

3 4

A hármas, utána egy szóköz, majd ezt követi a 4.

Megtehetem fordítva is. Az első formátum karakter-sorozatban hivatkozom az 1-s indexű változóra, majd a másikban a 0-ás indexű változóra:

int a = 3, b = 4;
Console.WriteLine("{1} {0}", a, b);

A kiírás eredménye ekkor:

4 3

Formátumkarakterek

A formátum karaktersorozatban az indexet követően egy kettőspont után további formátumokat tudok meghatározni egy-egy karakterrel. Az alábbi táblázat ezeket a formátum karaktereket tartalmazza:

Formátum karakter Leírás
C, c Pénzösszeg (currency)
D, d Decimális szám
E, e Tudományos (exponenciális) alak
F, f Fixpontos alak
G, g Általános (general)
N, n Szám (number)
R, r Eredeti alak
X, x Hexadecimális alak

Kiíratás pénznemben

A {0:c} formátum-karaktersorozat például pénznemben írja ki az adott értéket:

Console.WriteLine("Az ár: {0:c}", 23485);  // 23 485 Ft

A Ft persze csak magyar környezetben lesz kiírva. Más nyelvi környezet más pénznemet eredményez.

Kiíratás hexadecimális alakban

Egész számokat hexadecimális formátumban is kiírathatunk:

Console.WriteLine("Hex: {0:x}", 10);  // a

Kiíratás fixpontos alakban

Fixpontos alakban kiíratás:

Console.WriteLine("Fixpontos alak: {0:f}", 10);  // 10,00

A számítástechnikában a magyarban szokásos tizedesvessző helyett tizedes ponttal dolgozunk, de vegyük észre, hogy a kimenet igazodik, a magyar környezethez és a kiíratás tizedesvesszővel történik.

Kiíratás lebegőpontos alakban

Lebegőpontos alak:

Console.WriteLine("Lebegőpontos alak: {0:e}", 10);  //  1,000000e+001

Vezető nullák

Console.WriteLine("Érték: {0:00000}", 85);

Ha a szám kétjegyű mint a példában, akkor a nem létező számjegyek helyén 0-ás karakter fog szerepelni:

00085

Hány helyen legyen ábrázolva

Hány helyen ábrázoljunk egy számjegyet, az eddigiektől eltérően kettőspont helyett vesszővel tagolva adjuk meg:

Console.WriteLine("Érték: {0,10}", 85);     // "        85"
Console.WriteLine("Érték: {0,-10}", 85);    // "85        "

Ha szeretnénk a már ismertetett például vezető nullákat is, akkor azt következő formában tehetjük meg:

Kombinálva a vezető nullákkal:

Console.WriteLine("Érték: {0,10:00000}", 85);  // "     00085"
Console.WriteLine("Érték: {0,-10:00000}", 85); // "00085    "

A megjegyzésben a kiíratás formátumát látjuk. Vegyük észre, hogy a -10 alakban a ”-„ azt jelenti a számot balra igazítjuk.

Alternatív ábrázolás

Megadhatjuk külön a pozitív értékek, külön a negatív értékek és a nullák formátumát:

Console.WriteLine("{0:#;minusz #}", 85);     // "85"
Console.WriteLine("{0:#;minusz #}", -85);     // "minusz 85"
Console.WriteLine("{0:#;minusz #;nulla}", 0);     // "nulla"

Az számok helyett szöveg is megjeleníthető.

Szokásos formátumok

Ezredesenkénti csoportosítás:

Console.WriteLine("{0:+### ### ### ###}", 123456789123);     // "+123 456 789 123"

Telefonszám lehetséges alakja:

Console.WriteLine("{0:##-####-#####}", 1234567891);          // "12-3456-7891"

Tizedes jegyek ábrázolása

Console.WriteLine("{0:#.##}", 55.3242);     // "55.32"

Például két tizedesjegy ábrázolása

Globalizálás

globalizal.cs
using System;
using System.Globalization;
 
class Program
{
    static void Main()
    {
        CultureInfo nezet = CultureInfo.GetCultureInfo("eu-ES");
        Console.WriteLine(string.Format(nemzet, "{0:c}", 85));
 
        Console.ReadKey();
    }
}

Használható nemzetnevek:

Nyelv és nyelvterület

Gyakorlat

  1. Adott a 0,052134334 literális állandó
    1. Írassa ki 20 helyen, jelezve az előjelt.
  2. Az alábbi feladatot egyetlen kiírató utasítással oldja meg:
    1. van három változónk: max, min, atlag
    2. írassuk ki tabulátorral tagolva a min, atlag, max változók értékét
    3. a változók tabulátorral tagolva egyetlen sorban jelenjenek meg
    4. Mind a három változó 10 helyen legyen ábrázolva, 5 tizedejegy pontossággal.

Math osztály

A Math egy matematikai osztály, amely statikus állandókat (konstansokat) és függvényeket (metódusokat) tartalmaz. A függvények trigonometriai, logaritmikus és általánosak.

Nem kell példányosítani, azonnal használható.

Abs()

Math.Abs(x);

X értékének abszolút értékét adja.

PI

A PI nem metódus, helyette egy mező. Mező, mert nem csinál semmit csak egy értéket szolgáltat.

Math.PI

A pi értékét tudjuk kiolvasni ebből a mezőből.

Sin()

eredmeny = Math.Sin(x);

Az x érték szinuszát adja vissza. Az x radiánban értendő. Ha szöget kell szinuszra váltanunk, akkor át kell azt számoljuk radiánba. Például:

radian = szog * Math.PI / 180;
eredmeny = Math.Sin(radian);

Cos()

eredmeny = Math.Cos(x);

Az x érték koszinuszát adja vissza az erdmeny változóban. Az x radiánban értendő.

Tan()

Egy szám tangensét adja vissza.

eredmeny = Math.Tan(x);

Az x érték tangensét adja vissza az eredmeny változóban. Az x radiánban értendő.

Sqrt()

Gyökvonás:

eredmeny = Math.Sqrt(9);

Az eredmeny változóban 3 lesz.

Pow()

Hatványozás:

eredmeny = Math.Pow(3,2);

A három második hatványát adja vissza.

Round()

A legközelebbi egészre kerekít.

Console.WriteLine(Math.Round(3.4));  // "3"
Console.WriteLine(Math.Round(3.5));  // "4"
Console.WriteLine(Math.Round(3.6));  // "4"
Console.WriteLine(Math.Round(3.1237));  // "3,124"

Min()

Két szám közül a kisebbel tér vissza.

Console.WriteLine(Math.Min(3,8)); // "3"

Max()

Két szám közül a nagyobbal tér vissza

Console.WriteLine(Math.Max(3,8)); // "8"

Truncate()

A szám egész részével tér vissza.

Console.WriteLine(Math.Truncate(3.12345)); //"3"

Ceiling()

Kerekítés felfelé

Console.WriteLine(Math.Ceiling(3.1)); //"4"

Floor()

Lefele kerekít.

Console.WriteLine(Math.Floor(3.9)); //"3"

BigMul()

Két nagy szám összeszorzása

int int1 = Int32.MaxValue;
int int2 = Int32.MaxValue;
long longResult;
 
longResult = Math.BigMul(int1, int2);
Console.WriteLine("Számítás két Int32 értékkel:");
Console.WriteLine("{0} * {1} = {2}", int1, int2, longResult);

Kimenet:

Számítás két Int32 értékkel:
2147483647 * 2147483647 = 4611686014132420609

Log()

Egy szám logaritmusával tér vissza

Általánosan:

Log(Double)

A bemenő paraméter egy valós szám.

Console.WriteLine(Math.Log(3.5));  // "1,25276296849537"

Egy szám adott alapú logaritmusa

Általánosan:

Log(Double,Double)

A bemenő paraméter két valós szám. Az első számnak a második számon alapuló logaritmusa.

Console.WriteLine(Math.Log(3.5,1.2));  // "1,25276296849537"

Sign()

Egy szám előjelét adja vissza:

Console.WriteLine(Math.Sign(0));  // "0"
Console.WriteLine(Math.Sign(3));  // "1"
Console.WriteLine(Math.Sign(-3));  // "-1"

Gyakorlat

  1. Írjon programot, amely kiírja 130º koszinuszát.
  2. Írjon programot, amely kiírja 30º szinuszát.
  3. Írjon programot, amely megszorozza pi értékét 150-el, az eredményt írassa ki.
  4. Írjon programot, amely kiszámítja 235 a 46-dik hatványon értéket, majd az eredményt a képernyőre írja.
  5. Írjon programot, amely 529424-nek kiírja a gyökét.
  6. Szükséges-e a Math osztály használatához a példányosítás?

Idő lekérdezése

Idő egyszerűen

using System;
class Program
{
	static void Main()
	{
		Console.WriteLine(DateTime.Now);
	}
}
string ido = DateTime.Now.ToString();
using System;
class Program
{
	static void Main()
	{
		string datum = DateTime.Now.ToString();
		Console.WriteLine(datum);
 
	}
}

Idő formázva

Program.cs
using System;
class Program
{
    static void Main()
    {
 
        DateTime AktIdo = DateTime.Now;
 
        Console.WriteLine("d = {0:d}", AktIdo);
        Console.WriteLine("D = {0:D}", AktIdo);
        Console.WriteLine("f = {0:f}", AktIdo);
        Console.WriteLine("F = {0:F}", AktIdo);
        Console.WriteLine("g = {0:g}", AktIdo);
        Console.WriteLine("G = {0:G}", AktIdo);
        Console.WriteLine("M = {0:M}", AktIdo);
        Console.WriteLine("R = {0:R}", AktIdo);
        Console.WriteLine("s = {0:s}", AktIdo);
        Console.WriteLine("t = {0:t}", AktIdo);
        Console.WriteLine("T = {0:T}", AktIdo);
        Console.WriteLine("u = {0:u}", AktIdo);
        Console.WriteLine("U = {0:U}", AktIdo);
        Console.WriteLine("Y = {0:Y}", AktIdo);
        Console.WriteLine();
        Console.WriteLine("Hónap: {0}", AktIdo.Month);
        Console.WriteLine("A hét napja: {0}", AktIdo.DayOfWeek);
        Console.WriteLine("A nap ideje: {0}", AktIdo.TimeOfDay);
    }
}

Formázás karaktersorozattal

Program.cs
using System;
class Program
{
    static void Main()
    {
        DateTime AktIdo = DateTime.Now;
 
        string format = "yyyy.MM.dd HH:mm";
 
        Console.WriteLine(AktIdo.ToString(format));
    }
}

ToLongTimeString() és ToLongDateString() metódus

Program.cs
using System;
class Program
{
	public static void Main()
	{
		Console.WriteLine(DateTime.Now.ToLongTimeString() + "," + DateTime.Now.ToLongDateString());
	}
}

Véletlen szám generálás

Egész számok

Véletlen szám generálására System névtérben lévő Random osztályt használhatjuk. Példányosítása kötelező, azaz ebben a formában kell objektumot generálni:

Random random = new Random();

A fenti példában a random nevű objektumot generáltuk, amelynek metódusai képesek egész és valós véletlen számok előállítására.

Random veletlen = new Random();
int a = veletlen.Next(5,8);

5 és 7 között generál egy számot. Értéke 5,6 vagy 7.

A Next metódus három alakja:

Next()
Next(Int32)
Next(Int32, Int32)

Valós szám

Program.cs
using System;
class Program
{
	public static void Main()
	{
 
		Random random = new Random();
		double a = random.NextDouble();
 
		Console.WriteLine(a);
	}
}

Byte-ok

A NextBytes() metódus segítségével egy byte tömböt képesek vagyunk egyetlen mozdulattal feltölteni véletlen számokkal.

Program.cs
using System;
class Program
{
	public static void Main()
	{
 
		Random random = new Random();
 
		byte[] tomb = new byte[10];
		random.NextBytes(tomb);
 
		for(int i=0; i<10; i++)
			Console.Write(tomb[i] + " ");
	}
}

Gyakorlat

  1. Szükséges-e a Random osztály példányosítása
  2. Írassa ki a 6-os Lottó nyerőszámait, 6 darab véletlen számból, egymás mellé, kettőspontokkal tagolva.

Konverzió

Kasztolás

int a = 12345678;
long b = a;
int c = (int) b;  //explicit konverzió

Az utolsó esetben szükség van a (int) explicit konverzióra, mert c változó kisebb mint a b. Így ha túlcsordulás történik a fordító dob egy kivételt.

Convert osztály

A System névtérben találunk egy Convert nevű osztályt, amelynek metódusai a különböző típusokba való konvertálást megoldják.

using System;
class Program
{
    static void Main()
    {
        String s = 4;
        int a = Convert.ToInt32(s);
    }
}

A példában a beolvasott érték karaktersorozat, amit átalakítunk egész típusúvá.

További lehetőségek

Convert.ToInt32()    //egészt ad vissza
Convert.ToInt64()    //64-bites egészet ad vissza
Convert.ToSingle()   //float-ot ad vissza
Convert.ToDouble()   //double-t ad vissza
Convert.ToString()   //Stringet ad vissza
Convert.ToChar()     //Karaktertípust ad vissza

A számrendszer alapja is megadható, például a ToInt32() metódus esetén:

string str = "a";
Convert.ToInt32(str, 16);

Egy 16-os számrendszerbeli szám konvertálása 10-es számrendszerbe.

Szöveg számmá ellenőrizve

string str = "45";
int num;
bool parseOk = int.TryParse(str, out num);

Adatbekérés

Stringek beolvasása

Console osztály ReadLine() metódusa egy karaktersorozatot olvas be a billentyűzetről. A karaktersorozatnak akkor van vége, ha „Enter”-t nyomtunk.

Adatbekérés a konzolról:

prog.cs
using System;
class Prog
{
    static void Main()
    {
        string s;
        Console.Write("Neved: ");
        s = Console.ReadLine();
        Console.WriteLine("Ezt írtad: " + s);
    }  
}

A programban deklaráltunk egy s változót. Viszont fentebb már említettük, hogy a „string” valójában nem típus, hanem osztály. Az „s” egy olyan objektum, amit nem kell példányosítani a new kulcsszóval. Később látni fogjuk, hogy az „s” objektumnak vannak metódusai, amiket használhatunk.

Az alábbi utasítás:

s = Console.ReadLine();

egy tehát a beolvasott karaktersorozatot az s változóban fogja eltárolni. Az s változó pedig string típussal deklaráltuk.

Számértékek beolvasása

Nincs külön számértéket beolvasó függvény. A számértékeket először karaktersorozatként olvassuk be, majd átkonvertáljuk azokat számmá. A konvertálás a Convert osztállyal végezzük.

Egész számok

Az alábbiakban három módszer látunk a karaktersorozat egész számmá konvertálására:

using System;
class Program
{
    static void Main()
    {
        int a;        
        a = Convert.ToInt32(Console.ReadLine());
    }
}
using System;
class Program
{
    static void Main()
    {
        int a;        
        a = int.Parse(Console.ReadLine());
    }
}
using System;
class Program
{
    static void Main()
    {
        int a;        
        a = Int32.Parse(Console.ReadLine());
    }
}

Valós számok

using System;
class Program
{
    static void Main()
    {
        double a, b;      
 
        a = Double.Parse(Console.ReadLine());
        b = Convert.ToDouble(Console.ReadLine());
 
    }
}

Gyakorlat

  1. Milyen metódussal kérhetünk be számokat?
  2. A metódus amellyel értékeket kérünk be, milyen osztályhoz tartozik.
  3. Az osztály amelynek egy metódusát használtuk ebben a fejezetben, melyik névtérben van?
  4. Milyen osztály használható stringek számokká konvertálására?
  5. Írjon programot, amely bekér két számot, majd kiírja a szorzatukat.
  6. Írjon programot, amely bekér két számot, majd az elsőt elosztja a másodikkal, a képernyőre írja az eredményt.

Szekvenciális tevékenység, hatáskör

Szekvenciális tevékenység

Azok az utasítások, amelyeket egymásután sorba hajtunk végre alkotják a szekvenciális tevékenységeket. Később látni fogjuk, hogy lesz olyan amikor egy utasítást nem biztos, hogy végre szeretnénk hajtani, esetleg csak akkor szeretnénk végrehajtani, ha teljesül valami feltétel. Esetleg egy utasítást többször is szeretnénk végrehajtani, de ha ezen ismétlések száma száz, nem szeretnénk azt százszor leírni.

Változók hatásköre

Az eddigi példákban az egyes változókat is a metódusokban hoztuk létre. Néha azonban előfordul, hogy olyan változókat szeretnénk használni amelyhez több metódus is hozzáfér. A változót ilyenkor a metóduson kívül, de az osztályon belül hozzuk létre. Az ilyen változókat mindig a metódusok előtt szoktuk létrehozni az osztály mezőinek nevezzük.

Az alábbi példaprogramban létrehozunk például egy „s” nevű mezőt:

prog.cs
using System;
class Prog
{
    static string s;
 
    static void Main()
    {
        Console.Write("Neved: ");
        s = Console.ReadLine();
        Console.WriteLine("Ezt írtad: " + s);
 
    }  
}

Szelekciós tevékenység

Bizonyos esetekben nem szeretnénk, ha minden utasítás végrehajtódna. Csak a kiválasztott utasítások hajtódnak ilyenkor végre. Az utasítás végrehajtását, tehát feltételhez kötjük. A feltétel valójában egy állítás. Az utasításokat pedig akkor hajtjuk végre, ha az állítás igaz. Az állítás mindig valamilyen logikai kifejezés. Például állíthatom azt, hogy:

a > 3

Az a változó tartalma nagyobb mint 3.

Vagy:

a > b

Az a változó tartalma nagyobb mint b változóé, stb.

if

A szelekcióra az if utasítást használjuk a C# nyelvben. Az alábbiakban az if utasítás általános formáját látjuk:

if (feltétel)
  tevékenység;

Láthatjuk, hogy az if után zárójelben adjuk meg a feltételt. Fontos, hogy a feltétel után ne zárjuk le a pontosvesszővel az if utasítást. A feltételt követi az utasítás, amelyet végre kell hajtani. Vegyük észre, hogy a példában csak egyetlen utasítás szerepel. Ha a feltétel teljesül az utasítás végrehajtódik.

A következőkben általános formában azt látjuk, hogyan lehet megadni, ha a feltétel nem teljesül, akkor mi is történjen.

if {feltétel)
  tevékenység;
else
  tevékenység2;

Az else után írt utasítás akkor kerül végrehajtásra, ha a feltétel nem igaz.

A következő példák az általános forma helyett már egy konkrét C# megvalósítást mutatnak be.

Ha feltétel igaz, akkor teszünk valamit. Ha hamis akkor mást.

boole bináris = true;
if (bináris == true)
{
  Console.WriteLine("igaz");
}

Két elágazásra példa

if (bináris == true)
{
   Console.WriteLine("igaz");
}
else if (szám > 10)
{
   Console.WriteLine("nagy");
}

Többágú elágazást hozhatunk létre, ha az else után ismét egy if utasítást írunk egy újabb feltétellel. Szokás „else if” utasításnak is hívni.

Három elágazásra példa:

if (bináris == true)
{
   Console.WriteLine("igaz");
}
else if (szám > 10)
{
   Console.WriteLine("nagy");
}
else
{
  Console.WriteLine("egyébként");
}

Az else if esetén kiveszem az else részt akkor az if-től egy önálló if blokk következik. A ”{„ blokk nyitó karakter és ”}„ blokk záró karakterek nem kötelezőek, ha csak egyetlen utasítás szerepel a blokkban.

Adott például két szám (3 és 5)

switch

A switchet többágú szelekcióra találták ki, de ssak egyszerű változókat fogad el a vizsgálathoz.

Legyen például egy „szam” nevű változó, amelynek tartalma alapján különböző szövegeket szeretnénk a képernyőre íratni:

int szam = 3;
 
switch(szam)
{
  case 1:
    Console.WriteLine("Egy");
    break;
  case 2: 
    Console.WriteLine("Kettő");
    break;
  case 3:
    goto case 2;
  default:
    Console.WriteLine("Egyik sem");
    break;
}

Ha a „szam” tartalma 1, akkor az „Egy” szöveget írjuk ki, ha 2, akkor „Kettő”, stb. Ha egyik érték sem volt, akkor az „Egyik sem” szavakat írjuk ki.

Iteráció

Az iteráció más néven ciklus vagy ismétlés. Valamilyen tevékenység ismételt végrehajtása. A ciklusoknak két fajtájáról szoktunk beszélni. Ezek:

A növekményes ciklus esetén mindig tudjuk hányszor kell ismételnünk, de legalábbis valamiből ez előre kiderül. Az „amíg” típusú ciklusok esetén nem tudjuk meddig kell mennünk, mert az vagy a felhasználótól, vagy egy adatsorozat hosszától, vagy más külső tényezőtől függ, amit előre nem ismerünk.

for

A legáltalánosabb ciklus utasítás a for. Alapvetően növekményes ciklusok létrehozására találták ki, de a C# nyelvben és minden C alapú nyelvben használhatjuk „amíg” típusú ciklus megvalósítására is.

for (kezdő_érték; feltétel; növekmény)
    utasítás;
    

A ciklus fejrésze három részre osztható. A három részt egymástól pontosvesszővel választjuk el. Növekményes ciklusoknál mindig használunk egy ciklusváltozót, amelyben számoljuk, hogy éppen hol járunk a ciklusban. Az fejrész első paramétere ennek a ciklusváltozónak a kezdőértéke. A második a feltétel, azaz meddig menjen a ciklus. A harmadik pedig megmondja számunkra, hogyan növeljük a ciklusváltozót. Egyesével, kettesével vagy más növekményben. A ciklus során végrehajtandó utasításokat nevezzük a ciklus törzsének.

Ha egyetlen utasításunk van a ciklus törzsben akkor nem kötelező blokk nyitó és blokk záró kapcsos-zárójeleket elhelyeznünk. Több utasítás esetén azonban ez kötelező. Ezzel jelezzük, hogy mely utasítások tartoznak a ciklus törzséhez.

for (kezdő_érték; feltétel; növekmény)
{
    utasítás1;
    utasítás2;
    ...
    utasításn;
}

Egy konkrét példa, amelyben a ciklus változó tartalmát kiíratjuk. A ciklus 0-tól – 9-ig írja a számokat a képernyőre.

for ( int i = 0; i < 10; i++)
{
    Console.WriteLine(i);
}

while

A while ciklust alapvetően „amíg” típusú ciklusok létrehozására találták ki, de létrehozható vele növekményes ciklus is.

A while ciklus addig ismétlődik, amíg a kifejezés értéke igaz

while(kifejezés)
{
    utasítás;
}

Egy végtelen ciklus:

while(true)
{

}

do while

A do while ciklus megegyezik a while ciklussal azzal a különbséggel, hogy hátultesztelő. Ez azt jelenti, hogy a ciklus törzse egyszer mindenképpen végrehajtódik, és csak az után vizsgáljuk meg, hogy a következő ciklus is végrehajtható-e.

int i = 1;
do
{
   Console.WriteLine("Egyik sem");
   i++;
}while (i < 10);

Vegyük észre, hogy az utolsó sorban le kell zárni a ciklust pontosvesszővel.

foreach

A foreach utasítással olyan ciklusokat tudunk létrehozni, amelyek egy lista vagy tömb elemeit bejárják, azaz végig veszik.

Lista létrehozása és végigjárása

List<int> lista = new List<int>();
 
lista.Add(15);
lista.Add(10);
lista.Add(20);
lista.Add(42);
lista.Add(30);
 
foreach(int i in lista)
{
  Console.WriteLine(i);
}

A példában a lista elemei egész számok. Az int változót a foreach fejrészében deklaráljuk „int i”, ebben kapjuk vissza az aktuális számot. Az i változót kötelező a foreach fejrészében deklarálnunk! A következő forma helytelen:

foreach(i in lista)
    ...

Szöveges tömb létrehozása és bejárása

string[] tömb = new string[3];
tömb[0] = "Máté";
tömb[1] = "Márk";
tömb[2] = "Lukács";
 
foreach(string str in tömb)
{
  Console.WriteLine(str);
}

Sztringek

A Sztringekről

A sztring adattípus az egyik nagyon fontos adattípus. Elméletileg több milliárd hosszú lehet a mérete, de az operációs rendszer is határt szab számára. A „string” vagy „String” típusként deklaráljuk, az UTF-16 kódolással tárolt karaktereket.

A sztringek nem módosíthatók. Módosulás helyett egy új példány jön létre.

A string egyik tulajdonsága a Length, amely a szöveg hosszát tartalmazza. Készítsünk egy programot, amelyben a egy s nevű változót deklarálunk, majd kiíratjuk annak hosszát:

string s = "Alma";
Console.WriteLine(s.Length);

Az s objektumnak lesz egy Length értéke, amelyet lekérdezhetünk. A példában kiíratjuk az eredményt.

A „String” osztály használata:

String s = "Alma";
Console.WriteLine(s.Length);

Metódusok

Concat

Az első dolog, amit általában szeretnénk egy sztringgel, összefűzni másik sztringgel. Sztringek összefűzésének művelete a konkatenálás.

Tulajdonképpen ezt csináljuk akkor is, amikor egy sztring változóhoz sztring literális konstanst fűzök:

string jarmu = "Opel";
Console.WriteLine("Az " + jarmu + " jó kocsi");

Összefűzés + karakterrel, másik példa:

string s1 = "egyik";
string s2 = "másik"; 
Console.WriteLine(s1 + s2);  

Az összefűzésre a ”+„ operátort használjuk. Az összefűzésre persze van külön metódus is, amelynek a neve Concat().

string s = "alma";
string s2 = "valami";
 
Console.WriteLine(String.Concat(s, s2)); 

Összefűzés

A kiíratás helyett eltárolhatjuk:

string s3 = String.Concat(s, s2); 

Compare

A következő művelet az összehasonlítás. Az összehasonlítás az ”==„ operátorral nem ajánlott, helyette használjuk az alábbi metódusok valamelyikét.

A Compare() metódus, egy 0-át ad vissza, ha egyezik a két összehasonlított sztring, -1-et ha nem egyezik.

string s1 = "Alma";
string s2 = "Alba";
Console.WriteLine(String.Compare(s1, s2));
Console.WriteLine(String.Compare(s, "Abba"));
Console.WriteLine(String.Compare(s, null));

CompareTo

string s1 = "Alma";
string s2 = "Alba";
Console.WriteLine(s1.CompareTo(s2));

CompareOrdinal

string s1 = "alma";
string s2 = "Alma";
Console.WriteLine(String.CompareOrdinal(s, s2));

A két betű különbségét adja.

Equal

s = "alma";
s2 = "valami";
 
Console.WriteLine(s.Equals("alma"));
Console.WriteLine(String.Equals(s, s2)); 

Egyenlőség vizsgálata

Szövegre értelmezhető műveletek

Contains

Egy adott szöveg szerepel-e a sztringünkben

string s = "megbízható";
bool tartalmaz = s.Contains("bíza");
 
Console.WriteLine("Hossz: {0}", tartalmaz);

IndexOf

Egy adott karakter szerepel-e a sztringünkben

string s = "megbízmhatóm";
int hol = s.IndexOf('m');
 
Console.WriteLine("Hossz: {0}", hol);

Remove

A 4-es indextől törlés a végéig

string s = "megbízható";
string s2 = s.Remove(4);
 
Console.WriteLine("Hossz: {0}", s2);

A 4-es indextől két karakter törlése

string s = "megbízható";
string s2 = s.Remove(4, 2);
 
Console.WriteLine("Hossz: {0}", s2);

Insert

Az Insert() metódussal beszúrhatunk egy szöveget egy String típusú objektumba.

mondat2 = mondat.Insert(8, "Kossuth");

A példában a mondat nevű változóhoz fűzzük a „Kossuth” szót, majd eltároljuk a mondat2-ben.

ToLower és ToUpper

Kis vagy nagybetűvé alakítás

string s = "MEGbízható";
string s2 = s.ToLower();
string s3 = s.ToUpper();
 
Console.WriteLine("Hossz: {0}", s2);
Console.WriteLine("Hossz: {0}", s3);

String típusra néhány példa

Program1.cs
using System;
using System.Text;
 
class Program
{
    static void Main()
    {
        string s;        
        s = "Valami";        
        Console.WriteLine(s);        
        Console.WriteLine(s.Substring(2,2));
        Console.WriteLine(s.Replace("al","ág"));
    }    
}
Program2.cs
using System;
class str
{
        public static void Main()
        {
                Console.WriteLine("Szövegkezelés Java nyelven");
 
		string szoveg = "alma";
 
		Console.WriteLine(szoveg.Equals("almaa")); // true értéket ad vissza, ha egyezik, vagy false
		Console.WriteLine(szoveg.CompareTo("alma")); // 0-át kapunk, ha egyezik
		Console.WriteLine(szoveg.IndexOf("alma")); // -1 ha nem található; hanyadik helytől (első index 0)
 
		//Szöveg darabolása
		string sor ="alma:körte:barack:szilva";
		string[] tomb =	sor.Split(':');
		Console.WriteLine(tomb[1]);
 
		string mondat = "Ha megint ezért üzen";
		Console.WriteLine(mondat.Substring(4)); //Kezdő indextől szeretném a karaktereket
		Console.WriteLine(mondat.Substring(4, 7));  //Kezdő index és hány darab karakter
 
        }
}

Tartalmaz-e egy szöveget egy karaktersorozat változó:

if(mondat.ToLower().IndexOf("alma")>=0 ) 
    Console.WriteLine("Tartalmazza az alma szót");

Kisbetűssé alakítás:

string kisbetus = vegyebetus.ToLower();

Módosítható szöveg

A szimpla String típusként létrehozott karaktersorozatok valójában nem módosíthatók, mint azt fentebb már tárgyaltuk. A StringBuilder osztállyal módosítható szöveget hozhatunk létre.

A StringBuilder osztály a System.Text névtérben található:

using System.Text;

A használat előtt a new operátorral helyet foglalunk az objektumnak:

StringBuilder s = new StringBuilder;

A StringBuilder típusú változót egyes részeit például kicserélhetem. A példakedvéért szeretnénk az ékezetes „á” karakteretek egy ékezet nélküli „a” karakterre cserélni. Ekkor ezt írhatom:

StringBuilder s = new StringBuilder();
s.Append("almá");
if (s[3] == 'á') 
      s[3] = 'a';

Ezt a műveletet szimpla String típussal nem tehetem meg.

A példában láttuk, hogy az „s” StringBuilder változóhoz egy Append() metódussal tudunk egy szimpla karaktersorozat literált, de akár egy változót is hozzáfűzni. Vegyük észre, hogy megoldottuk a String típus StringBuilder típussá konvertálását. Visszafele a ToString() metódussal történik a konverzió:

StringBuilder s = new StringBuilder();
s.Append("szilva");
string s2 = s.ToString();

A StringBuilder típusú változókhoz sortörés fűzhető az AppendLine() metódussal:

StringBuilder s = new StringBuilder();
s.Append("szilva");
s.AppendLine();
s.Append("Körte");

A sortörés egyetlen mozdulattal is megtehető:

StringBuilder s = new StringBuilder();
s.Append("szilva").AppendLine();

Beszúrás

StringBuilder s = new StringBuilder();
s.Append("Szilvi");
s.Insert(4,"a");

Rendezés

Program01.cs
using System;
class Program
{
	static void Main()
	{
		String[] t = {"Szilva", "Körte", "Barack", "Alma"};
 
		Array.Sort(t);
 
		foreach(String s in t)
				Console.WriteLine(s);
	}
}

A stringek kezelése tömbként

Hivatkozás egy karakterre

A karaktersorozatok minden elemére hivatkozhatunk. Így bármely karaktert elérhetjük a sorozatból. Az első karakter indexe 0-val kezdődik, mint a tömböknél.

Példa

Program.cs
using System;
 
class tomb
{
      public static void Main()
      {
          Console.WriteLine("Szó");
          string szo = Convert.ToString(Console.ReadLine());
 
          Console.WriteLine("A beírt szó első betűje: {0}\n\n", szo[0]);
       }
}

Tömbök

Egy dimenziós tömbök

Vektor:

3 7 5 2 8 6

Számokat tárolunk.

Minden számnak adunk egy indexet:

[0] [1] [2] [3] [4] [5]
3 7 5 2 8 6
  int[] tomb;        //Deklaráljuk a tömböt
  tomb = new int[3]; //Helyet foglalunk a tömbnek
  tomb[0] = 5;       //Az első elemnek értéket adunk
  tomb[1] = 9;       //A második elemnek értéket adunk
  tomb[2] = 8;       //A harmadik elemnek értéket adunk

A fentiek egy egész számokat tárolni képes tömböt mutat be.

Néhány lehetséges tömbtípus:

A tömbök méretét lekérdezhetjük a Length tulajdonsággal:

meret = tomb.Length;

Alternatív megadás

A var kulcsszóval is bevezethető a változónév:

var tomb = new int[3];

Egy három elemet tartalmazó tömböt deklaráltunk.

Tömb kezdőértéke

int[] tomb = {3, 4, 7};
double[] szam = { 3.5, 3.6};

vagy

double[] szam = new double[2]  { 3.5, 3.6};

vagy

double[] szam = new double[]  { 3.5, 3.6};
int[] tomb1 = Enumerable.Range(5,5).ToArray();
int[] tomb2 = Enumerable.Repeat(0, 5).ToArray();	

Tömb átméretezése

A tömbök átméretezhetők az Array.Resize() utasítással:

Program.cs
using System;
class Program
{
    static void Main()
    {
	char[] tomb = new char[4];	
 
	tomb[0] = 'P';
	tomb[1] = 'e';
	tomb[2] = 'r';
	tomb[3] = 'l';
 
	Console.WriteLine(tomb[2]);	
	Array.Resize(ref tomb, 2);
    }
}

Mátrix

2×2 tömb tömb deklarálása:

int[,] tomb = new int[3,3];

Egy értékadás:

tomb[2,2] = 3;
Program.cs
class Program
{
    static void Main()
    {
	int[,] tomb = new int[,]{
		{3,4,5},
		{6,3,2},
		{8,2,7}
	};				
    }
}

Mátrix átméretezése

Program.cs
using System;
 
class Program
{
	static private void ResizeIntArray(ref int[,] original, int cols, int rows)
	{
		int[,] newArray = new int[rows, cols];
		Array.Copy(original, newArray, original.Length);
		original = newArray;
	}
 
	static void Main()
	{
		int[,] szamok = new int[3,3];
 
		ResizeIntArray(ref szamok,5,10);
	}
}

készítünk egy 2 dimenziós tömböt

int[,] newArray = new int[rows, cols];

átmásoljuk az előző tömb tartalmát

Array.Copy(original, newArray, original.Length);

az eredeti tömbnek átadom az új tömböt.

original = newArray;

Több dimenziós tömbök

Kettőnél több dimenziós tömbök is használhatók.

int[,,] tomb = new int[3,3,3];
tomb[2,2,2] = 3;
int[,,,] tomb = new int[3,3,3,3];
tomb[2,2,2,2] = 3;

Egy három és egy négy dimenziós tömb:

Program.cs
using System;
class Program
{
	public static void Main()
	{
 
 
		//Három dimenzós tömb kezdőértéke
		int[,,] tomb = new int[,,] {
			{{1, 2, 3}}, 
			{{4, 5, 6}}
		};
 
 
		//Négy dimenzió tömb kezdőértéke
		int[,,,] tomb4 = new int[,,,] {
			{{{1, 2, 3, 5}}}, 
			{{{4, 5, 6, 7}}}
		};
 
 
		//~ tomb[0, 0, 0] = 3;
		Console.WriteLine(tomb[1,0,0]);
		Console.WriteLine(tomb4[1,0,0,0]);
	}
}

Tömb paraméterként

Program.cs
using System;
class Program
{
	public static void Main()
	{
		int[] tomb = {35, 45, 63, 77};		
 
		kiir(tomb);		
	}
	static void kiir(int[] t)
	{
		for(int i=0; i<t.Length; i++)
			Console.WriteLine(t[i]);
	}
}

Tömben tömb

Angolosan: Jagged Array (Array-of-Arrays)

Program.cs
using System;
class Program
{
	public static void Main()
	{
		//Tömben tömb vagy egyenletlen tömb (minden sor más elemszámot tartalmazhat
 
		int[][] tomb = new int[2][];
		tomb[0] = new int[3];
		tomb[1] = new int[3];
 
 
		tomb[0][0] = 3;
		tomb[0][1] = 5;
		tomb[0][2] = 8;
		tomb[1][0] = 15;
		tomb[1][1] = 123;
		tomb[1][2] = 2;
 
		Console.WriteLine(tomb[0][1]);
	}
}

Tömbben tömb kezdőértékkel

Program.cs
using System;
class Program
{
	public static void Main()
	{
		//Tömben tömb vagy egyenletlen tömb (minden sor más elemszámot tartalmazhat
 
		int[][] tomb = new int[2][];
		tomb[0] = new int[3] {2, 5, 3};
		tomb[1] = new int[3] {8, 4, 9};		
 
		Console.WriteLine(tomb[0][1]);
	}
}

Lista

A List osztály a System.Collections.Generic névtérben található, különféle elemeket tárolhatunk benne. Hogy milyen típust szeretnénk benne tárolni meg kell adnunk a deklaráció során kisebb mint és nagyobb mint jelek között.

Program01.cs
using System;
using System.Collections.Generic;
 
class Program01
{
	static void Main()
	{
 
		List<int> lista = new List<int>();		
 
		lista.Add(35);
		lista.Add(45);
		lista.Add(29);
 
		Console.WriteLine(lista[0]);
		Console.WriteLine(lista.Count);
                lista.Clear();
                Console.WriteLine(lista.Count);
	}
}

Struktúrák

A struktúrák a C nyelvből származnak, de ilyen szerkezet található a Pascal nyelvben, csak ott rekordnak hívják. A struktúrák használatának célja, hogy különböző típusú adatokat tudjunk tárolni. Csak gondoljunk bele, mit tárolhatunk egy tömbbe?! Több azonos típusú adatot. A struktúrában ugyanígy több adat tárolható, de ezek típusa eltérhet egymástól.

A C# struktúrái egy kicsit többek a C nyelvben kitalált eredeti verziótól. A struktúrák ugyanis hasonlóan működnek az osztályokhoz. Vagyis nem csak változókat deklarálhatunk bennünk, hanem metódusokat is, amelyek valamilyen műveletet végeznek a változókon.

A C# struktúra típusként viselkedik, vagyis egy változót kell vele deklarálnunk a használatához. Az egyes tagokat úgy érjük el, hogy ponttal tagolva leírom a változónév után a struktúrában található változó nevét.

Az alábbiakban egy egyszerű példát látunk a használatukra. A struktúrában követelmény, hogy nem hozható létre metóduson belül.

Első példa

Program.cs
class Program
{
    struct Egyszeru
    {
        public int Pozicio;
        public bool Kesz;
        public double UtolsoErtek;
    };
 
    static void Main()
    {
        Egyszeru s;
        s.Pozicio = 1;
        s.Kesz = false;
        s.UtolsoErtek = 5.5;
    }
}

A példában egy „Egyszeru” nevű struktúrát hozunk létre, amelynek változóit a Main() metódusban értékekkel töltjük fel. Vegyük észre, hogy a struktúrát a az osztályon belül hoztuk létre.

A következőkben egy olyan példát látunk, ahol a struktúrát az osztályon kívül hozzuk létre.

Második példa

Program.cs
using System;
 
struct TEgyszeru
{
	public String nev;
	public int kor;
	public long fizetes;
}
 
class Program
{
    static void Main()
    {
        Console.WriteLine("Hi");
	TEgyszeru dolgozo;
 
	dolgozo.nev = "Kis János";
	dolgozo.kor = 35;
	dolgozo.fizetes = 370000;
 
        Console.ReadKey();
    }
}

Metódusok

Több metódus

Eddig egyetlen metódust használtunk, melynek neve a „Main”. Ebbe írtuk utasításainkat. Ha sok egymással összefüggő utasításunk van, akkor azokat metódusokba rendezzük, adunk neki egy nevet. Az utasítást csoportot ezek után a metódus nevének plusz zárójeles rész leírásával hívjuk.

Például legyen egy utasítás halmaz amely egy névjegyet ír ki:

Program.cs
using System;
class Program
{
    static void Main()
    {
        Console.WriteLine("Nagy József");
	Console.WriteLine("1142 Budapest");
	Console.WriteLine("Nyár u. 3.");			
	Console.WriteLine("Tel.: +36(1)2345-123");
	Console.WriteLine("Fax.: +36(1)2345-124");			
    }
}

Az utasításokat metódusba teszem, melynek neve: „Nevjegy”

static void Nevjegy()
{
    Console.WriteLine("Nagy József");
    Console.WriteLine("1142 Budapest");
    Console.WriteLine("Nyár u. 3.");			
    Console.WriteLine("Tel.: +36(1)2345-123");
    Console.WriteLine("Fax.: +36(1)2345-124");			
}

A Nevjegy metódust így hívom a Main() metóduban:

Nevjegy();

Az egész program ezek után:

Program.cs
using System;
class Program
{
    static void Nevjegy()
    {
        Console.WriteLine("Nagy József");
        Console.WriteLine("1142 Budapest");
        Console.WriteLine("Nyár u. 3.");
        Console.WriteLine("Tel.: +36(1)2345-123");
        Console.WriteLine("Fax.: +36(1)2345-124");
    }
 
    static void Main()
    {
        Nevjegy();
    }
}

A következőkben egy olyan metódust alkotunk amely összead két számot, majd kiírja a képernyőre:

Program.cs
using System;
class Program
{
    static void Osszead()
    {
        int eredmeny = 3 + 5;
        Console.WriteLine(eredmeny);
    }
 
    static void Main()
    {
        Osszead();
    }
}

A metódus 3-hoz 5-öt ad. Az eredményt pedig rögtön a képernyőre írja.

Tegyük fel, hogy én most nem 5-öt, hanem valamilyen más számot szeretnék hozzáadni. Egy objektumon vagy osztályon végrehajtható eljárás. Két fajta metódus van, a statikus és a példány.

Statikus metódus

A statikus metódust az osztályon hívjuk meg és nem annak egy példányán.

Program.cs
class Program
{
    static void Kiir()
    {
        System.Console.WriteLine("A metódus meghívása");
    }
 
    static void Main()
    {
        Program.Kiir();
        Kiir();  // Mivel osztályon belül vagyunk nem kötelező annak nevét megadni.
    }
 
}

A fentikben azt írtuk, hogy az osztályon hívjuk meg a statikus metódust:

Program.Kiir();

A példában viszont azt látjuk, hogy meghívható az osztály neve nélkül is, mivel osztályon belül vagyunk.

Kiir();

Példánymetódus

Az osztály egy példányán hívjuk meg.

Program.cs
class Program
{
    void Kiir()
    {
        System.Console.WriteLine("A metódus meghívása");
    }
 
    static void Main()
    {
        Program p = new Program();
        p.Kiir();
    }
}

Az Program osztálynak létrehozzuk egy külön példányát. A példában ez a „p”. A p egy olyan objektum, amely a Program osztályból lett származtatva.

Fájlkezelés

Eddig az adatokat bekértük a felhasználótól, tároltuk azokat a memóriában, de a program befejezése után azok elvesztek. Ha szeretnénk megőrizni az adatokat későbbre is, állományba kell azokat mentenünk valamelyik háttértárolón.

A C# nyelvben a fájlokat adatfolyamként kezeljük, a folyamba írunk és abból olvasunk.

A következő lépések szükségesek a fájlkezeléshez:

  1. Folyam megnyitása
  2. Kapcsolódás a folyamhoz
  3. Olvasás/Írás a folyamba

Olvasás a fájlból

A fájlkezelő osztályok a System.IO névtérben vannak, ezért szükségünk van egy új „using” kezdetű sorra:

using System;
using System.IO;
 
...
 
FileStream folyam = new FileStream("adat.txt", FileMode.Open);
StreamReader olvaso = new StreamReader(folyam);
while (!olvaso.EndOfStream)
{
    Console.WriteLine(olvaso.ReadLine());
}
olvaso.Close();

A példában a FileStream és StreamReader osztályokat használjuk.

A StreamReader osztállyal létrehozott objektumnak van egy ReadLine() metódusa. Tulajdonképpen ezzel tudunk olvasni. A metódus egy sort olvas, majd a következő sorra ugrik a fájlmutató. A következő olvasás mára második sort fogja olvasni. Mivel nem lehetünk biztosak abban hány sor van egy állományban, az EndOfStream mező olvasásával vizsgáljuk, hogy vége van-e a fájlnak. Egy while ciklussal addig folytatjuk a beolvasást, amíg nem érjük el a fájl végét.

Írás a fájlba

Program.cs
using System;
using System.IO;
 
class Program
{
        public static void Main()
        {
                Console.WriteLine("Hi");
 
		FileStream folyam = new FileStream("adat.txt", FileMode.Create);
		StreamWriter iro = new StreamWriter(folyam);
 
		iro.WriteLine("Alma");
		iro.WriteLine("Körte");
		iro.Close();
        }
}

Egyéb módok

Hozzáfűzés a fájlhoz

Program.cs
using System;
using System.IO;
 
class Program
{
    static void Main()
    {
        Console.WriteLine("Írás");
 
        FileStream folyam = new FileStream("adat.txt", FileMode.Append);
        StreamWriter iro = new StreamWriter(folyam);
 
        iro.Write("valami");
        iro.Write(45);
        iro.Flush();
 
        iro.Write(60);
        iro.WriteLine();
        iro.Close();
 
    }
}

Fájlkezelés egyszerűbben

Ha nem szeretnénk fájlmódot megadni, akkor használhatjuk csak a StreamReader osztályt egy állomány olvasásához.

StreamReader olvaso = new StreamReader("adat.txt");
while((sor = olvaso.ReadLine()) != null)
    Console.WriteLine(sor);
olvaso.Close();
Program.cs
using System;
using System.IO;
 
class Program
{
	static void Main()
	{
		Console.WriteLine("Olvasás fájlból");
		StreamReader  olvaso = File.OpenText("adat.txt");
		string sor = null;
		while ((sor = olvaso.ReadLine()) != null)
			Console.WriteLine(sor);
		olvaso.Close();		
	}
}
Program.cs
using System;
using System.IO;
 
class Program
{
	static void Main()
	{
		Console.WriteLine("Olvasás fájlból");
		StreamReader  olvaso = File.OpenText("adat.txt");
 
		string sorok = olvaso.ReadToEnd();
		Console.WriteLine(sorok);
 
		olvaso.Close();		
	}
}
Program.cs
using System;
using System.IO;
 
class Program
{
	static void Main()
	{
		Console.WriteLine("Írás fájlba");
 
		FileInfo f = new FileInfo("gy.txt");
		StreamWriter iro =f.CreateText();
		iro.WriteLine("alma");
		iro.WriteLine("körte");
		iro.WriteLine("szilva");
		iro.Close();
 
	}
}
Program.cs
using System;
using System.IO;
 
class Program
{
	static void Main()
	{
		Console.WriteLine("Írás fájlba");
 
		StreamWriter iro =File.CreateText("gy2.txt");
		iro.WriteLine("alma");
		iro.WriteLine("körte");
		iro.WriteLine("szilva");
		iro.Close();
 
	}
}

Fájlkezelés objektumainak lezárása

A következő példában létrehozzuk a StreamReader egy példányát, a using utasításon belül. A usingnak van egy blokkja. A blokk végén a StreamReader példányán automatikusan meghívódik a Dispose() metódus.

using(StreamReader olvaso = new StreamReader("adat.txt");)
{
    while((sor = olvaso.ReadLine()) != null)
        Console.WriteLine(sor);
    olvaso.Close();
}

Hibakezelés

try 
{
    using(StreamReader olvaso = new StreamReader("adat.txt");)
    {
        while((sor = olvaso.ReadLine()) != null)
            Console.WriteLine(sor);
        olvaso.Close();
    }
} catch (Exception e) 
{
    Console.WriteLine("A fájl nem létezik: ");
    Console.WriteLine(e.Message);
}

Olvasás fájlból kódolás megadásával

using System;
using System.IO;
using System.Text;
 
class Program
{
	static void Main()
	{
		Console.WriteLine("Olvasás fájlból");
		StreamReader  olvaso = new StreamReader("adat.txt", Encoding.UTF8);
		string sor = null;
		while ((sor = olvaso.ReadLine()) != null)
			Console.WriteLine(sor);
		olvaso.Close();		
	}
}

Megadható kódolások:

Egy C# program szerkezete

Szerkezet

A C# programban metódusokat írunk. Kezdőként természetesen csak egy metódusunk van, ahogy fentebb láttuk ez a Main() metódus. Később azonban, ha már nagyon sok utasításunk lesz, vagy csak mert logikailag ésszerű külön tenni bizonyos utasításokat, újabb metódusokat hozunk létre, ezeket is a főosztályon belül.

Ha már nagyon sok metódusunk van, akkor a logikailag összetartozó metódusokat tehetjük külön osztályba is. A forráskódunk, amely tulajdonképpen egy állomány ekkor különálló több osztályból fog állni.

Ha már nagyon sok osztályunk egy állományban, azokat névterekbe rendezhetjük. Ha már nagyon sok névterünk azokat pedig újabb állományokba írhatjuk.

A C# program tehát egy vagy több állományból áll. Minden állományban lehet egy vagy több névtér. A névtereken belül egy vagy több osztályt hozhatunk létre.

Az eddigi példákban nem használtunk névtereket. Ebből is következik, hogy az nem kötelező. A névtér használata azért lehet, hasznos mert így egy osztálynevét többször is használhatunk, a sok-sok osztály pedig csoportosíthatjuk.

A „Helló Világ” nevű program saját névtérbe helyezve így nézhetne ki:

hello3.cs
using System;
 
namespace Elso
{
	class Program
	{
		static void Main()
		{
			Console.WriteLine("Helló Világ!");
		}
	}
}

A példában a saját Main() metódusunkat egy „Elso” nevű névtérbe helyeztük. A névterek használatával, tulajdonképpen összefoghatjuk, illetve csoportosíthatjuk az osztályokat.

Több forrásfájl használata

Ha már nagyon sok osztályunk van, szeretnénk egy részét külön állományokban tartani.

Ha az osztály tartalmazó fájlt egyszerűen a main.cs mellé teszem, akkor már használhatjuk is az osztályt.

sajat.cs
using System;
 
class Gyumolcs {
    public static void kiir() {
        Console.WriteLine("alma\nkörte\nbarack");
    }
}
main.cs
class Belepesipont {
    static void Main()  {
        Gyumolcs.kiir();
    }
}

Mono 2.0 használata esetén a fordítás:

gmcs sajat.cs main.cs

Névtér használata

Az alábbiakban készítek egy állományt amelynek sajat.cs lesz a neve. Elhelyezek benne egy Elelem nevű névteret, a névtérben lesz egy Gyumolcs nevű osztályunk, az pedig tartalmaz egy kiir() metódust, amely gyümölcsök neveit írja a képernyőre:

sajat.cs
using System;
 
namespace Elelem
{
    class Gyumolcs
    {
        public static void kiir()
        {
            Console.WriteLine("alma\nkörte\nbarack");
        }
    }
}

Ezek után létrehozunk egy állományt, amely használni fogja az Elelem névteret, benne a Gyumolcs osztály kiir() metódusát:

main.cs
using Elelem;
class Belepesipont
{
    static void Main()
    {
 
        Gyumolcs.kiir();
    }
}

Mono 2.0 használata esetén a fordítás:

gmcs sajat.cs main.cs

DLL-ek használata

Az alábbiakban egy DLL-t készítünk amely tartalmaz egy számláló és egy érték visszaadó metódust.

Forrás

Szamlalo.cs
public class Szamlalo
{
      int val = 0;
 
      public void Hozzaad (int x) 
      { 
          val = val + x;
      }
 
      public int Ertek()
      {
          return val;
      }  
 
}

Lényeges, hogy a Szamlalo osztály public előtaggal legyen megadva!

Prog.cs
using System;
 
class Prog {
 
      static void Main()
      {
          Szamlalo szamol = new Szamlalo();
          szamol.Hozzaad(4);
          szamol.Hozzaad(3);
          Console.WriteLine("Érték: " + szamol.Ertek());
       }
}

Fordítás

MS keretrendszerrel

Elsőként elkészítjük a .dll állományt:

csc /target:library Szamlalo.cs

Ez után lefordítjuk a programot:

csc /reference:Szamlalo.dll Prog.cs

Mono rendszerrel

Elsőként elkészítjük a .dll állományt:

gmcs /target:library Szamlalo.cs

Ez után lefordítjuk a programot:

gmcs /reference:Szamlalo.dll Prog.cs

Függelék

A Visual Studio alapértelmezett kódja

ConsoleApp1.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}