A kiválasztott változat és az aktuális verzió közötti különbségek a következők.
Előző változat mindkét oldalon Előző változat | Előző változat Utolsó változat Következő változat mindkét oldalon | ||
oktatas:programozas:c:c_nyelv [2019/01/05 22:08] |
oktatas:programozas:c:c_nyelv [2020/05/24 19:15] admin [Mátrix] |
||
---|---|---|---|
Sor 1: | Sor 1: | ||
+ | [[oktatas:programozás:C|< C]] | ||
+ | |||
+ | |||
+ | ====== C programozási nyelv ====== | ||
+ | |||
+ | * **Szerző:** Sallai András | ||
+ | * Copyright (c) Sallai András, 2011, 2013, 2014, 2015, 2020 | ||
+ | * Licenc: GNU Free Documentation License 1.3 | ||
+ | * Web: http://szit.hu | ||
+ | |||
+ | ===== Bevezetés ===== | ||
+ | A C nyelv egy általános célú programozási nyelv. Rendszerprogramozási nyelvként is emlegetik, | ||
+ | mivel hatékonyan használható operációs rendszerek írására. Természetesen használható más | ||
+ | alkalmazói programok írására is. A nyelvet a BCPL és B nyelvből eredeztetik: | ||
+ | |||
+ | | BCPL | -> | B | -> | C | | ||
+ | |||
+ | |||
+ | A C nyelvet **Dennis Ritchie** az 1970-es évek elején fejlesztette ki **Ken Thompson** segítségével. A | ||
+ | nyelvet UNIX operációs rendszerre tervezte, amely egy DEC PDF-7 rendszeren futott. Volt egy B nevű | ||
+ | nyelv, amely nem lett ismert. A C sok tekintetben örökölte a B nyelv tulajdonságait, azért is lett | ||
+ | a neve az ábécé következő betűje. Az 1970es években a személyi számítógépeken BASIC nyelvet lassan | ||
+ | felváltja a C nyelv. 1978-ban **Dennis Ritchie** és **Brian Kerninghan** nevével fémjelzett | ||
+ | „//**A C programozási nyelv**//” című könyv első kiadása megjelenik. 1983 -- 1989 az Amerikai | ||
+ | Nemzeti Szabványügyi Hivatal (angolul: American National Standards Institute, röviden ANSI) | ||
+ | szabványnak fogadják el. 1990-ben megjelenik a szabványnak egy átdolgozott kiadása C99 névvel. | ||
+ | |||
+ | {{:oktatas:programozás:c:c_nyelvek_halmaza.png|}} | ||
+ | |||
+ | Az ANSI C az eredeti K&R nyelvnek egy kibővített változata. A megvalósítások | ||
+ | ehhez még plusz kiterjesztéseket tesznek hozzá. | ||
+ | |||
+ | ===== Gyakorlat 001 ===== | ||
+ | |||
+ | * Válaszoljon a következő kérdésekre: | ||
+ | * Ki kezdte fejleszteni a C nyelvet? | ||
+ | * Milyen operációs rendszerre tervezték a C nyelvet eredetileg? | ||
+ | * Milyen programozási nyelvből örökölt tulajdonságokat a C nyelv? | ||
+ | * Mikor fogadták el a C nyelvet ANSI szabványnak? | ||
+ | ===== Helló Világ ===== | ||
+ | |||
+ | <code c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | printf("Helló Világ\n"); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | A C nyelv több előre megírt függvénnyel rendelkezik, amit csak meg kell hívni. Ezen előre megírt | ||
+ | függvénygyűjteményeket hívjuk sztenderd könyvtáraknak. A sztenderd könyvtárak is több csoportja | ||
+ | ismert, amelyeket elneveztünk a rájuk jellemző névvel. Ilyenek a stdio, stdlib, math, stb. | ||
+ | |||
+ | A fenti program első sora amely #include-al kezdődik egy szabványos könyvtár használatát | ||
+ | teszi lehetővé, amelynek neve stdio. Az stdio programozói könyvtárnevet kötelező kisebb mint és | ||
+ | nagyobb mint karakterek közé tenni: | ||
+ | #include <stdio.h> | ||
+ | |||
+ | A programban szereplő printf() utasítás a stdio.h fejállományban vagy programozói könyvtárban található. | ||
+ | Ha használni akarjuk a printf() függvényt, mindig szükség van a #include <stdio.h> sorra. | ||
+ | |||
+ | A C nyelvben, minden utasítást függvényekbe rendezünk. Egy C programban mindig lenni kell egy | ||
+ | main nevű függvénynek, a programnak ugyanis ez lesz a belépési pontja. A függvények neve után | ||
+ | egy nyitó és egy bezáró zárójelet teszünk. Ezzel is jelezzük, hogy a main valójában függvény: | ||
+ | main() | ||
+ | A main() tehát egy függvény fejrésze, amely egy névből (esetünkben a "main") és az azt követő | ||
+ | zárójelekből áll. | ||
+ | |||
+ | Egy függvénynek mindig van törzs része is. A függvény törzsét kapcsos zárójelek írjuk. | ||
+ | A függvény törzsében írjuk le mit történjen a programban. A mi programunkban egyeteln | ||
+ | utasítás van: | ||
+ | printf("Helló Világ\n"); | ||
+ | |||
+ | A printf() függvény, illetve utasítás a képernyőre írja a paraméterként megkapott értékeket. | ||
+ | Esetünkben ez a "Helló Világ" szöveg. A szöveg végén a "\n" gondoskodik a sortörésről. | ||
+ | |||
+ | {{:oktatas:programozas:c:c_fuggveny_reszei.png?400|}} | ||
+ | |||
+ | ===== Megjegyzés ===== | ||
+ | |||
+ | A C nyelv lehetővé teszi egy és többsoros megjegyzés elhelyezését. | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | // egy soros megjegyzés | ||
+ | </code> | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | /* több | ||
+ | soros | ||
+ | megjegyzés | ||
+ | */ | ||
+ | </code> | ||
+ | |||
+ | ===== Gyakorlat 002 ===== | ||
+ | |||
+ | * Írjon programot, ami kiírja a településének a nevét, és irányító számot egy újabb sorba. | ||
+ | * Az előző programban, írja többsoros megjegyzésbe saját nevét. | ||
+ | |||
+ | ===== Kivitel ===== | ||
+ | |||
+ | Ha leírok egy karaktersorozatot, például alma, a printf() függvény a képernyőre írja: | ||
+ | <code c Program01.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | printf("alma"); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code c Program01.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | puts("alma"); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | A karaktersorozat persze lehet számok vagy akár más karakterek sorozata is: | ||
+ | printf("35"); | ||
+ | |||
+ | |||
+ | A számokat csak a formátumuk meghatározásával lehet kiíratni. | ||
+ | <code c> | ||
+ | printf("%d", 35); | ||
+ | </code> | ||
+ | |||
+ | Előbb írok egy formázó szöveget, majd jöhet a szám. | ||
+ | Egész számok esetén a formázó szöveg: "%d". | ||
+ | |||
+ | |||
+ | A printf() kiíratandó paramétere, lehet akár egy kifejezés is: | ||
+ | printf("%d", 35*2); | ||
+ | A kifejezés kiértékelődik, és az eredményt kapjuk vissza. | ||
+ | |||
+ | |||
+ | ===== Escape szekvenciák ===== | ||
+ | |||
+ | Fentebb láttuk, ha egy karaktersorozatot a képernyőre iratok, annak minden karaktere | ||
+ | változtatás nélkül megjelenik a képernyőn. Egyes karaktereknek azonban lehet speciális | ||
+ | jelentése is. | ||
+ | |||
+ | Fentebb már láttuk, ha az "n" betű elé egy visszaperjelet (\) írunk, akkor annak különleges | ||
+ | jelentése lesz. Ahelyett, hogy magát a karaktert kapnánk a képernyőn egy sortörést | ||
+ | küld a képernyőre. | ||
+ | |||
+ | Ehhez hasonló, például a <nowiki>"\t"</nowiki>, amely egy tabulátorjelet küld a képernyőre. | ||
+ | |||
+ | Az ilyen karaktereket hívjuk Escape szekvenciáknak. | ||
+ | |||
+ | Mivel az idézőjelnek <nowiki>(")</nowiki> is speciális jelentése van, ezért azt is csak | ||
+ | escape szekvenciaként tudjuk megjeleníteni: | ||
+ | \" | ||
+ | |||
+ | A következő táblázat az escape szekvenciák listáját tartalmazza: | ||
+ | |||
+ | ^ Escape szekvencia ^ Leírás ^ | ||
+ | | \n | Sortörés | | ||
+ | | \t | Tabulátor | | ||
+ | | <nowiki>\"</nowiki> | Idézőjel | | ||
+ | | \% | Százalékjel | | ||
+ | |||
+ | ===== Gyakorlat 003 ===== | ||
+ | |||
+ | * Írjon programot, ami "Kék János" nevet. | ||
+ | * A következő sorba, tabulátorral tagolva a fizetését írja ki, ami 2856000. | ||
+ | * A program írja ki a saját (szerző) nevét is, a "szerző: " szöveg után. | ||
+ | |||
+ | |||
+ | ===== Változók és adattípusok ===== | ||
+ | A C nyelvbe változókat hozhatunk létre, értékek tárolására. | ||
+ | A változó deklarálása során meg kell adni milyen típus fogunk benne tárlni, | ||
+ | majd megadom a változó nevét. Például egy egész típusú változót szeretnék | ||
+ | tárolni, egy szam nevű változóban, akkor: | ||
+ | int szam = 25; | ||
+ | |||
+ | Ebben a példában rögtön definiáltam a szam nevű változó értékét. | ||
+ | |||
+ | |||
+ | A típusok előtt különféle módosítókat adhatunk meg. Ilyen módosító a signed vagy az unsigned. | ||
+ | Magyarul előjeles vagy előjel nélküli. A típusok alapértelmezetten előjelesek. Ha nem szeretnék | ||
+ | negatív számokat használni, akkor használhatom az unsigned módosítót, így a pozitív számokból | ||
+ | nagyobb intervallummal dolgozhatok. | ||
+ | |||
+ | |||
+ | Példaként, adjuk meg az int számára unsigned módosítót. Ez azt jelenti, | ||
+ | hogy csak előjel nélküli, pozitív számokat adhatunk meg. | ||
+ | unsigned int szam = 25; | ||
+ | |||
+ | Egy int típusban, a géptől függően 2 vagy 4 bájt nagyságú számot tárolhatunk. | ||
+ | Az int számra megadhatunk egy short módosítót. Ekkor maximum 32767 a legnagyobb | ||
+ | megadható szám. A legkisebb -32768. | ||
+ | short int szam = 25; | ||
+ | |||
+ | A legnagyobb megadható szám tárolása: | ||
+ | short int szam = 32767; | ||
+ | |||
+ | |||
+ | Használhatjuk egyszerre a unsigned és a short módosítót is. Ekkor a legkisebb tárolható szám 0, | ||
+ | a legnagyobb, 65535. Például: | ||
+ | |||
+ | unsigned short int szam = 63000; | ||
+ | |||
+ | |||
+ | {{:oktatas:programozas:c:tipusokmodositok.png?400|}} | ||
+ | |||
+ | |||
+ | A következő táblázat tovább módosítókat tartalmaz, és méreteket tartalmaz. | ||
+ | |||
+ | |||
+ | ^ Típus ^ Bájt ^ Minimális érték ^ Maximális érték ^ | ||
+ | | char, signed char | 1 | -128 | 127 | | ||
+ | | unsigned char | 1 | 0 | 255 | | ||
+ | | short, short int, \\ signed short int | 2 | -32768 | +32767 | | ||
+ | | unsigned short, \\ unsigned short int | 2 | 0 | 65535 | | ||
+ | | int, signed int | 2 vagy 4 | short vagy long | short vagy long | | ||
+ | | unsigned \\ unsigned int | ugyanígy, de \\ unsigned | ugyanígy, de \\ unsigned | | ||
+ | | long, long int, \\ signed long int | 4 | -2147483648 | +2147483647 | | ||
+ | | unsigned long, \\ unsigned long int | 4 | 0 | 4294967295 | | ||
+ | | char, \\ unsigned char | 1 | 0 | 255 | | ||
+ | | signed char | 1 | -128 | 127 | | ||
+ | |||
+ | |||
+ | A szabványos limits.h fejállományban megtalálhatók a maximum és minimum értékek. | ||
+ | |||
+ | | CHAR_MIN | | ||
+ | | CHAR_MAX | | ||
+ | | UCHAR_MAX | | ||
+ | | SHRT_MIN | | ||
+ | | SHRT_MAX | | ||
+ | | USHRT_MAX | | ||
+ | | INT_MAX | | ||
+ | | INT_MIN | | ||
+ | | UINT_MAX | | ||
+ | | LONG_MAX | | ||
+ | | LONG_MIN | | ||
+ | | ULONG_MAX | | ||
+ | |||
+ | |||
+ | Ha szeretnénk kiíratni a legnagyobb tárolható int típust, írjuk meg a következő programot: | ||
+ | <code c nagyegesz.c> | ||
+ | #include <stdio.h> | ||
+ | #include <limits.h> | ||
+ | |||
+ | int main() { | ||
+ | printf("%d\n", INT_MAX); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ===== Valós típus ===== | ||
+ | |||
+ | Legnagyobb tárolható double típus: | ||
+ | <code c valos.c> | ||
+ | #include <stdio.h> | ||
+ | #include <float.h> | ||
+ | int main() { | ||
+ | printf("double: %g\n", DBL_MAX); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | <code c> | ||
+ | printf("float : %g\n", FLT_MAX); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | | FLT_MAX | | ||
+ | | DBL_MAX | | ||
+ | ===== Gyakorlat 004 ===== | ||
+ | |||
+ | * Válaszoljon a következő kérdésekre: | ||
+ | * Mi a legnagyobb tárolható szám, ha short típust adok meg? | ||
+ | * Mi a legnagyobb tárolható szám, ha char típust adok meg? | ||
+ | * Mi annak az állandónak a neve, amiből kideríthető, mi legnagyobb tárolható int típus? | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Állandók vagy konstansok ===== | ||
+ | |||
+ | Az állandó olyan érték, amelyet a továbbiak során nem akarunk megváltoztatni. A program futási ideje alatt ezek az állandók nem változtathatók. Kétfajta állandót használunk: literális és nevesített. | ||
+ | |||
+ | {{:oktatas:programozas:c:allandok.png?400|}} | ||
+ | ==== Literális állandó ==== | ||
+ | |||
+ | |||
+ | Lehet szám, karakter, karaktersorozat, stb. | ||
+ | |||
+ | === Számállandó === | ||
+ | |||
+ | |||
+ | 1234 formában leírt szám egész szám. Ha long típusú állandót akarok leírni akkor utána kell tennem | ||
+ | egy kis l vagy L betűt: 123456789L | ||
+ | |||
+ | === Karakteres állandó === | ||
+ | |||
+ | |||
+ | Egy vagy több aposztrófok (') közzé írt karakter. | ||
+ | Pl.: 'a' vagy 'b' | ||
+ | Karakterként nem szerepelhet a ' vagy az újsor. Ezért ezek helyettesítésére ún. escapesorozatokat | ||
+ | (escape szekvencia) használunk: | ||
+ | új sor NL \n | ||
+ | vízszintes tabulátor HT \t | ||
+ | függőleges tabulátor VT \v | ||
+ | visszalépés (backspace) BS \b | ||
+ | kocsivissza CR \r | ||
+ | lapemelés (formfeed) FF \f | ||
+ | hangjelzés (bell) BEL \a | ||
+ | backslash \ \\ | ||
+ | kérdőjel ? \? | ||
+ | aposztróf ' \' | ||
+ | idézőjel " \" | ||
+ | oktális szám ooo \ooo | ||
+ | hexadecimális szám hh \xhh | ||
+ | |||
+ | === Szöveges állandó === | ||
+ | |||
+ | |||
+ | Szokásos elnevezése: „karaktersorozat”. A szöveget úgy adjuk meg, hogy maga a program azon | ||
+ | változtatni nem tud a végrehajtás során, vagyis állandó. A C nyelvben a szöveges állandót | ||
+ | idézőjelek között adjuk meg. Pl.: | ||
+ | |||
+ | "Alma a fa alatt" | ||
+ | Vegyük észre! A magyar nyelvtől eltérően a C nyelvben a nyitóidézőjel felül van. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Nevesített állandó ==== | ||
+ | |||
+ | === #define === | ||
+ | |||
+ | Az állandó számára egy azonosító nevet adunk meg. Egy szövegkonstans pl. a „Nagy Péter”. Ennek | ||
+ | a konstansnak nevet is adhatunk, pl.: TELJESNEV. Innentől kezdve a TELJESNEVet bárhova írom | ||
+ | oda behelyettesítődik a „Nagy Péter”. C nyelvben ez a következő módon adható meg: | ||
+ | #define TELJESNEV ”Nagy Peter” | ||
+ | A C nyelvben lehetőség van még egy módon állandó megadására a const módosítóval. Pl.: | ||
+ | const int a; | ||
+ | Azt vállaljuk,hogy a változó tartalmát sosem változtatjuk meg. | ||
+ | |||
+ | Általánosan: | ||
+ | <code c> | ||
+ | #define azonosító helyettesítő–szöveg | ||
+ | </code> | ||
+ | |||
+ | Egy konkrét példa: | ||
+ | <code c> | ||
+ | #define MAX 5 | ||
+ | #define FELSOHATAR 100 | ||
+ | #define ALSOHATAR 50 | ||
+ | </code> | ||
+ | |||
+ | === const === | ||
+ | Egy nem módosítható objektumot deklarál. Az azonosítót nem használhatjuk | ||
+ | egy egyenlőségjel baloldalán. | ||
+ | |||
+ | <code c> | ||
+ | const int a = 5; | ||
+ | </code> | ||
+ | |||
+ | |||
+ | <code c konst.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | const int a = 5; | ||
+ | printf("%d\n", a); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | <code c konst2.c> | ||
+ | #include <stdio.h> | ||
+ | #define MERET 3 | ||
+ | typedef double Ttomb[MERET]; | ||
+ | int main() { | ||
+ | Ttomb tomb = {3.7, 5.2, 2.8}; | ||
+ | printf("%f\n", tomb[0]); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Láthattuk, hogy nevesített állandót két módon hozhatok létre. | ||
+ | A define előfordítói utasítással, és a const módosítóval. | ||
+ | |||
+ | {{:oktatas:programozas:c:nevesitett_literalis_allando.png?300|}} | ||
+ | |||
+ | A const egy módosító. A módosító után áll az állandó típusa. | ||
+ | A típus lehet char*, ezzel szöveges állandó adható meg. | ||
+ | |||
+ | {{:oktatas:programozas:c:szoveges_allando.png?400|}} | ||
+ | |||
+ | A const módosító mondja meg, hogy nevesített állandót szeretnénk, | ||
+ | létrehozni. Amikor a programozó állandót hoz létre, azt vállalja, | ||
+ | hogy ezt a memória területet a program tovább része alatt nem | ||
+ | szeretné megváltoztatni. | ||
+ | |||
+ | ===== Gyakorlat 005 ===== | ||
+ | |||
+ | * Írjon programot, amely két állandót tartalmaz: | ||
+ | * a programban használja a #define utasítást | ||
+ | * az egyik szám, egy iskolában adható legkisebb osztályzatot tartalmazza | ||
+ | * a másik szám, az iskolában adható legnagyobb osztályzatot tartalmazza | ||
+ | * az állandók neveit válassza meg tetszőlegesen | ||
+ | |||
+ | |||
+ | ===== Deklarációk ===== | ||
+ | |||
+ | |||
+ | A felhasználása előtt minden változót deklarálni kell, bár bizonyos deklarációk a programkörnyezet | ||
+ | alapján is létrejöhetnek. A deklaráció egy típust határoz meg, és utána egy vagy több adott típusú | ||
+ | változó felsorolása (listája) áll. | ||
+ | |||
+ | <code c> | ||
+ | int also, felso, lepes; | ||
+ | char c, sor[1000]; | ||
+ | </code> | ||
+ | |||
+ | A változók a deklarációk közt tetszőleges módon szétoszthatók, pl. a bal oldali deklarációs listákkal teljesen egyenértékű az | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | int also; | ||
+ | int felso; | ||
+ | int lepes; | ||
+ | char c; | ||
+ | char sor[1000]; | ||
+ | </code> | ||
+ | |||
+ | A változók a deklaráció során kezdeti értéket is kaphatnak: | ||
+ | <code c> | ||
+ | int i = 0; | ||
+ | char esc = '\\'; | ||
+ | int hatar = MAXSOR+1; | ||
+ | float eps = 1.0e-5 | ||
+ | </code> | ||
+ | Bármely változó deklarációjában alkalmazható a const minősítő. Pl.: | ||
+ | <code c> | ||
+ | const double e = 2.71828182845905; | ||
+ | const char uzenet [ ] = ”figyelem:”; | ||
+ | int strlen(const char[ ]); | ||
+ | </code> | ||
+ | ===== Gyakorlat 006 ===== | ||
+ | |||
+ | * Válaszoljon a következő kérdésekre: | ||
+ | * Milyen nyelvet tanulunk most? | ||
+ | * Ki találta ki ezt a nyelvet amit tanulunk? | ||
+ | * Mikor let a nyelv kifejlesztve? | ||
+ | * Mire használjuk? | ||
+ | * Van-e szabványosított verziója? | ||
+ | * Mi az az előfordítás? | ||
+ | * Mivel kezdjük az előfordítói utasításokat? | ||
+ | * Mi az a konstans? | ||
+ | * Hogyan hozunk létre C nyelvben konstanst? | ||
+ | * Milyen az írásmódja a változóknak és a konstansoknak? | ||
+ | * A C nyelv kis és nagybetű érzékeny? | ||
+ | * A C nyelv kiírató utasítása? | ||
+ | * Hol nem szükséges a C nyelvben az utasítás végére (;) pontosvessző? | ||
+ | |||
+ | |||
+ | ===== Operátorok ===== | ||
+ | |||
+ | Kétfajta operátort különböztetünk meg: | ||
+ | |||
+ | * egy operandusú | ||
+ | * két operandusú | ||
+ | |||
+ | Egy operandus esetén az operátor lehet prefix és postfix: | ||
+ | operátor operandus | ||
+ | operandus operátor | ||
+ | |||
+ | Két operandusú operátor esetén: | ||
+ | operandus1 operátor operandus2 | ||
+ | |||
+ | | ||
+ | |||
+ | |||
+ | ==== Aritmetikai műveletek ==== | ||
+ | |||
+ | + összeadás | ||
+ | - kivonás | ||
+ | * szorzás | ||
+ | / osztás | ||
+ | % maradék képzés | ||
+ | | ||
+ | Példák: | ||
+ | <code c> | ||
+ | int c = 3 + 5; | ||
+ | </code> | ||
+ | | ||
+ | |||
+ | <code c> | ||
+ | int a = 3; | ||
+ | int b = 5; | ||
+ | int osszeg = a + b; | ||
+ | </code> | ||
+ | |||
+ | Maradékképzés: | ||
+ | <code c> | ||
+ | int maradek = 9 % 2; | ||
+ | </code> | ||
+ | |||
+ | A maradékot a "maradek" nevű változóban tároljuk. | ||
+ | |||
+ | |||
+ | |||
+ | ==== Relációs műveletek ==== | ||
+ | > | ||
+ | < | ||
+ | >= | ||
+ | <= | ||
+ | == Egyenlő | ||
+ | != Nem egyenlő | ||
+ | Az eredményük vagy 0 (hamis) vagy 1 (igaz) | ||
+ | |||
+ | |||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | int a = 3; | ||
+ | int b = 5; | ||
+ | int e = a < b; | ||
+ | printf("%d\n", e); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== Logikai műveletek ==== | ||
+ | |||
+ | && ÉS | ||
+ | || VAGY | ||
+ | ! NEM | ||
+ | |||
+ | Kiértékelés balról jobbra. Ha a kifejezés értéke meghatározható, akkor a kiértékelés leáll. | ||
+ | |||
+ | Például: | ||
+ | (a < 10) && (b > 5) | ||
+ | |||
+ | |||
+ | ==== Értékadás másként ==== | ||
+ | |||
+ | <code c> | ||
+ | a = a + 1 -> a += 1 | ||
+ | a = a - 1 -> a -= 1 | ||
+ | a = a * 1 -> a *= 1 | ||
+ | a = a / 1 -> a /= 1 | ||
+ | </code> | ||
+ | |||
+ | <code c> | ||
+ | a = a * (b + 1) -> a *= b + 1 | ||
+ | </code> | ||
+ | |||
+ | ==== Növelő és csökkentő operátorok ==== | ||
+ | |||
+ | ++ | ||
+ | -- | ||
+ | |||
+ | Az operátorok lehetnek prefix vagy postfix. | ||
+ | a++ -> a = a + 1; | ||
+ | ++a -> a = a + 1; | ||
+ | |||
+ | Ha postfixként használjuk: | ||
+ | a = 15; | ||
+ | b = a++; // -> b = a; a = a + 1; | ||
+ | |||
+ | Ha prefixként használjuk: | ||
+ | a = 15; | ||
+ | b = ++a; // -> a = a + 1; a = b; | ||
+ | |||
+ | ==== Bitenkénti logikai operátorok ==== | ||
+ | |||
+ | |||
+ | | & | bitenkénti ÉS | | ||
+ | | <nowiki>|</nowiki> | bitenkénti VAGY | | ||
+ | | <nowiki>^</nowiki> | bitenkénti kizáró vagy | | ||
+ | | <nowiki><<</nowiki> | bitléptetés balra | | ||
+ | | <nowiki>>></nowiki> | bitléptetés jobbra | | ||
+ | | ~ | egyeskomplemens | | ||
+ | |||
+ | Csak egész számokra alkalmazhatók | ||
+ | |||
+ | === Példa a bitenkénti balra léptetésre === | ||
+ | |||
+ | | 000011 | nem számít mennyit jelent | | ||
+ | | 000010 | 3-at jelent, ennyivel léptetünk | | ||
+ | | 001100 | eredmény | | ||
+ | |||
+ | |||
+ | === Komplemens képzés === | ||
+ | |||
+ | | a = 6 | 0000 0110 | | ||
+ | | ~a | 1111 1001 | 249 | | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Precedencia ==== | ||
+ | |||
+ | | () | zárójel | | ||
+ | | ! ++ -- - | negálás, növelés, csökkentés, előjel | | ||
+ | | * / % | szorzás, osztás, maradékképzés | | ||
+ | | + - | összeadás, kivonás | | ||
+ | | << >> | bitenkénti eltolás balra és jobbra | | ||
+ | | <nowiki>< <= >= ></nowiki> | kisebb mint, kisebb vagy egyenlő, nagyobb vagy egyenlő, nagyobb mint | | ||
+ | | == =! | egyenlő, nem egyenlő | | ||
+ | | & | bitenkénti megengedő (inkluzív) és | | ||
+ | | <nowiki>^</nowiki> | kizáró (exkluzív) vagy | | ||
+ | | <nowiki>|</nowiki> | bitenkénti vagy | | ||
+ | | && | és | | ||
+ | | <nowiki>||</nowiki> | vagy | | ||
+ | |||
+ | Ha a egy művelet azonos szinten van, akkor az operátorok balról jobbra lesznek kiértékelve. | ||
+ | |||
+ | Példa a balról jobbra kiértékelésre: | ||
+ | <code c> | ||
+ | 12/2*3 = 18 | ||
+ | </code> | ||
+ | |||
+ | A zárójel mindig módosítja a kiértékelés sorrendjét. | ||
+ | |||
+ | ===== Gyakorlat 007 ===== | ||
+ | |||
+ | * Válaszoljon a következő kérdésekre: | ||
+ | * Mire való a % operátor? | ||
+ | * Mire való a && operátor? | ||
+ | * Mire való a || operátor? | ||
+ | * Mire való a ++ operátor? | ||
+ | |||
+ | |||
+ | |||
+ | ===== Formázott kivitel ===== | ||
+ | |||
+ | A printf() függvény formátumozott kivitelt tesz lehetővé számunkra. | ||
+ | A formátum kétféle karaktert tartalmazhat: amely kiíródik | ||
+ | változás nélkül a kimenetre, és amely a soron következő argumentum | ||
+ | konverzióját írja elő. Minden konverziós szakasz a % jellel kezdődik. | ||
+ | |||
+ | |||
+ | A % jel és a konverziós karakter között a sorrendben a következők lehetnek: | ||
+ | * mínusz jel, ami konvertált argumentumot balra igazítja | ||
+ | * egy szám, ami megadja a minimális mezőszélességet | ||
+ | * egy pont, ami elválasztja a mezőszélességet a pontosságot megadó számtól | ||
+ | * egy szám (pontosság) | ||
+ | * karaktersorozatnál a kiírandó karakterek maximális számát | ||
+ | * lebegőpontos számok esetén a tizedespont után kiírt számjegyek számát | ||
+ | * egész karakterek esetén a kiírt számjegyek maximális számát | ||
+ | * egy h betű, ha egy egész számot short típusként vagy egy l betű, ha long típusként írun ki | ||
+ | |||
+ | |||
+ | A leggyakrabban használt konverziós karakterek, a d, f, c és s. | ||
+ | |||
+ | |||
+ | A d konverziós karaktert egész számok kiíratására használjuk. | ||
+ | |||
+ | {{:oktatas:programozas:c:egsz_szam_formazasa.png?200|}} | ||
+ | |||
+ | Az f konverziós karaktert valós számok kiíratására használjuk. | ||
+ | |||
+ | {{:oktatas:programozas:c:valos_szam_formazasa.png?200|}} | ||
+ | |||
+ | A c konverziós karaktert, karakterek kiíratására használjuk. | ||
+ | |||
+ | {{:oktatas:programozas:c:karakter_formazasa.png?200|}} | ||
+ | |||
+ | Az s konverziós karaktert, karaktersorozatok, vagyis szövegek kiíratására használjuk. | ||
+ | |||
+ | {{:oktatas:programozas:c:szoveg_formazasa.png?200|}} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | Kiíratás 2 tizedesjegy pontossággal: | ||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | double a = 31.123456; | ||
+ | printf("%.2f\n", a); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Kiíratás 20 szélesen: | ||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | double a = 31.123456; | ||
+ | printf("%20.2f\n", a); | ||
+ | |||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Balra igazítás: | ||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | double a = 31.123456; | ||
+ | printf("|%-20.2f|\n", a); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ^ formátum karakter ^ típus ^ Használatra példa ^ | ||
+ | | ld | long | | ||
+ | | d | int, short, char | | ||
+ | | f | float | | ||
+ | | c | char, int | | ||
+ | | Lg | long double | | ||
+ | | <nowiki>%</nowiki> | százalék jelet ír a képernyőre | <nowiki>printf("%%\n");</nowiki> | | ||
+ | |||
+ | ===== Gyakorlat 008 ===== | ||
+ | |||
+ | * Válaszoljon a következő kérdésekre: | ||
+ | * Milyen formátum karakter szükséges egy egész érték kiíratásához? | ||
+ | * Milyen formátum karakter szükséges egy valós érték kiíratásához? | ||
+ | * Milyen formátum karakter szükséges egy karakter kiíratásához? | ||
+ | * Milyen formátum karakter szükséges egy karaktersorozat kiíratásához? | ||
+ | |||
+ | |||
+ | ===== Matematikai függvények ===== | ||
+ | |||
+ | A matematikai függvények a math.h nevű fejállományban vannak. | ||
+ | |||
+ | |||
+ | |||
+ | ==== Állandók ==== | ||
+ | PI értéke | ||
+ | |||
+ | M_PI 3.14159265358979323846 | ||
+ | |||
+ | |||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | #include <math.h> | ||
+ | int main() { | ||
+ | printf("%f\n", M_PI); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Szinusz ==== | ||
+ | |||
+ | A trigonometriai függvények szög helyett radiánban várják az értéküket. | ||
+ | A feladatokban általában szögben adják meg az értékeket, amit át kell számolnunk | ||
+ | radiánban. | ||
+ | |||
+ | |||
+ | Ha például van 30 fokunk, akkor meg kell szorozni PI értékével, | ||
+ | majd az eredményt el kell osztani 180-nal. | ||
+ | |||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | #include <math.h> | ||
+ | |||
+ | int main() { | ||
+ | printf("%f\n", sin(30 * M_PI / 180)); | ||
+ | |||
+ | } | ||
+ | |||
+ | </code> | ||
+ | Készítsük el példaprogramot, majd fordítsuk és futtassuk. | ||
+ | |||
+ | A matematikai függvények használata esetén szükség van egy új kapcsolóra, a -l. | ||
+ | A -l értéke egy "m" betű, utalva a math-ra. Egy matematikai függvény használata esetén, | ||
+ | tehát így fordítunk egy C forráskódot: | ||
+ | |||
+ | <code bash> | ||
+ | cc -l m -o main main.c | ||
+ | </code> | ||
+ | |||
+ | ==== Függvények ==== | ||
+ | |||
+ | double sin (double); | ||
+ | double cos (double); | ||
+ | double tan (double); | ||
+ | double sinh (double); | ||
+ | double cosh (double); | ||
+ | double tanh (double); | ||
+ | double asin (double); | ||
+ | double acos (double); | ||
+ | double atan (double); | ||
+ | double atan2 (double, double); | ||
+ | double exp (double); | ||
+ | double log (double); | ||
+ | double log10 (double); | ||
+ | double pow (double, double); | ||
+ | double sqrt (double); | ||
+ | double ceil (double); // Felfele kerekít | ||
+ | double floor (double); // Lelfele kerekít | ||
+ | double fabs (double); // Abszolút érték | ||
+ | double ldexp (double, int); | ||
+ | double frexp (double, int*); | ||
+ | double modf (double, double*); | ||
+ | double fmod (double, double); | ||
+ | |||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | #include <math.h> | ||
+ | int main() { | ||
+ | printf("%f\n", sqrt(9.5)); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | <code c trig.c> | ||
+ | #include <stdio.h> | ||
+ | #include <math.h> | ||
+ | int main() { | ||
+ | printf("%f\n", pow(2,8)); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== Az abszolút érték egész számokkal ==== | ||
+ | |||
+ | Érdekesség, hogy az abs() függvény másik programozói könyvtárban van, a stdlib.h könyvtárban. | ||
+ | |||
+ | Szintaxis: | ||
+ | <code> | ||
+ | int abs(int) //Abszolút érték | ||
+ | </code> | ||
+ | |||
+ | Használata, például: | ||
+ | <code c main.c> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main() { | ||
+ | int szam = -4; | ||
+ | int ered = abs(szam); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | Ha fordításnál kihagyjuk az stdlib.h programozói könyvtárat, | ||
+ | akkor figyelmeztetést kapunk: | ||
+ | <code> | ||
+ | warning: implicit declaration of function 'abs' [-Wimplicit-function-declaration] | ||
+ | int ered = abs(szam); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | Az újabb GCC 5-s verzióban az alapértelmezetten C szabvány a C11. | ||
+ | Ez megköveteli, hogy szerepeltessük az #include fordítási direktívával, | ||
+ | a stdlib.h könyvtárat. | ||
+ | |||
+ | |||
+ | A fordító rávehető, hogy C89/C90 szabványt használjon, ami nem találja | ||
+ | hibának, ha nem fordítjuk az stdlib.h könyvtárat hozzá. | ||
+ | |||
+ | cc -std=gnu89 -o main main.c | ||
+ | |||
+ | Az alapértelmezett C11 szabványt nem kell megadni, de megadható: | ||
+ | cc -std=gnu11 -o main main.c | ||
+ | |||
+ | |||
+ | ==== Egész osztás ==== | ||
+ | |||
+ | Az stdlib.h fejállományban van egy div() függvény, amellyel egész osztást | ||
+ | végezhetünk. A div() függvény egy div_t struktúrát ad vissza. | ||
+ | |||
+ | <code c oszt.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main() { | ||
+ | div_t a = div(5, 2); | ||
+ | printf("%d\n", a); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | A struktúra így néz ki: | ||
+ | <code c> | ||
+ | typedef struct | ||
+ | { | ||
+ | int quot; | ||
+ | int rem; | ||
+ | } div_t; | ||
+ | </code> | ||
+ | |||
+ | |||
+ | Mivel az eredményt struktúrában kapjuk, kiírathatjuk külön az | ||
+ | osztás eredményét, és a maradékot is: | ||
+ | |||
+ | <code c oszt.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main() { | ||
+ | div_t a = div(5, 2); | ||
+ | printf("%d\n", a.quot); | ||
+ | printf("%d\n", a.rem); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | ===== Gyakorlat 009 ===== | ||
+ | |||
+ | * Válaszoljon a következő kérdésekre: | ||
+ | * Mi a math.h? | ||
+ | * A maradék képzést milyen operátorral valósítjuk meg? | ||
+ | * Mondjon két egy operandusú operátort. | ||
+ | * Mondjon négy bitenkénti operátort. | ||
+ | * Milyen utasítással írathatunk ki formázott kivitelt. | ||
+ | * Formázott kivitel esetén, valós számot milyen formátumkarakterrel tudunk kiíratni? | ||
+ | |||
+ | ===== Véletlen szám ===== | ||
+ | |||
+ | |||
+ | ==== Függvények ==== | ||
+ | Egy számítógépen nem könnyű valódi véletlen számot generálni, mivel | ||
+ | minden folyamat jól meghatározott algoritmusok mentén fut. | ||
+ | A C nyelvben az stdlib.h fejállományban (programozói könyvtár), | ||
+ | van definiálva két függvény, ami véletlen szám generálást, segíti. | ||
+ | |||
+ | A következő táblázatban ezeket látjuk: | ||
+ | |||
+ | |||
+ | | int rand(void) | Véletlen szám generálás | | ||
+ | | void srand(unsigned int) | A véletlen szám generálás előkészítése | | ||
+ | |||
+ | A két függvény az ANSI szabvány része. | ||
+ | |||
+ | A rand() függvény 0 és egy nagy egész szám között generál véletlen számot. | ||
+ | A nagy egész szám a stdlib.h fejállományban van definiálva, neve **RAND_MAX**, ami | ||
+ | egy állandó. Ez tartalmazza a legnagyobb generálható egész számot. | ||
+ | 64 bites Debian GNU/Linux 10 verzióban ez: **2147483367**. | ||
+ | |||
+ | Általában nem ilyen számra van szükség van szükség, helyette valamilyen | ||
+ | adott tartományban van véletlen számra szükségünk. | ||
+ | |||
+ | Ezért a kapott véletlen számon, elvégzünk egy egész osztást, és | ||
+ | annak maradékát vesszük figyelembe. Ha például 0 és 3 közötti | ||
+ | számra van szükségünk (ebbe bele értve a 0 és a 3-t is, akkor, | ||
+ | 4-gyel osztunk. A kapott maradék 0, 1, 2 vagy 3 lesz. | ||
+ | Ez lesz a véletlen számunk. | ||
+ | |||
+ | Ha 1, 2, 3 és 4-s számok közül szeretnénk véletlenszerűen számokat | ||
+ | kapni, akkor az előző eredményhez adjunk hozzá 1-t. A véletlen szám | ||
+ | generálása, ekkor így néz ki: | ||
+ | <code c> | ||
+ | int vel = rand() % 4 + 1; | ||
+ | </code> | ||
+ | |||
+ | Az srand() függvényre azért van szükségünk, mert nélküle mindig | ||
+ | ugyanazt a véletlen számot kapjuk. Paraméterként egy time() | ||
+ | függvény szokás futtatni NULL paraméterrel: | ||
+ | <code c> | ||
+ | srand(time(NULL)); | ||
+ | int vel1 = rand() % 4 + 1; | ||
+ | int vel2 = rand() % 4 + 1; | ||
+ | </code> | ||
+ | |||
+ | A time() függény a time.h fejállományban található. | ||
+ | |||
+ | ==== Maximum kiíratása ==== | ||
+ | Írjunk egy programot, ami kiírja a legnagyobb generálható egész számot. | ||
+ | |||
+ | <code c maxrand.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main() { | ||
+ | printf("%d\n", RAND_MAX); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Fordítás és futtatás: | ||
+ | <code bash> | ||
+ | cc -o maxrand maxrand.c | ||
+ | ./maxrand | ||
+ | </code> | ||
+ | |||
+ | ==== Példa 1 ==== | ||
+ | |||
+ | <code c veletlen.c> | ||
+ | |||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <time.h> | ||
+ | |||
+ | int main() { | ||
+ | printf("Véletlen\n"); | ||
+ | srand(time(NULL)); | ||
+ | printf("0 és 4 között: %d\n", rand() % 5); | ||
+ | printf("20 és 29 között: %d\n", rand() % 10 +20); | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Újabb példa ==== | ||
+ | |||
+ | <code c veletlen.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <time.h> | ||
+ | int main() { | ||
+ | srand(time(NULL)); | ||
+ | |||
+ | int a = rand() % 2; | ||
+ | int b = rand() % 2; | ||
+ | |||
+ | printf("Elso : %d\n", a); | ||
+ | printf("Masodik: %d\n", b); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Valódi véletlen szám ==== | ||
+ | Ha több véletlen számot kell generálnunk egymás után, | ||
+ | a rand() függvény nem ad mindig megfelelő eredményt. | ||
+ | BSD és Linux rendszereken a valódi véletlenszámhoz | ||
+ | használjuk a /dev/urandom állományt. | ||
+ | |||
+ | <code c valid.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int veletlen(int n) { | ||
+ | unsigned int vel; | ||
+ | FILE *f; | ||
+ | |||
+ | f = fopen("/dev/urandom", "r"); | ||
+ | fread(&vel, sizeof(vel), 1, f); | ||
+ | fclose(f); | ||
+ | | ||
+ | return vel % n; | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | printf("%d\n", veletlen(6)); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ===== Gyakorlat 010 ===== | ||
+ | |||
+ | * Válaszoljon a következő kérdésekre: | ||
+ | * Milyen fejállományban van a rand() függvény? | ||
+ | * Milyen fejállományban található a time() függvény? | ||
+ | * Milyen fejállományban található a RAND_MAX állandó? | ||
+ | * Milyen fejállományban található a srand() függvény? | ||
+ | * Írjon programot, amely kockadobást szimulál. | ||
+ | * Mentés: kocka.c | ||
+ | * Írjon programot, amely pókerhez 5 kockadobást szimulál. | ||
+ | * Mentés: poker.c | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Konverzió ===== | ||
+ | ==== Típusátalakítások ==== | ||
+ | |||
+ | Egy int típusú változó értéke gond nélkül áttehető egy short típusú változóba, amíg az elfér a | ||
+ | a short típusban. | ||
+ | <code c> | ||
+ | int a = 35; | ||
+ | short b = a; | ||
+ | </code> | ||
+ | |||
+ | A short típusban a legnagyobb tárolható szám: 32767. Mi történik, akkor, ha | ||
+ | 32768 számot tesszük "a" változóba, ami int típusú? | ||
+ | |||
+ | <code c> | ||
+ | int a = 32768; | ||
+ | short b = a; | ||
+ | </code> | ||
+ | |||
+ | Az eredeti szám ilyenkor nem marad meg, értékvesztés történik. | ||
+ | |||
+ | Ha valós típusú változó értékét tesszük egész típusú változóba, | ||
+ | akkor a törtrészek elvesznek, de a típusátalakítás működik: | ||
+ | |||
+ | <code c> | ||
+ | double a = 35.123; | ||
+ | int b = a; | ||
+ | </code> | ||
+ | |||
+ | ==== Karaktersorozatok és számok közötti konverziók ==== | ||
+ | |||
+ | A függvények az stdlib.h programozói könyvtárban találhatók. | ||
+ | |||
+ | <code c> | ||
+ | double atof(const char*) | ||
+ | int atoi(const char*) | ||
+ | long atol(const char*) | ||
+ | |||
+ | int ltoa(int, char*, int) | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== String egész számmá ==== | ||
+ | |||
+ | A következő példában egy s változót hozunk létre, | ||
+ | amelyben 2 karakter szeretnénk tárolni. | ||
+ | A C nyelvben nincs karaktersorozat (string) számára típus. | ||
+ | Ezért egy karakter tömböt fogunk használni. A char s[3], | ||
+ | egy tömb amiben karaktereket tárolhatunk, összesen 3 darabot. | ||
+ | |||
+ | Mi csak két karakter szeretnénk tárolni "15", de a | ||
+ | karaktersorozatot lezáró \0 érték számára is helyet | ||
+ | kell foglalni, ezért 3 byte számára foglalunk helyet. | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | char s[3]; | ||
+ | strcpy(s, "15"); | ||
+ | int a = atoi(s); | ||
+ | </code> | ||
+ | |||
+ | Az **atoi()** függvény a **stdlib.h** programozói könyvtárból érhető el. | ||
+ | Az **strcpy()** függvény a **string.h** programozói könyvtárból érhető el. | ||
+ | |||
+ | A helyfoglalást, néha a malloc() függvénnyel szokták megoldani, | ||
+ | amelynek a használata kicsit összetettebb, de az eredmény egyenértékű | ||
+ | a fenti megoldással: | ||
+ | |||
+ | <code c> | ||
+ | char *s = (char*) malloc(5 * sizeof(char)); | ||
+ | strcpy(s, "15"); | ||
+ | int a = atoi(s); | ||
+ | </code> | ||
+ | |||
+ | A (char*) típusátalakítás jelent. A malloc() a típusfoglalást után | ||
+ | void típust ad vissza, de nekünk char* típusra van szükség. | ||
+ | |||
+ | Ha azt írom char s; akkor egyetlen karakter akarok tárlni az s változóban. | ||
+ | Ha azt írom char *s; akkor egy karaktersorozatra (string) mutató értéket | ||
+ | szeretnék tárolni s-ben. | ||
+ | |||
+ | |||
+ | ==== String hosszú egész számmá ==== | ||
+ | |||
+ | <code c> | ||
+ | char *s = (char*) malloc(5 * sizeof(char)); | ||
+ | strcpy(s, "15"); | ||
+ | long a = atol(s); | ||
+ | </code> | ||
+ | |||
+ | Az atol() függvény a stdlib.h fejállományból érhető el. | ||
+ | |||
+ | |||
+ | ==== String valós számmá ==== | ||
+ | |||
+ | <code c> | ||
+ | char *s = (char*) malloc(5 * sizeof(char)); | ||
+ | strcpy(s, "15"); | ||
+ | float a = atof(s); | ||
+ | </code> | ||
+ | |||
+ | Az atof() függvény a stdlib.h fejállományból érhető el. | ||
+ | ==== Egész stringgé ==== | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | char *s = (char*) malloc(10 * sizeof(char)); | ||
+ | int a = 15; | ||
+ | sprintf(s, "%d", a); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== Egész stringgé ==== | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | char *s = (char*) malloc(10 * sizeof(char)); | ||
+ | float a = 15.7; | ||
+ | sprintf(s, "%f", a); | ||
+ | </code> | ||
+ | |||
+ | ==== Karakter stringgé ==== | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | char *s = (char*) malloc(10 * sizeof(char)); | ||
+ | char ch = 'a'; | ||
+ | sprintf(s, "%c", ch); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== String karakterré ==== | ||
+ | |||
+ | <code c> | ||
+ | char *s = (char*) malloc(10 * sizeof(char)); | ||
+ | strcpy(s, "a"); | ||
+ | char ch = s[0]; | ||
+ | </code> | ||
+ | ===== Gyakorlat 011 ===== | ||
+ | |||
+ | * Válaszoljon a következő kérdésekre: | ||
+ | * Milyen függvénnyel lehet átkonvertálni egy karaktersorozatot (string), egész számmá? | ||
+ | |||
+ | |||
+ | ===== Bevitel ===== | ||
+ | |||
+ | ==== Szám bekérése ==== | ||
+ | |||
+ | Bekéréshez használhatjuk a scanf() függvényt, ami a stdio.h fejállományban van leírva. | ||
+ | A scanf() a printf() függvényhez hasonlóan használható. | ||
+ | |||
+ | ^ Formátumkarakterek ^^ | ||
+ | ^ Karakter ^ mikor használható ^ | ||
+ | | %d | egész szám bekérése | | ||
+ | | %f | valós szám bekérése | | ||
+ | | %lf | valós szám bekérése double típusú változóba | | ||
+ | | %c | karakter bekérése | | ||
+ | | %s | egy szó bekérése | | ||
+ | |||
+ | |||
+ | A scanf() függvénynek minimum két paramétere van. Az első a formátumstring, utána pedig | ||
+ | annyi változó, amennyi a formátumstringben megadtunk, vesszővel tagolva. | ||
+ | A formtáumstringbe egy változó leírását a "%" karakterrel kezdjük, és egy vagy két | ||
+ | formátumkarakterrel fejezzük be. Egy egész szám bekérése például: | ||
+ | scanf("%d", &a); | ||
+ | |||
+ | |||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | int a; | ||
+ | printf("Szam: "); | ||
+ | scanf("%d", &a); | ||
+ | printf("Ezt írtad: %d\n", a); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Ebben a példában egyetlen egész számot kérünk be az "a" változóba. | ||
+ | Vegyük észre az "a" változó előtt a "&" karaktert. Erre azért van szükség, mert | ||
+ | a második paraméter nem a változó neve, hanem annak címe kell legyen. | ||
+ | |||
+ | Ebből következik, hogy egy változó címét úgy kapjuk meg, hogy "&valtozonev" formát | ||
+ | használom. | ||
+ | |||
+ | |||
+ | Több változó is bekérhető egyszerre. | ||
+ | A következő példában egyszerre két változót kérünk be. | ||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | int szam1, szam2; | ||
+ | printf("Két szám: "); | ||
+ | scanf("%d %d", &szam1, &szam2); | ||
+ | printf("Ezeket írtad: %d %d\n", szam1, szam2); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | A program végrehajtásakor, ilyenkor az első szám után 1 vagy több szóközt, | ||
+ | tabulátor vagy sortörést (whitespace karakterek) írok. az első bekért szám | ||
+ | után egy Enter is írható, így a második számot a következő sorba írom be. | ||
+ | |||
+ | ==== Valós szám bekérése ==== | ||
+ | Ha egy float típusú változóba kérünk be számot, a formátumkarakter "f" karakter: | ||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | float szam1; | ||
+ | printf("Valós szám: "); | ||
+ | scanf("%f", &szam1); | ||
+ | printf("Ezt írtad: %f\n", szam1); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Dupla pontos szám bekérésénél a formátumkarakterből kettő kell: "lf". | ||
+ | |||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | double szam1; | ||
+ | printf("Valós szám: "); | ||
+ | scanf("%lf", &szam1); | ||
+ | printf("Ezt írtad: %f\n", szam1); | ||
+ | |||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== Karakter bekérése ==== | ||
+ | |||
+ | Egy karakter bekérése esetén a formátumkarakter egy "c" betű. | ||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | char ch; | ||
+ | printf("Karakter: "); | ||
+ | scanf("%c", &ch); | ||
+ | printf("Ezt írtad: %c\n", ch); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== Szó bekérése ==== | ||
+ | |||
+ | A scanf() függvény alkalmas karaktersorozat beolvasására. | ||
+ | A scanf() azonban a whitespace karaktereket szeparátornak | ||
+ | tekinti, ezért csak szavakat képes beolvasni. | ||
+ | |||
+ | |||
+ | Az alábbi program képes beolvasni egy nevet, amiben nincs szóköz vagy | ||
+ | tabulátor. | ||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() { | ||
+ | char *nev; | ||
+ | nev = (char*) malloc(100 * sizeof(char)); | ||
+ | printf("Név: "); | ||
+ | scanf("%s", nev); | ||
+ | printf("Ezt írtad: %s\n", nev); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Vegyük észre, hogy a scanf() függvény, második paraméterében, a nev változó neve elé | ||
+ | nem tettünk "&" karaktert, pedig azt írtuk, hogy oda cím kell. Azért nem szükséges, | ||
+ | mert a nev változót eleve mutató típusnak deklaráltam, ez a "*" karakter jelzi | ||
+ | a kódban: | ||
+ | |||
+ | char *nev; | ||
+ | |||
+ | Ez pedig azt jelenti, hogy eleve a változó címével dolgozunk. | ||
+ | |||
+ | A char nev[30] egy karaktertömb, amiben maximum 30 karakter tárolható. | ||
+ | Így is használható, így nem szükséges külön malloc() vagy hasonló függvénnyel | ||
+ | helyet foglalni a nev változónak: | ||
+ | char nev[30] | ||
+ | |||
+ | Egy konkrét példa a használatra: | ||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | char nev[30]; | ||
+ | printf("Keresztnév: "); | ||
+ | scanf("%s", nev); | ||
+ | printf("Ezt írtad: %s\n", nev); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | A bekérésnél itt sem kell a "&" karakter. | ||
+ | |||
+ | |||
+ | ==== Mondat bekérése ==== | ||
+ | |||
+ | Az fgets() függvény az állományok olvasására használható és az stdio.h | ||
+ | fejállományban található. Az stdio.h fejlécállományban | ||
+ | deklarálva van egy stdin nevű fájl is, amely billentyűzetet szimbolizálja. | ||
+ | Így egy valódi állomány helyett a billentyűzetet is olvashatjuk az fgets() | ||
+ | függvénnyel. | ||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | char nev[100]; | ||
+ | |||
+ | printf("Név: "); | ||
+ | fgets(nev, 100, stdin); | ||
+ | printf("Ezt írtad: %s\n", nev); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | Az fgets() függvény csak adott számú karaktert kér be, amit a második | ||
+ | paraméterben adhatunk meg. Az fgets() függvény beolvassa az Enter billentyűt is. | ||
+ | |||
+ | Ha szeretnénk sortörést törölni, ami az Enter hatására kerül az | ||
+ | adatszerkezetbe, akkor a következő egyszerű példa erre mutat egy lehetőséget. | ||
+ | |||
+ | A karaktersorozat első elemének címét az „s” mutató tartalmazza: | ||
+ | |||
+ | <code c> | ||
+ | if (s[strlen(s)-1]=='\n') s[strlen(s)-1] = '\0'; | ||
+ | </code> | ||
+ | |||
+ | A fenti utasítás csak akkor tünteti el az utolsó | ||
+ | karaktert, ha az valóban egy sortörés. | ||
+ | |||
+ | Működése: | ||
+ | megnézzük, hogy az utolsó karakter sortörés-e. | ||
+ | Ha igen, akkor lecseréljük karaktersorozat végét | ||
+ | jelölő null karakterre. | ||
+ | |||
+ | |||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() { | ||
+ | char *nev; | ||
+ | nev = (char*) malloc(100 * sizeof(char)); | ||
+ | printf("Név: "); | ||
+ | fgets(nev, 100, stdin); | ||
+ | printf("Ezt írtad: %s\n", nev); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | A Karaktersorozat fejezetben még lesz szó, azok bekéréséről. | ||
+ | |||
+ | ===== Gyakorlat 012 ===== | ||
+ | |||
+ | * Válaszoljon a következő kérdésekre: | ||
+ | * Milyen fejállományban található a scanf() függvény? | ||
+ | * Mire használhatjuk a scanf() függvényt? | ||
+ | * Melyik függvénnyel lehet mondatokat bekérni? scanf() vagy fgets() | ||
+ | |||
+ | ===== Szelekció ===== | ||
+ | |||
+ | ==== if ==== | ||
+ | |||
+ | Bizonyos utasítások végrehajtását feltételhez köthetjük. | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | int a = 5; | ||
+ | if(a > 0) | ||
+ | printf("Pozitív szám\n"); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== if-else ==== | ||
+ | |||
+ | <code c Program01.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | int a = 5; | ||
+ | if(a > 0) | ||
+ | printf("Pozitív szám\n"); | ||
+ | else | ||
+ | printf("Nulla vagy negatív\n"); | ||
+ | |||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== switch ==== | ||
+ | |||
+ | A switch() utasítás paramétereként a C nyelvben csak egész számokat | ||
+ | megvalósító típusok adhatok meg. Például int, char. | ||
+ | |||
+ | <code c Program01.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | int szam; | ||
+ | |||
+ | printf("Szám: "); | ||
+ | scanf("%d", &szam); | ||
+ | |||
+ | switch(szam) { | ||
+ | case 1 : | ||
+ | printf("Egy\n"); break; | ||
+ | case 2 : | ||
+ | printf("Kettő\n"); break; | ||
+ | default: | ||
+ | printf("Más szám\n"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Minden case részt meg kell szakítani egy break utasítással, ha nem szeretnénk | ||
+ | a következő case utáni rész is végrehajtani. | ||
+ | |||
+ | ===== Gyakorlat 013 ===== | ||
+ | |||
+ | * Írjon programot, amely -2 és 2 között generál egy számot. | ||
+ | * A lehetséges számok -2, -1, 0, 1, 2 | ||
+ | * Ha szám nagyobb mint 0, írja a képernyőre, hogy a következőt: "Pozitív" | ||
+ | * Az előző programot, egészítse ki: | ||
+ | * 0 vagy negatív szám esetén írja a képernyőre: "Nulla vagy negatív" | ||
+ | * Az előző programot, írja át: | ||
+ | * 0-nál nagyobb szám esetén kiírja: "Pozitív" | ||
+ | * 0 esetén "Nulla" | ||
+ | * 0-nál kisebb szám esetén: "Negatív" | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Iteráció ===== | ||
+ | |||
+ | ==== for ==== | ||
+ | |||
+ | A for() utasítás, egy növekményes ciklusok számára megvalósított eszköz. | ||
+ | Három paramétere van. A paramétereket ";" karakterrel tagoljuk. | ||
+ | Az első paraméter a kezdőérték. A második paraméter a feltétel, amely | ||
+ | tartalmazza, meddig ismétlődjön a ciklus. Az utolsó paraméter a növekmény. | ||
+ | Itt növeljük a i változó tartalmát. | ||
+ | |||
+ | <code> | ||
+ | for(kezdőérték ; feltétel ; növekmény ) { | ||
+ | //ciklus törzse | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | A ciklus törzsébe írjuk azokat az utasításokat, amelyek szeretnénk | ||
+ | minden egyes iterációban végrehajtani. A ciklus törzsét "{" karakterrel | ||
+ | kezdjük, és "}" karakterrel zárjuk. Ha csak egyetlen utasításunk van, | ||
+ | nem kötelező a kapcsos zárójelek használata. A kód átláthatósága érdekében, | ||
+ | azonban ajánlott használni mindig. | ||
+ | |||
+ | <code c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | int i; | ||
+ | for(i=0; i<10;i++) | ||
+ | printf("%d\n", i); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== while ==== | ||
+ | |||
+ | A while() ciklusnak egyetlen paramétere van, a feltétel. | ||
+ | Ha feltétel igaz, a ciklus törzsében található utasítások | ||
+ | végrehajtódnak. Ha hamis, a ciklus véget ér. | ||
+ | |||
+ | <code c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | int i=0; | ||
+ | while(i<10) { | ||
+ | printf("%d\n", i); | ||
+ | i++; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== do-while ==== | ||
+ | |||
+ | A do-while, egy hátul tesztelő ciklus. A ciklus törzsét először végrehajtja, | ||
+ | és csak ez után vizsgálja meg, hogy a feltétel igaz vagy hamis. | ||
+ | Ha feltétel igaz, a ciklus törzsét újra végrehajtja. Ha hamis, | ||
+ | a ciklus véget ér. | ||
+ | |||
+ | <code c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main(){ | ||
+ | int i=0; | ||
+ | do { | ||
+ | printf("%d\n", i); | ||
+ | i++; | ||
+ | }while(i<10); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | ===== Gyakorlat 014 ===== | ||
+ | |||
+ | * Írjon programot, amely véletlen számokat generál. | ||
+ | * Mentés: nulig.c | ||
+ | * A program írja ki a generált véletlen számot. | ||
+ | * Ha a szám nem 0, akkor generáljon újabb számot. | ||
+ | |||
+ | |||
+ | ===== Összetett típusok ===== | ||
+ | |||
+ | ==== enum ==== | ||
+ | Felsorolt vagy enum típus. Az enum a felsorolt értékeket egészként tárolja. | ||
+ | |||
+ | <code c> | ||
+ | enum {hetfo, kedd, szerda, csutortok pentek}; | ||
+ | </code> | ||
+ | A hetfo 0 értékkel egyenlő, a kedd 1 értékkel, a szerda 2, stb. | ||
+ | |||
+ | <code c enum.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main() { | ||
+ | enum het {hetfo, kedd, szerda, csutortok, pentek, szombat, vasarnap}; | ||
+ | |||
+ | enum het a; | ||
+ | a = hetfo; | ||
+ | if(a==hetfo) | ||
+ | printf("hétfő\n"); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | A fenti példában deklarálunk egy a változót, amely a het napjai értéket veheti | ||
+ | fel: | ||
+ | <code c> | ||
+ | enum het a; | ||
+ | </code> | ||
+ | |||
+ | Az a változóban ez után értékként megadhatjuk a hetfo, kedd, szerda, stb. értékeket. | ||
+ | A példában a hetfo értéket adjuk meg: | ||
+ | <code c> | ||
+ | a = hetfo; | ||
+ | </code> | ||
+ | Ezek után megvizsgálhatjuk, hogy az a változó milyen értéket tartalmaz. | ||
+ | A példában az vizsgáljuk értéke egyenlő-e hetfo-vel: | ||
+ | <code c> | ||
+ | if(a==hetfo) | ||
+ | </code> | ||
+ | |||
+ | Az a változóval persze többet is tehetünk. Például növelhetjük az értéket: | ||
+ | <code c> | ||
+ | a++ | ||
+ | </code> | ||
+ | Egy ilyen növelés után a tartalma már kedd lesz. | ||
+ | |||
+ | Megjegyzés: A későbbiekben még veszünk összetett adattípusokat. Ilyen lesz a | ||
+ | tömb meg a struktúra. | ||
+ | ===== Gyakorlat 015 ===== | ||
+ | |||
+ | * Írjon programot, amelyben az év hónapjait egy enum szerkezetben tárolja. | ||
+ | * Mentés: havi.c | ||
+ | * Írassa ki a hónapokat az 5-dik hónapot. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Karaktersorozat ===== | ||
+ | |||
+ | ==== Tárolás ==== | ||
+ | |||
+ | A karaktersorozat (angolul string) típus nem létezik a C nyelvben. | ||
+ | Ha karaktersorozatot szeretnénk tárolni, akkor egy karakteres mutató | ||
+ | típusú változót hozok létre, ahol a mutatótól kezdve a memóriában | ||
+ | több karaktert is tárolhatok. A mutató típusú változó a karaktersorozat | ||
+ | elejére mutat a memóriában. A sorozat végét egy null karakter adja (nem az | ||
+ | ASCII 0-ás karaktere, hanem egy olyan byte aminek az értéke 0. | ||
+ | Escape szekvenciával jelölve: | ||
+ | |||
+ | <code c> | ||
+ | '\0' | ||
+ | </code> | ||
+ | |||
+ | |||
+ | A példa kedvéért legyen a "Hello" szöveg eltárolva a fe1011 memóriacímtől kezdve. | ||
+ | Az alábbi táblázat mutatja, mit tartalmaz a memória. | ||
+ | |||
+ | ^ betűk | 'H' | 'e' | 'l' | 'l' | 'o' | 0 | | ||
+ | ^ memóriacím | fe1011 | fe1012 | fe1013 | fe1014 | fe1015 | fe1016 | | ||
+ | |||
+ | Az utolsó tehát nem számjegy, hanem egy 0 értékű bájt. | ||
+ | |||
+ | Ezt persze nem kell nekünk a karaktersorozat végére tenni, mert azt | ||
+ | a fordító automatikusan megteszi. Egy ilyen mutató létrehozása | ||
+ | a következő módon valósítható meg: | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | char *s; | ||
+ | </code> | ||
+ | |||
+ | A működéshez le kell még foglalni annyi karakter helyet a memóriában, amennyit | ||
+ | szeretnénk eltárolni. A helyfoglaláshoz két függvényből egyet szoktunk használni: | ||
+ | * malloc() | ||
+ | * calloc() | ||
+ | Mindkettő az stdlib.h programozói könyvtárakban van. | ||
+ | Mi most a malloc() használatát nézzük meg. | ||
+ | |||
+ | A malloc() függvénynek egyetlen paramétere van, mégpedig a | ||
+ | lefoglalandó byte-ok száma. Ha például 30 karaktert | ||
+ | akarunk tárolni, akkor így írhatjuk: | ||
+ | <code c> | ||
+ | malloc(30); | ||
+ | </code> | ||
+ | Ezzel még nincs kész. Meg kell adni, hogy melyik mutatóhoz | ||
+ | rendeljük ezt a 30 byte-ot: | ||
+ | |||
+ | <code c> | ||
+ | s = malloc(30); | ||
+ | </code> | ||
+ | |||
+ | A malloc() azonban void típust ad vissza, amit át kell alakítanunk | ||
+ | char* típusúvá: | ||
+ | |||
+ | <code c> | ||
+ | s = (char*) malloc(30); | ||
+ | </code> | ||
+ | |||
+ | Ez már egy működő helyfoglalás. | ||
+ | |||
+ | A deklarálás és a helyfoglalás együtt ezek után: | ||
+ | |||
+ | <code c> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main() { | ||
+ | char *s; | ||
+ | s = (char*) malloc(30); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | A C nyelven egy karakter eltárolására nem biztos, hogy 1 byte-ot | ||
+ | használunk. Ez függhet az adott rendszertől. A helyfoglaló | ||
+ | függvényt ezért szokás kibővíteni egy vizsgálattal, amely megmondja | ||
+ | mekkora egy char típus az adott rendszeren. Erre a sizeof() | ||
+ | operátort használhatjuk. Az általa visszaadott értéket | ||
+ | szorozzuk be 30-al: | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | #include <stdlib.h> | ||
+ | int main() { | ||
+ | char *s; | ||
+ | s = (char*) malloc(30 * sizeof(char)); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Ha szeretnénk megváltoztatni a lefoglalt hely méretét az következő utasítással tehetjük meg: | ||
+ | * realloc() | ||
+ | |||
+ | A lefoglalt hely felszabadítása: | ||
+ | * free() | ||
+ | |||
+ | |||
+ | Példa: | ||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | int main() { | ||
+ | char *nev; | ||
+ | nev = (char*) malloc(10* sizeof(char)); | ||
+ | strcpy(nev, "Lajos"); | ||
+ | printf("%s\n", nev); | ||
+ | |||
+ | nev = (char*) realloc(nev, 30 * sizeof(char)); | ||
+ | strcpy(nev, "Ferdinándházi Lajos"); | ||
+ | printf("%s\n", nev); | ||
+ | |||
+ | free(nev); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== A változó használata ==== | ||
+ | |||
+ | Most már használhatjuk a "s" változót. A C nyelvben egy | ||
+ | karaktersorozatot nem adhatunk meg egy egyenlőség jel jobboldalán. | ||
+ | Ha egy változóba egy karaktersorozatot szeretnénk elhelyezni, | ||
+ | akkor arra az strcpy() függvény használható, amely a string.h | ||
+ | könyvtárakban találhatók: | ||
+ | |||
+ | <code c> | ||
+ | #include <stdlib> | ||
+ | #include <string.h> | ||
+ | int main() { | ||
+ | char *gyumolcs; | ||
+ | gyumolcs = (char*) malloc(30 * sizeof(char)); | ||
+ | strcpy(gyumolcs, "szilva"); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Ha tömböt használunk, akkor nem szükséges külön helyfoglaló utasítást használni, | ||
+ | például a malloc(), mivel a eleve helyfoglalás történik. Legyen a példa kedvéért | ||
+ | egy "nev" nevű tömb, amiben 30 karakternek foglalok helyet: | ||
+ | char nev[30]; | ||
+ | Itt lefoglaltam a helyet 30 karakter számára, nem kell külön malloc() függvény. | ||
+ | |||
+ | |||
+ | A használatra példa: | ||
+ | <code c> | ||
+ | #include <string.h> | ||
+ | int main() { | ||
+ | char gyumolcs[30]; | ||
+ | strcpy(gyumolcs, "szilva"); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== Kiíratás ==== | ||
+ | |||
+ | Ha egy változóban lévő karaktersorozatot akarunk a képernyőre íratni, akkor | ||
+ | az "s" formátumkódot kell használnunk. A fenti gyumolcs változó tartalmának | ||
+ | képernyőre íratása: | ||
+ | |||
+ | |||
+ | <code c gyumolcs.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib> | ||
+ | #include <string.h> | ||
+ | int main() { | ||
+ | char *gyumolcs; | ||
+ | gyumolcs = (char*) malloc(30 * sizeof(char)); | ||
+ | strcpy(gyumolcs, "szilva"); | ||
+ | printf("%s\n", gyumolcs); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== Bekérés ==== | ||
+ | |||
+ | A karaktersorozatok bekéréséről már volt szó a Bekérés című fejezetben. | ||
+ | Itt most átismételjük a tanultakat. | ||
+ | |||
+ | <code c bekerstr.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib> | ||
+ | |||
+ | int main() { | ||
+ | char *gyumolcs; | ||
+ | gyumolcs = (char*) malloc(30 * sizeof(char)); | ||
+ | scanf("%s" gyumolcs); | ||
+ | printf("%s\n", gyumolcs); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Ha egy változóba egy értéket szeretnénk beolvasni a scanf() függvénnyel, akkor | ||
+ | sosem magát a változó nevét kell megadni, hanem annak címét. Ezt úgy | ||
+ | érjük el, hogy a változó név elé egy "&" karaktert teszünk. | ||
+ | A gyumolcs változó elé mégsem tettünk, mert az eleve mutató típus, | ||
+ | vagyis itt eleve a változó címét kapjuk meg. | ||
+ | |||
+ | A scanf() függvény azonban csak egyetlen szó bekérésére alkalmas, | ||
+ | mert whitespace karakterig olvas. A szóközök után írt karaktereket | ||
+ | már nem tárolja el. | ||
+ | |||
+ | Mondatok beolvasását az fgets() függvénnyel valósítjuk meg. | ||
+ | Rendelkezésre áll a gets() függvény is, de használata | ||
+ | biztonsági kockázatot jelent. | ||
+ | |||
+ | Példa az fgets() használatára. | ||
+ | |||
+ | <code c mondat.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main() { | ||
+ | char *mondat; | ||
+ | mondat = (char*) malloc(30 * sizeof(char)); | ||
+ | printf("Mondat: "); | ||
+ | fgets(mondat, 30, stdin); | ||
+ | printf("Ezt írtad: %s\n", mondat); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Az fgets() valójában fájlok olvasására lett kitalálva, | ||
+ | de van egy speciális fájl, aminek a neve stdin. | ||
+ | Ha ezt a fájlt olvassuk, akkor billentyűzet leütéseit | ||
+ | kapjuk meg. | ||
+ | |||
+ | A nem ajánlott gets() függvényre példa: | ||
+ | <code c noget.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main() { | ||
+ | char *mondat; | ||
+ | mondat = (char*) malloc(30 * sizeof(char)); | ||
+ | printf("Mondat: "); | ||
+ | gets(mondat); | ||
+ | printf("Ezt írtad: %s\n", mondat); | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== Karaktersorozat darabolása ==== | ||
+ | A C nyelvben az strtok() függvényt használhatjuk egy karaktersorozat darabolására. | ||
+ | |||
+ | Szintaktikája: | ||
+ | <code c> | ||
+ | #include <string.h> | ||
+ | char *strtok( char *str1, const char *str2 ); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | Az strtok() függvény visszaad egy következő egységet (tokent), a karaktersorozatból. | ||
+ | A választott karaktersorozat az első paraméter. Második paraméter az elválasztó. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <code c> | ||
+ | strcpy(str, "alma:körte:szilva:barack"); | ||
+ | strtok(str, ":"); | ||
+ | </code> | ||
+ | |||
+ | Az strtok() NULL értékkel tér vissza ha nem talál több tokent. | ||
+ | Az strtok() függvényt úgy használjuk, hogy az első részt | ||
+ | kiolvassuk első paraméternek megadva az str változót: | ||
+ | |||
+ | <code c> | ||
+ | strtok(str, ":"); | ||
+ | </code> | ||
+ | |||
+ | Minden további hívást a NULL értékkel kell végrehajtani: | ||
+ | <code c> | ||
+ | strtok(NULL, ":"); | ||
+ | </code> | ||
+ | |||
+ | A teljes megvalósítás így nézhet ki: | ||
+ | |||
+ | <code c kardarab.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() { | ||
+ | char *str = (char*) malloc(30 * sizeof(char)); | ||
+ | char *token = NULL; | ||
+ | strcpy(str, "alma:körte:szilva:barack"); | ||
+ | |||
+ | token = (char*) strtok(str, ":"); | ||
+ | while(token != NULL) { | ||
+ | printf("%s\n", token); | ||
+ | token = (char*) strtok(NULL, ":"); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Másik példa: | ||
+ | <code c kardarab2.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() { | ||
+ | char *jarmu = (char*) malloc(30 * sizeof(char)); | ||
+ | char elvalaszto[] = ":"; | ||
+ | char *resz = NULL; | ||
+ | strcpy(jarmu, "opel:ford:citroen:mazda"); | ||
+ | |||
+ | resz = (char*) strtok(jarmu, elvalaszto); | ||
+ | while(resz != NULL) { | ||
+ | printf("%s\n", resz); | ||
+ | resz = (char*) strtok(NULL, elvalaszto); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Ugyanaz más szeparátorral: | ||
+ | <code c kardarab3.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() { | ||
+ | char *jarmu = (char*) malloc(30 * sizeof(char)); | ||
+ | char elvalaszto[] = "#"; | ||
+ | char *resz = NULL; | ||
+ | strcpy(jarmu, "opel#ford#citroen#mazda"); | ||
+ | |||
+ | resz = (char*) strtok(jarmu, elvalaszto); | ||
+ | while(resz != NULL) { | ||
+ | printf("%s\n", resz); | ||
+ | resz = (char*) strtok(NULL, elvalaszto); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | A szeparátorokaból lehet több is: | ||
+ | <code c kardarab4.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() { | ||
+ | char *jarmu = (char*) malloc(30 * sizeof(char)); | ||
+ | char elvalaszto[] = "#:;"; | ||
+ | char *resz = NULL; | ||
+ | strcpy(jarmu, "opel#ford:citroen;mazda"); | ||
+ | |||
+ | resz = (char*) strtok(jarmu, elvalaszto); | ||
+ | while(resz != NULL) { | ||
+ | printf("%s\n", resz); | ||
+ | resz = (char*) strtok(NULL, elvalaszto); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Lásd még: | ||
+ | |||
+ | * [[oktatas:programozás:c:c_példaprogram#sztring_darabolás]] | ||
+ | |||
+ | |||
+ | ==== Üres vagy nem üres ==== | ||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int main () { | ||
+ | char szoveg[30]; | ||
+ | if(szoveg[0]) { | ||
+ | printf("Üres\n"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | int main () { | ||
+ | char szoveg[30]; | ||
+ | if(szoveg && szoveg[0]) { | ||
+ | printf("Üres\n"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | int main () { | ||
+ | char szoveg[30]; | ||
+ | strcpy(szoveg, ""); | ||
+ | if(szoveg[0] == '\0') { | ||
+ | printf("Üres\n"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== Összefűzés ==== | ||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | int main () { | ||
+ | char szoveg1[30]; | ||
+ | char szoveg2[30]; | ||
+ | |||
+ | strcpy(szoveg1, "alma"); | ||
+ | strcpy(szoveg2, "körte"); | ||
+ | strcat(szoveg1, szoveg2); | ||
+ | printf("Szöveg: %s\n", szoveg1); | ||
+ | |||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== Összehasonlítás ==== | ||
+ | |||
+ | <code c prog.c> | ||
+ | #include <stdio.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | int main () { | ||
+ | char szoveg[30]; | ||
+ | strcpy(szoveg, "alma"); | ||
+ | |||
+ | if(!strcmp(szoveg, "alma")) { | ||
+ | printf("Egyezik\n"); | ||
+ | }else { | ||
+ | printf("Nem egyezik\n"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ===== Gyakorlat 016 ===== | ||
+ | |||
+ | * Írjon programot, amelyben bekéri egy dolgozó nevét, települését és fizetését. | ||
+ | * Mentés: dole.c | ||
+ | |||
+ | |||
+ | |||
+ | ===== Tömb ===== | ||
+ | ==== Vektor ==== | ||
+ | |||
+ | A tömbök azonos típusú elemek tárolása kitalált adatszerkezet. | ||
+ | Például több egész számot is szeretnék eltárolni. | ||
+ | A változó deklaráció során jeleznünk kell, hogy | ||
+ | most nem egy értékű változóról van szó. ezt a | ||
+ | változó neve után tett szögletes zárójelek jelzik. | ||
+ | |||
+ | <code c> | ||
+ | int tomb[4]; | ||
+ | </code> | ||
+ | Meg kell adnunk azt is hány darab értéket szeretnénk tárolni. | ||
+ | A fenti példában négy darab érték tárolásához foglaltunk memóriát, | ||
+ | amely mindegyik "int" azaz egész típusú lehet. | ||
+ | |||
+ | |||
+ | A tömbnek ez után 4 eleme lehet. Minden elemet egy indexel tudunk | ||
+ | azonosítani. Az első index a nulla: 0, majd a többi szám. | ||
+ | Ebből következik, hogy egy négy elemű tömbnél a legfelső index | ||
+ | 3. | ||
+ | |||
+ | A tömb elemeinek úgy adhatunk értéket, hogy leírjuk a tömb nevét, | ||
+ | utána szögletes zárójelben megadom, melyik indexű elemet akarom | ||
+ | beállítani. | ||
+ | |||
+ | <code c> | ||
+ | int tomb[4]; | ||
+ | tomb[0] = 3; | ||
+ | tomb[1] = 8; | ||
+ | tomb[2] = 5; | ||
+ | tomb[3] = 2; | ||
+ | </code> | ||
+ | |||
+ | Felhasználni ugyanígy tudjuk. Ha szeretném például kiíratni a tömb egyik elemét, azt így tehetem meg: | ||
+ | <code c> | ||
+ | printf("%d\n", tomb[0]); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Tömb kezdőértékkel ==== | ||
+ | A tömböknek rögtön kezdőértéket adhatunk a deklarációban. Az alábbi példában erre látunk példát. | ||
+ | |||
+ | <code c tomb1.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | int tomb[] = {3, 5, 6, 7, 8, 9 }; | ||
+ | printf("%d\n", tomb[0]); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Megadható a tömb nagysága: | ||
+ | <code c> | ||
+ | int tomb[3] = {3, 5, 6}; | ||
+ | </code> | ||
+ | De ez nem kötelező. Ha viszont megadjuk akkor annak értéke nem lehet | ||
+ | kisebb a tömb kezdőértékeinek a számánál. | ||
+ | |||
+ | Ez még helyes. | ||
+ | <code c> | ||
+ | int tomb[5] = {3, 5, 6}; | ||
+ | </code> | ||
+ | Ez már helytelen: | ||
+ | |||
+ | <del>int tomb[2] = {3, 5, 6};</del> | ||
+ | |||
+ | |||
+ | |||
+ | <code c tomb.c> | ||
+ | #include <stdio.h> | ||
+ | #include <math.h> | ||
+ | #define MAX 2 | ||
+ | typedef int Ttomb[MAX]; | ||
+ | |||
+ | void kiir(int *tomb) { | ||
+ | tomb[0]=8; | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | Ttomb tomb; | ||
+ | |||
+ | tomb[0] = 5; | ||
+ | tomb[5] = 3; | ||
+ | |||
+ | kiir(tomb); | ||
+ | printf("%d\n", tomb[0]); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Tömb bejárása ==== | ||
+ | |||
+ | <code c tomb.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | int tomb[] = {3, 8, 5, 6, 2, 9 }; | ||
+ | int i; | ||
+ | for(i=0; i<6; i++) { | ||
+ | printf("%d\n", tomb[i]); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Tömb mérete ==== | ||
+ | |||
+ | <code c> | ||
+ | int tomb[] = {3, 8, 5, 6, 2, 9 }; | ||
+ | int n = sizeof tomb / sizeof tomb[0]; | ||
+ | </code> | ||
+ | Vagy: | ||
+ | |||
+ | <code c> | ||
+ | int tomb[] = {3, 8, 5, 6, 2, 9 }; | ||
+ | size_t meret = sizeof(tomb) / sizeof(tomb[0]); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | Vagy: | ||
+ | <code c> | ||
+ | int tomb[] = {3, 8, 5, 6, 2, 9 }; | ||
+ | int n = sizeof tomb / sizeof *tomb; | ||
+ | </code> | ||
+ | |||
+ | |||
+ | Komplett példa: | ||
+ | <code c tomb.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | int tomb[] = {3, 8, 5, 6, 2, 9 }; | ||
+ | int n = sizeof tomb / sizeof *tomb; | ||
+ | int i; | ||
+ | for(i=0; i<n; i++) { | ||
+ | printf("%d\n", tomb[i]); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Mátrix ==== | ||
+ | A tömböknek lehet két kiterjedése is. Ekkor mátrixról beszélünk. | ||
+ | A tömb felépítése ekkor hasonlít a matematikában tanult mátrixhoz, | ||
+ | amelynek kiterjedése kétirányú. | ||
+ | |||
+ | Lássunk egy példát egy mátrixra: | ||
+ | |||
+ | | 3 | 12 | 8 | 9 | | ||
+ | | 2 | 15 | 17 | 7 | | ||
+ | | 11 | 4 | 3 | 18 | | ||
+ | |||
+ | === Mátrix létrehozása C nyelven === | ||
+ | |||
+ | |||
+ | Az alábbi egyszerű mátrixot szeretnénk megvalósítani: | ||
+ | | 3 | 12 | 8 | 9 | | ||
+ | | 2 | 15 | 17 | 7 | | ||
+ | |||
+ | <code c> | ||
+ | int tomb[2][4]; | ||
+ | </code> | ||
+ | Ez két sort és 4 oszlopot jelent. | ||
+ | |||
+ | |||
+ | Értékadás: | ||
+ | <code c> | ||
+ | int tomb[2][4]; | ||
+ | //Első sor: | ||
+ | tomb[0][0] = 3; | ||
+ | tomb[0][1] = 12; | ||
+ | tomb[0][2] = 8; | ||
+ | tomb[0][3] = 9; | ||
+ | //Második sor: | ||
+ | tomb[1][0] = 2; | ||
+ | tomb[1][1] = 15; | ||
+ | tomb[1][2] = 17; | ||
+ | tomb[1][3] = 7; | ||
+ | </code> | ||
+ | |||
+ | |||
+ | {{:oktatas:programozas:c:c_ket_dimenzios_tomb.png?400|}} | ||
+ | |||
+ | === Mátrix kezdőértéke === | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | int tomb2[2][4] = { | ||
+ | {3, 13, 8, 9}, | ||
+ | {2, 15, 17, 7} | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | ==== Feltöltés ==== | ||
+ | |||
+ | GCC-ben: | ||
+ | <code c> | ||
+ | int tomb[10] = {[0 ... 9] = 5}; | ||
+ | </code> | ||
+ | |||
+ | Egyébként meg egy for ciklussal. | ||
+ | |||
+ | |||
+ | ==== Tömb paraméterként ==== | ||
+ | |||
+ | Tömb átadása paraméterként: | ||
+ | |||
+ | <code c rendez.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | void rendez(int *tomb) { | ||
+ | if(tomb[0] > tomb[1]) { | ||
+ | int tmp = tomb[0]; | ||
+ | tomb[0] = tomb[1]; | ||
+ | tomb[1] = tmp; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | int tomb[2]; | ||
+ | tomb[0] = 3; | ||
+ | tomb[1] = 2; | ||
+ | rendez(tomb); | ||
+ | printf("%d %d\n", tomb[0], tomb[1]); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Az átadott tömb cím szerint adódik át. | ||
+ | |||
+ | ===== Gyakorlat 017 ===== | ||
+ | |||
+ | * Írjon programot, amelyben valós számokat tárol. | ||
+ | * Mentés: valostomb.c | ||
+ | |||
+ | |||
+ | |||
+ | ===== Saját típus ===== | ||
+ | ==== A saját típusok alapjai ==== | ||
+ | |||
+ | |||
+ | Vannak olyan esetek amelyekben célszerű saját típust létrehozni. | ||
+ | Először nézzük meg, hogyan kell saját típust létrehozni. | ||
+ | |||
+ | |||
+ | Általánosan: | ||
+ | <code c> | ||
+ | typedef típus újtipusnév; | ||
+ | </code> | ||
+ | |||
+ | Legyen a példa kedvéért egy új típus amely megegyezik az egészeket tárolni képes int típussal: | ||
+ | <code c> | ||
+ | typedef int TEgesz; | ||
+ | </code> | ||
+ | |||
+ | Ezek után, például így használhatom: | ||
+ | <code c> | ||
+ | TEgesz szam = 5; | ||
+ | </code> | ||
+ | |||
+ | A "TEgesz" azonosítót mint típust használtam fel. | ||
+ | |||
+ | Ennek persze kevés értelme lehet, de annál több haszna van, | ||
+ | tömbtípusok létrehozásánál, különösen ha a tömböket | ||
+ | paraméterként szeretném átadni. Lássunk egy tömbtípus létrehozását: | ||
+ | |||
+ | <code c> | ||
+ | typedef int TEgeszTomb[100]; | ||
+ | </code> | ||
+ | |||
+ | Ezek után így használhatom: | ||
+ | |||
+ | <code c> | ||
+ | TEgeszTomb tomb; | ||
+ | tomb[0] = 5; | ||
+ | tomb[1] = 8; | ||
+ | //... | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== Saját típus a paraméterlistában ==== | ||
+ | |||
+ | Még hasznosabb, amikor a saját típust paraméterlistában használjuk. | ||
+ | |||
+ | |||
+ | |||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | typedef TEgeszTomb[100]; | ||
+ | |||
+ | |||
+ | int sum(TEgeszTomb ptomb) { | ||
+ | int osszeg = 0, i; | ||
+ | for(i=0; i<5; i++) | ||
+ | osszeg = osszeg + ptomb[i]; | ||
+ | return osszeg; | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | |||
+ | TEgeszTomb tomb = {3, 5, 8, 2, 7}; | ||
+ | |||
+ | printf("%d\n", sum(tomb)); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Fájlkezelés ===== | ||
+ | |||
+ | Az állományok írása és olvasása a stdio.h könyvtárak függvényei teszik lehetővé. | ||
+ | A C nyelvben egy a fájlváltozó típusa FILE. Mutatóként kell létrehoznunk, ezért | ||
+ | fájlmutatóról fogunk beszélni. A fájlokat először mindig meg kell nyitni, használat | ||
+ | után pedig bezárni. A megnyitásnak több módja is van, amelyek a következő táblázatban | ||
+ | találhatók. | ||
+ | |||
+ | ^ Mód ^ Leírás ^ | ||
+ | | "r" | Megnyitás olvasásra. | | ||
+ | | "w" | Megnyitás írásra. | | ||
+ | | "a" | Megnyitás hozzáfűzésre. | | ||
+ | | "r+" | Olvasható-írható mód. Írás a fájl elejére. | | ||
+ | | "w+" | Olvasható-írható mód. Az fájl tartalma elvész. | | ||
+ | | "a+" | Olvasható-írhatód mód. Kezdetben a fájlmutató elöl van. Az írás viszont a fájl végére történik | | ||
+ | |||
+ | A megnyitott állományt csatorna névvel is szokás illetni. A megnyitás az fopen() függvénnyel történik. | ||
+ | Az fopen() szintaxisa: | ||
+ | fájlmutató = fopen(char *állománynév, char *mód) | ||
+ | |||
+ | Például: | ||
+ | <code c> | ||
+ | FILE *fp; | ||
+ | fp = fopen("adat.txt", "w"); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Írás ==== | ||
+ | |||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | FILE *f; | ||
+ | f = fopen("adat.txt","w"); | ||
+ | fputs("alma",f); | ||
+ | fputs("szilva",f); | ||
+ | fputs("barack",f); | ||
+ | fclose(f); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== Hozzáfűzés ==== | ||
+ | |||
+ | |||
+ | <code c main.c> | ||
+ | #include <stdio.h> | ||
+ | int main() { | ||
+ | FILE *f; | ||
+ | f = fopen("adat.txt","a"); | ||
+ | fputs("Valami",f); | ||
+ | fclose(f); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | ==== Olvasás fájlból ==== | ||
+ | |||
+ | <code txt adat.txt> | ||
+ | alma | ||
+ | szilva | ||
+ | barack | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | <code c olvas.h> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main() { | ||
+ | FILE *fp = fopen("adat.txt", "r"); | ||
+ | char *str = (char*) malloc(30 * sizeof(char)); | ||
+ | |||
+ | while(!feof(fp)) { | ||
+ | fgets(str, 30, fp); | ||
+ | if(!feof(fp)) | ||
+ | printf("%s", str); | ||
+ | } | ||
+ | fclose(fp); | ||
+ | } | ||
+ | </code> | ||
+ | A fenti program képes az összes sort gond nélkül kiírni, akár van | ||
+ | az utolsó sor végén sortörés, akár nincs. | ||
+ | |||
+ | |||
+ | A következő megoldás működik, de csak akkor, ha az utolsó sor után van sortörés: | ||
+ | |||
+ | <code c olvas.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | int main() { | ||
+ | FILE *fp = fopen("adat.txt", "r"); | ||
+ | char *str = (char*) malloc(30 * sizeof(char)); | ||
+ | |||
+ | fgets(str, 30, fp); | ||
+ | while(!feof(fp)) { | ||
+ | printf("%s", str); | ||
+ | fgets(str, 30, fp); | ||
+ | } | ||
+ | fclose(fp); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | Az adat.txt állományhoz írunk áradatokat. | ||
+ | |||
+ | <code txt adat.txt> | ||
+ | alma 250 | ||
+ | szilva 300 | ||
+ | barack 450 | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | <code c olvas.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <string.h> | ||
+ | int main() { | ||
+ | FILE *fp = fopen("adat2.txt", "r"); | ||
+ | char *str = (char*) malloc(30 * sizeof(char)); | ||
+ | char *nev = (char*) malloc(30 * sizeof(char)); | ||
+ | int ar; | ||
+ | |||
+ | while(!feof(fp)) { | ||
+ | fgets(str, 30, fp); | ||
+ | if(!feof(fp)) { | ||
+ | sscanf(str, "%s %d\n", nev,&ar); | ||
+ | printf("%s %d\n", nev, ar); | ||
+ | } | ||
+ | } | ||
+ | fclose(fp); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | <code c olvas.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <string.h> | ||
+ | int main() { | ||
+ | FILE *fp = fopen("adat2.txt", "r"); | ||
+ | char *str = (char*) malloc(30 * sizeof(char)); | ||
+ | char *nev = (char*) malloc(30 * sizeof(char)); | ||
+ | int ar; | ||
+ | |||
+ | while(!feof(fp)) { | ||
+ | fgets(str, 30, fp); | ||
+ | if(!feof(fp)) { | ||
+ | sscanf(str, "%s", nev); | ||
+ | sscanf(str + strlen(nev), "%d", &ar); | ||
+ | printf("%s %d\n", nev, ar); | ||
+ | } | ||
+ | } | ||
+ | fclose(fp); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Olvasás karakterenként ==== | ||
+ | |||
+ | <code c olvaskar.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() { | ||
+ | |||
+ | FILE *fp = fopen("adat.txt", "r"); | ||
+ | char *str = (char*) malloc(30 * sizeof(char)); | ||
+ | |||
+ | char ch; | ||
+ | while((ch = fgetc(fp)) != -1) | ||
+ | printf("%c", ch); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | A következő példa megegyezik az előzővel, kivéve, hogy a -1 értéket egy állandóból vesszük, melynek | ||
+ | neve EOF. | ||
+ | |||
+ | |||
+ | |||
+ | <code c olvaseof.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | int main() { | ||
+ | |||
+ | FILE *fp = fopen("adat.txt", "r"); | ||
+ | char *str = (char*) malloc(30 * sizeof(char)); | ||
+ | |||
+ | char ch; | ||
+ | while((ch = fgetc(fp)) != EOF) | ||
+ | printf("%c", ch); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Hibakezelés ==== | ||
+ | |||
+ | Ha az állomány megnyitása során probléma van, akkor NULL értékkel tér vissza. | ||
+ | Ennek segítségével vizsgálhatjuk, hogy fájl megnyitás sikeres volt-e. | ||
+ | |||
+ | <code c hibakez.c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <errno.h> | ||
+ | int main() { | ||
+ | FILE *fp; | ||
+ | if((fp= fopen("adat.txta", "r"))== NULL) { | ||
+ | perror("Hiba a fájl megnyitása során\n"); | ||
+ | printf("Hibaszám: %d.\n", errno); | ||
+ | exit(-1); | ||
+ | } | ||
+ | |||
+ | char *str = (char*) malloc(30 * sizeof(char)); | ||
+ | |||
+ | fgets(str, 30, fp); | ||
+ | while(!feof(fp)) { | ||
+ | printf("%s", str); | ||
+ | fgets(str, 30, fp); | ||
+ | } | ||
+ | fclose(fp); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ===== Függvények ===== | ||
+ | |||
+ | Érték szerint átadott paraméterek: | ||
+ | <code c> | ||
+ | int novel(int szam) { | ||
+ | return szam + 1; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | Globális paraméterek | ||
+ | |||
+ | <code c> | ||
+ | int szam = 0; | ||
+ | |||
+ | void novel() { | ||
+ | szam = szam + 1; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | Cím szerint átadott paraméterek | ||
+ | |||
+ | <code c> | ||
+ | void novel(int *szam) { | ||
+ | *szam = *szam + 1; | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | int szam = 0; | ||
+ | novel(&szam); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ===== stdlib.h ===== | ||
+ | |||
+ | ==== Memóriafoglalás ==== | ||
+ | |||
+ | void* calloc(size_t, size_t) | ||
+ | void* malloc(size_t) | ||
+ | void* realloc(void*, size_t) | ||
+ | void free(void*) | ||
+ | void abor(void) // Program vége | ||
+ | void exit(int) | ||
+ | |||
+ | ==== Egyéb ==== | ||
+ | |||
+ | int system(const char*) // Egy külső program futtatása | ||
+ | char* getenv(const char*) // Környezeti változó lekérdezése | ||
+ | | ||
+ | void _beep(unsigned int, unsigned int) // hang: frekvencia, másodperc | ||
+ | void _sleep(unsigned long) // Várakozás ezredmásodpercig | ||
+ | |||
+ | ===== time.h ===== | ||
+ | |||
+ | |||
+ | ==== localtime() ==== | ||
+ | |||
+ | Szintaxis: | ||
+ | #include <time.h> | ||
+ | struct tm *localtime( const time_t *time ); | ||
+ | |||
+ | |||
+ | |||
+ | Leírás: | ||
+ | A localtime() függvény átkonvertálja a naptári időt helyi időbe. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== time() ==== | ||
+ | |||
+ | Szintaxis | ||
+ | #include <time.h> | ||
+ | time_t time( time_t *time ); | ||
+ | |||
+ | |||
+ | |||
+ | Leírás: | ||
+ | |||
+ | A time() függvény visszatér az aktuális idővel, vagy -1-gyel ha hiba történik. Ha van megadunk egy time paramétert, | ||
+ | akkor az aktuális idő eltárolódik ebben a változóban. | ||
+ | |||
+ | |||
+ | |||
+ | ==== strftime ==== | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | Az strftime() függvény dátum és időt formáz a time kimenetből egy formátum sztring alapján. A visszatérési érték szintén egy sztring. Az egyes formátumokhoz tartozó formátum kódok a következő táblázat mutatja: | ||
+ | |||
+ | |||
+ | ^ Kód ^ Jelentés ^ | ||
+ | | %a | a hét napja, rövidítve | | ||
+ | | %A | a hét napja, kiírva | | ||
+ | | %b | a hónap neve, rövidítve | | ||
+ | | %B | a hónap neve, kiírva | | ||
+ | | %c | az alapértelmezett dátumformátum | | ||
+ | | %d | nap, 2 számjeggyel (01 .. 31) | | ||
+ | | %H | óra, 24-órás formátumban, 2 számjeggyel (00 .. 23) | | ||
+ | | %I | óra, 12-órás formátumban, 2 számjeggyel (01 .. 12) | | ||
+ | | %j | év napja, 3 számjegy (001 .. 366) | | ||
+ | | %m | hónap, számmal (01 .. 12) /van kitöltő szóköz/ | | ||
+ | | %M | perc, 2 számjegy | | ||
+ | | %p | "am" vagy "pm", az adott időpont délelőtt, vagy délután | | ||
+ | | %S | másodperc, 2 számjegy | | ||
+ | | %U | az aktuális év hányadik hetében járunk, a hét vasárnappal kezdődik, vagyis az "01" hét január első vasárnapján kezdődik. /Az első hét előtti napokat "00" hétnek jelzi/ | | ||
+ | | %w | hét napja számmal, a vasárnap a 0 | | ||
+ | | %W | év hete, az év első hétfőjén kezdődik az "01" hét | | ||
+ | | %x | alapértelmezett dátumformátum idő nélkül | | ||
+ | | %X | alapértelmezett időpontformátum dátum nélkül | | ||
+ | | %y | év 2 számjeggyel (00 .. 99) | | ||
+ | | %Y | év, évszázaddal együtt | | ||
+ | | %Z | időzóna neve, 3 betű | | ||
+ | | %% | a "%" karakter | | ||
+ | |||
+ | |||
+ | ==== Példa ==== | ||
+ | |||
+ | time_t datum = time(NULL); | ||
+ | strftime(sz, sizeof(sz), "%c", &datum); | ||
+ | printf("%s\n", sz); | ||
+ | |||
+ | |||
+ | ===== Fogalmak ===== | ||
+ | |||
+ | |||
+ | ==== Függvény ==== | ||
+ | |||
+ | |||
+ | A C nyelvben ha utasításról beszélek, gyakran azt mondjuk helyette, hogy függvény. Ez azért van | ||
+ | mert minden utasítás valójában egy függvényként van megvalósítva. | ||
+ | |||
+ | ==== Kimeneti eszköz ==== | ||
+ | |||
+ | Mivel számítógépről beszélünk, ezért ez monitor, nyomtató vagy más ehhez hasonló eszköz. | ||
+ | |||
+ | ==== Standard Output ==== | ||
+ | |||
+ | A Standard Output az alapértelmezett kimeneti eszközt jelenti. Szokásos módon ez a monitor | ||
+ | képernyője. Tehát ha azt mondom „A Standard Outputra írok”, ez azt jelenti, hogy a képernyőre | ||
+ | írok. | ||
+ | |||
+ | ==== Standard Input ==== | ||
+ | |||
+ | A Standard Input az alapértelmezett bemeneti eszköz. Szokásos módon ez a billentyűzet. | ||
+ | A Standard Inputról olvasás így billentyűzetről bevitt adatokat jelenti. | ||
+ | |||
+ | A Standard Outputot és a Standard Inputot együtt röviden stdio néven rövidítjük. | ||
+ | |||
+ | ==== Paraméter ==== | ||
+ | |||
+ | |||
+ | Amikor írunk egy „saját” függvényt, előfordulhat, hogy a hívó programból adatokat akarunk átadni. | ||
+ | Ezeket az adatokat a függvény neve után zárójelbe írjuk és paramétereknek nevezzük. | ||
+ | |||
+ | ==== Utasítás ==== | ||
+ | |||
+ | |||
+ | Megmondjuk a gépnek mit tegyen. Ezt úgy tesszük, hogy leírjuk a nevét. Valójában ez egy | ||
+ | függvény neve. A C nyelvben ha nincs egy utasításnak paramétere akkor is kötelező a zárójelek | ||
+ | kitétele. Minden utasítást pontosvessző (;) zár le! Létezik üres utasítás is, ami egy pontosvessző | ||
+ | önmagában. | ||
+ | |||
+ | |||
+ | ==== Előfordító ==== | ||
+ | |||
+ | A C fordító a forráskód lefordítása előtt elvégez egy ún. előfordítást. Az előfordítás az előfordítói utasításokon történik. Az előfordító utasítások „#” jellel kezdődnek. Előfordítással fordított utasítás típusok: | ||
+ | * fájlok beépítése | ||
+ | * makrók | ||
+ | * feltételes fordítás | ||
+ | |||
+ | Példák az előfordítói utasításokra: | ||
+ | #include <stdio.h> | ||
+ | #define A 3 | ||
+ | |||