C++ alapismeretek Történet
Eötvös Loránd Tudományegyetem Informatikai Kar
• Wikipédia: a C++ általános célú, magas szintű programozási nyelv, mely támogatja az imperatív, az objektum-orientált, valamint a sablonprogramozást
Alkalmazott modul: Programozás
• Első változata 1979-ben készült (Bjarne Stroustroup) a C programozási nyelvből, eredetileg C with Objects névvel
C++ alapismeretek
• célja: objektumorientált programozási lehetőségekkel való kiegészítése a nyelvnek • jelenleg a 2014-es szabványt használjuk (C++14) • Többek szerint közepes szintű nyelvnek tekinthető, mert alacsonyabb szinten használatos utasítások (bit szintű műveletek, direkt memóriaműveletek,…) is használhatóak
© 2015 Giachetta Roberto
[email protected] http://people.inf.elte.hu/groberto
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Történet
A „Hello World” program
• Az alap nyelv csak konzol-alkalmazások készítésére szolgál
Feladat: Írjuk ki a Hello World! feliratot a képernyőre.
2
• sok kiegészítő található hozzá, amelyek segítségével sok megoldást implementálni lehet (pl. grafikus környezet) Megoldás:
• A világ egyik leggyakrabban használt programozási nyelve:
// fejrész: #include
// további fájlok beolvasása using namespace std; // használni kívánt névtér
• a szabvány teljesen szabad, ingyenes • önmagában minden lehetséges nyelvi eszközt megad, amelyre a programozás során szükségünk lehet
// törzsrész: int main() // főprogram deklaráció { cout << "Hello, World!" << endl; // kiírás return 0; // érték visszaadás } // főprogram vége
• gyors, hatékony programokat készíthetünk benne • sok fordító, fejlesztőkörnyezet készült hozzá • több nyelv alapjául szolgált: JAVA, C#, PHP, … ELTE TTK, Alkalmazott modul: Programozás
3
ELTE TTK, Alkalmazott modul: Programozás
4
C++ alapismeretek
C++ alapismeretek
Fejrész
Fejrész
• A program elején van a fejrész, ami tartalmazza:
• A C++ utasításai és típusai több fájlban helyezkednek el, az írandó programok általában önmagukban nem működőképesek, használnunk kell a további fájlokban megírt utasításokat
• a program működéséhez szükséges további fájlok neveit • a programban használt névtereket
• Mi is elhelyezhetjük a programkódunkat több fájlban (majd később lesz), amiket szintén használni szeretnénk
• a programban előre definiált elnevezések (makrók) értékeit • ezek olyan elnevezés - érték párok, amelyeknél a fordítás előtt behelyettesíti a programban az első érték összes előfordulását a második értékkel • szerkezete: #define <elnevezés> <érték> • pl.: #define ALMA 100
• Ehhez meg kell adnunk a használandó fájlok neveit - a beépített fájlok között keres, amik a C++ környezetben megvannak
• #include • #include "fájlnév"
// az ALMA helyére mindenhova 100-t ír
• Ekkor a program fordításakor a berakott fájlok teljes tartalma átmásolódik a mi programunkba
• tartalmazhat összetett kifejezéseket is ELTE TTK, Alkalmazott modul: Programozás
– aktuális könyvtárban keres
5
ELTE TTK, Alkalmazott modul: Programozás
6
1
C++ alapismeretek
C++ alapismeretek
Névterek
Törzsrész
• Amikor további beépített fájlokat használunk a programban, az ott található utasítások csoportosítva vannak úgynevezett névterekbe, hogy megkülönböztessük a különböző funkciókat ellátó utasításokat
• A programok törzsrésze függvényekből áll • a függvény a program egy saját működéssel rendelkező része, amely értéket ad vissza az őt meghívó utasításnak • a visszaadott érték a visszatérési érték, amelyet a return utasítással adunk meg, a függvény működése mindig leáll ennél a pontnál, amit utána írunk, az nem kerül végrehajtásra
• A programban meg kell mondanunk, hogy melyik névtérből származnak a használni kívánt utasítások, ennek két módja: • a fejrészben kiadjuk a using namespace ;, utasítást, ekkor a fájl hátralevő részében az adott névteret használjuk
• az általunk írt programban a programhívó eljárás a main függvényt hívja meg (az pedig további függvényeket hívhat meg, ez majd lesz később…)
• a használandó utasítást a következő a ::<parancsnév> formában írjuk le, ekkor megmondjuk, hogy a parancs a megadott névtérből való, pl.: std::cout
• A main függvény egész típusú (visszatérési értékű), ezért a függvény vége előtt vissza kell adnunk egy egész számot
ELTE TTK, Alkalmazott modul: Programozás
7
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Törzsrész
Vezérlési szerkezetek
• A main függvény szerkezete:
• Szekvencia:
int main() { … return 0; }
8
• az utasítások végére ;-t kell tenni • egy sorban lehet több utasítást is írni, illetve egy utasítást lehet több sorban is írni
// utasítások // visszaadunk egy 0-s értéket
• Programblokk:
• A main függvényben az úgynevezett hibakódot szokás visszaadni, azaz, hogy hiba történt-e a program futása során (0: nem történt hiba, 1,2,…: valamilyen hiba történt)
• utasítások csoportosításai • egy programblokk: { } • programblokkok tartalmazhatnak további blokkokat, így egymásba ágyazott szerkezetet készíthetünk, pl.:
• A hibakód jelentése nincs előre szabályozva, a programozó dönti el, hogy a visszaadott hibakód milyen hibát kíván reprezentálni (ezt például dokumentációba lehet leírni) ELTE TTK, Alkalmazott modul: Programozás
{ { } { } } 9
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Vezérlési szerkezetek
Vezérlési szerkezetek
• Elágazás:
• Többágú elágazás:
• feltételtől függően különböző utasítások végrehajtása:
• egy változó aktuális értékének függvényében futtat le adott utasításokat
if // logikai kifejezés { } else { }
• csak meghatározott értékek esetén fut le az adott ág, nem lehet értékhatárokat, illetve egyéb kifejezéseket megadni switch(){ case <érték1>: break; case <érték2>: break; … default: }
• a hamis ág itt is elhanyagolható, ekkor a szerkezet: if { }
• ha csak egy utasítást akarunk írni, a blokkot elhagyhatjuk: if else ELTE TTK, Alkalmazott modul: Programozás
10
11
ELTE TTK, Alkalmazott modul: Programozás
12
2
C++ alapismeretek
C++ alapismeretek
Vezérlési szerkezetek
Vezérlési szerkezetek
• egy ág végét a break utasítással jelöljük, ha ezt elmulasztjuk a következő ág első utasítása következik
• Ciklus:
• lehet különben ágat készíteni, ennek jelölése default
• utasítások ismétlése a megadott feltétel függvényében, a feltétel logikai értékű kifejezés lehet
• lehetőségünk üres ágakat is írni, ezzel lehetőségünk van több értékhez ugyanazt az ágat rendelni
• a ciklusmag egy, vagy több utasításból állhat, ha csak egy utasítást írunk, nem kell blokkot használni
switch(){ case <érték1>: case <érték2>: case <érték3>: // ezek az utasítások a három érték // bármelyike esetén lefutnak break; … ELTE TTK, Alkalmazott modul: Programozás
• előtesztelő: while { }
• utántesztelő: do { } while ; 13
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Vezérlési szerkezetek
Megjegyzések
• a számláló szerkezete itt teljesen elkülönül:
• Megjegyzést bárhol elhelyezhetünk a kódban
for (<számláló kezdőérték>; <számláló feltétele>; <számláló inkrementálás>){ }
• elhelyezhetjük a sor végén, akkor az utána a sorba írt utasításokat nem veszi figyelembe: ; // megjegyzés
• elhelyezhetjük a sor közben, illetve bármely utasítás közben (ügyelve arra, hogy nem szó közben írjuk), ekkor a komment után lévő utasításokat figyelembe veszi
• de természetesen előtesztelő ciklussal is meg lehet fogalmazni a számlálót, az eredmény ugyanaz lesz:
; /* megjegyzés */ ; /* megjegyzés */ /* megjegyzés */ ;
<számláló kezdőérték>; while (<számláló feltétele>){ <számláló inkrementálás> } ELTE TTK, Alkalmazott modul: Programozás
15
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Operátorok
Operátorok
• Értékadás (=)
• Értékmódosítások
• jelentése: a balérték egyezzen meg a jobbértékkel
• eggyel növeli, vagy csökkenti a szám értékét
• a bal oldalán változó állhat, a jobb oldalán egy kifejezés (amelynek eredménye kompatibilis a változó típusával)
• inkrementálás (++), dekrementálás (––)
• pl.: b = 3
• két módon lehet megadni, a változó előtt, illetve mögött, a különbség a végrehajtási sorrendben van (ha előtte értékadás található, akkor történhet az érték átadása a módosítás előtt, illetve után is) • pl.: b = a++; // a értékét átadjuk b-nek, majd
• eredményünk a bemenettel megegyező típusú • összeadás (+), kivonás (–), szorzás (*), osztás (/), maradékvétel (%)
// a-t növeljük b = ++a; // a értékét növeljük, majd // átadjuk b-nek
// a modulo 3
ELTE TTK, Alkalmazott modul: Programozás
16
• pl.: a++ // növeljük meg a értékét 1-gyel
// a b értéke legyen 3
• Matematikai műveletek
• pl.: a % 3
14
17
ELTE TTK, Alkalmazott modul: Programozás
18
3
C++ alapismeretek
C++ alapismeretek
Operátorok
Operátorok
• Összehasonlító műveletek
• Speciális értékadások:
• eredményük logikai típusú lesz
• add hozzá (+=), vond ki belőle (-=), vedd modulo (%=), …
• a balértéket hasonlítja a jobbértékkel
• pl.: a = a+2 helyett a+=2, a = a%2 helyett a %= 2
• egyenlőségvizsgálat (==), különbségvizsgálat (!=), kisebb (<), nagyobb (>), kisebb, vagy egyenlő (<=), nagyobb, vagy egyenlő (>=)
• feltételesen tedd egyenlővé (>>=, <<=), pl.: a >>=2 jelentése: ha a nagyobb kettőnél, akkor legyen az értéke 2
• pl.: b == 3
• Tömbelem indexelése ([])
// a b értéke egyenlő-e 3-mal?
• tömb (vektor), illetve szöveg bármely elemét lekérdezhetjük, módosíthatjuk
• Logikai műveltek • logikai értékeken végeznek logikai eredményű műveletet • tagadás (!), és (&&), vagy (||)
• az indexelés 0-tól kezdődik
• pl.: !(a && b) // nem (a és b)
• pl.: a[3]
ELTE TTK, Alkalmazott modul: Programozás
19
// az a tömb 3-as indexű eleme
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Operátorok
Változók
• Bitenkénti műveletek
• Változókat bárhol deklarálhatunk a kódunkban, nincs külön deklarációs rész
• az értékeink tényleges eltárolt bináris változatát is tudjuk manipulálni
• ha minden programblokkon, függvényen kívül deklaráljuk őket, akkor a deklarálás pontjától a program végéig bárhol (bármilyen függvényben, illetve programblokkban) elérhetőek lesznek, ezek az úgynevezett globális változók
• bitenkénti eltolás balra (<<), bitenkénti eltolás jobbra (>>), komplemens képzés (~), bitenkénti és (&), bitenkénti vagy (|), kizáró vagy (^) • pl.: a ^ b
20
• ha valamely programblokkban, függvényben deklaráljuk őket, akkor csak annak végéig lesznek elérhetőek, utána megsemmisülnek, és nem lehet hivatkozni rájuk, ezeket lokális változóknak nevezzük
// a XOR b
• globális változók használatát lehetőleg kerüljük el, mert könnyen vezetnek hibás működéshez ELTE TTK, Alkalmazott modul: Programozás
21
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Konstansok
Típusok
• A C++ erősen típusos nyelv, azaz minden változónak létrehozásakor meg kell adnunk a típusát, és azt a fordító nyomon fogja követni a program lefordításakor
• Logikai típus (bool): • felvehető értékek: true, false • meg lehet adni neki egész számokat is, ekkor a 0 értéke a hamis, minden más igaz, ha kiíratunk egy logikai változót, akkor 0-t, vagy 1-t ír ki
• változó deklaráció: ;
• lehetőségünk van kezdőértéket is adni a változónak:
• logikai, illetve bitenkénti műveletek végezhetőek rajta, a bitenkénti művelet megfeleltethető a logikai műveletnek (pl. tagadás és komplementer)
= ;
• Egyszerre több változót deklarálhatunk vesszővel elválasztva
• pl.: bool a, b, c;
• Elnevezett konstansokat a const kulcsszóval hozhatunk létre, ekkor értéket is kell nekik adnunk:
a = true; b = false; c = a || !(~a && b) && true;
const = ; ELTE TTK, Alkalmazott modul: Programozás
22
23
ELTE TTK, Alkalmazott modul: Programozás
24
4
C++ alapismeretek
C++ alapismeretek
Típusok
Típusok
• Egész típusok:
• Valós, lebegőpontos típusok: • kulcsszavai: float, double, long double
• attól függően, mekkora méreten szeretnénk eltárolni az értéket, különböző kulcsszavakat használhatunk (a pontos méretek implementációfüggőek): • short (ált. 16 bit): –32768 - +32767 • int (ált. 32 bit): –2147483648 - +2147483647 • long (ált. 64 bit): –2147483648 - +2147483647
• a méretek implementációfüggőek (balról jobbra növekvően), a típusok kompatibilisek egymással, az egész típusokkal, illetve a logikai típussal • Karakter típus (char):
• kompatibilisek egymással, illetve a logikai és valós típussal • egészek osztása egész eredményt ad • pl.: int a = 2, b = 4;
• mivel ténylegesen a karakterek ASCII kódját tárolja, így kompatibilis az egész típussal • pl.: char a, b ='y'; (a++ == 'b')
a = (a * (b + 6) – 4.3) % a; ELTE TTK, Alkalmazott modul: Programozás
• a karaktereket szimpla idézőjelben kell megadnunk
25
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Típusok
Típusok
• Szöveg típus (string):
• Tömbök: • minden típusból készíthetünk tömböt, ehhez csak az elemek számát kell megadnunk létrehozáskor a [ ] operátor segítségével
• dupla idézőjelben kell megadnunk a konstansokat • nem beépített típus, ezért használatakor hivatkoznunk kell az őt tartalmazó fájlra (#include <string>) • igazából karakterek tömbjeként működik, azért használható az indexelő ([]) operátor
• méretként csak konstans egész érték adható meg • pl.: int a[10]; // 10 elemű egészekből álló // tömb létrehozása
• lekérdezhető a hossza: .size();
• elem lekérdezése és beállítása ugyanezzel az operátorral, ahol az indexek 0-tól a tömb mérete -1-ig tartanak, ha túlindexelünk, az futási idejű hibához vezet
• szöveget lehet konkatenálni az összeadás (+) operátorral • pl.: string a = "a", b = "szöveg"; a = a + " " + b;
// konkatenáció
• lehet többdimenziós tömböket (mátrixokat) is készteni
int x = a.size(); // x = 8 lesz ELTE TTK, Alkalmazott modul: Programozás
27
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Konzol használat
Konzol használat
• A C++ adatbeolvasásra és megjelenítésre alapvetően konzol felületet használ (külső könyvtárakkal grafikus felület is támogatható)
• Kiírás a cout, beolvasás a cin utasítással történik, valamint a << és >> operátorokkal, amikkel több kiírandó értéket választhatunk el
28
• bekérésnél csak változóba olvashatunk be értéket
• A konzolon csak egyféle színben, egyféle betűtípussal tudunk kiíratni karaktereket
• kiírásnál az operátorok között lehetnek változók és konstansok tetszőleges típusból, illetve tördelőjelek, például a sorvége jel (endl)
• A konzolra történő beolvasás-kiírásnál a műveleteket külön fájlban, az iostream (input-output stream)-ben találjuk, ezért ezt kell használnunk a programban:
• pl.: int a; cin >> a; // a bekérése cout << "A értéke: " << a; // kiíratása cout << "Egy sor" << endl << "Másik sor"; // sortörés beiktatása
#include
• Az iostream a standard névtérbe tartozik: using namespace std; ELTE TTK, Alkalmazott modul: Programozás
26
29
ELTE TTK, Alkalmazott modul: Programozás
30
5
C++ alapismeretek
C++ alapismeretek
Forrásfájlok
Programok fordítása
• C++ programok a .cpp kiterjesztésű fájlok, ezek szerkeszthetőek szövegszerkesztővel, vagy valamilyen C++ programozási környezettel (pl.: DevC++, KDevelop, Eclipse, Code::Blocks, Visual Studio, ...)
• Ha megszerkesztettük a programot, fordítanunk kell, ezt a feladatot a fordítóprogram látja el • több lépésben végzi a feladatát, először assembly kódot generál, majd abból gépi kódot
• A fejlesztői környezetek általában projektekben dolgoznak, hogy több fájlból álló programokat is könnyen tudjunk kezelni • Mivel nincs automatikus kódformázás, nekünk kell figyelnünk arra, hogy:
• vannak előfordítási lépések, mint a fájltartalom bemásolás, illetve a definíciók behelyettesítése • Fordítás közben üzeneteket kapunk, ezek lehetnek:
• a programunk kinézete, tabulálása megfelelő legyen
• hibák (error): hiba, amiért nem sikerült lefordítani a programot, ezeket javítanunk kell
• ne keverjük a kis-nagybetűket sehol, hiszen a C++ megkülönbözteti őket
• figyelmeztetés (warning): nem hiba (nem kötelező javítani), de esetleges hibajelenséget okozhat futás közben
ELTE TTK, Alkalmazott modul: Programozás
31
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Programok fordítása
Véletlen generálás
• a fordító a legjobb tudomása szerint adja meg a hiba helyét, de ez lehet téves jelzés is
• A C++ lehetőséget ad véletlen számok előállítására, ehhez két utasításra (függvényhívásra) van szükségünk: • srand(): inicializálja a generátort
• A g++ a legnépszerűbb fordító, használata:
• rand(): megad
g++ ...
• pl.: g++ main.cpp
egy egész értékű pozitív véletlenszámot
• Az utasítások a stdlib.h fájlban vannak, ezért ezt be kell ágyaznunk a programba (#include <stdlib.h>)
• alapértelmezetten egy a.out nevű programot készít, de ezt a –o kapcsolóval megváltoztathatjuk
• A generálás mindig a kezdőértékhez viszonyítva történik, amely lehet konstans, vagy változó is
• a –w kapcsolóval kikapcsolhatjuk a figyelmeztetéseket,
• általában az aktuális időpillanatot szokás megadni, amit lekérdezhetünk a time(0) függvénnyel (ehhez használnunk kell a time.h fájlt)
-Wall megjeleníti az összes lehetséges hibalehetőséget
• a –pedantic csak a szabvány kódot fogadja el ELTE TTK, Alkalmazott modul: Programozás
33
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Karakterkezelés
Karakterkezelés
• A karakterek C++-ban ASCII kódjuk alapján vannak eltárolva, ezért amikor karakter típusú változót hozunk létre, akkor igazából egy bájtban tárolt számot ment el a gép
• Továbbá lehetőségünk van az egész számra alkalmazható műveleteket használni, pl.:
• Íj módon lehetőségünk van a számokra alkalmazott műveleteket karakterekre is alkalmazni, illetve értékül adni őket számoknak, és fordítva, pl.:
• Manipulációs műveletek (a cctype fájlból, a paraméterben konstanst vagy változót adunk meg, és visszakapjuk a módosított karaktert):
char ch1 = 'a'; int ch1i = ch1; // ch1i megkapja ’a’ ASCII kódját int ch2i = 97; char ch2 = ch2i; // ch2 megkapja a 97-es ASCII kódú karaktert
ELTE TTK, Alkalmazott modul: Programozás
32
34
char ch = 'a'; cout << ++ch; // kiírja a 'b'-t
• kisbetűvé alakítás: tolower() • nagybetűvé alakítás: toupper() • betű-e a karakter: isalpha() • szám-e a karakter: isdigit() 35
ELTE TTK, Alkalmazott modul: Programozás
36
6
C++ alapismeretek
C++ alapismeretek
Szövegkezelés
Szövegkezelés
• A szöveget kezelő utasításokat egy adott szöveg típusú változóra kell meghívnunk .() (a műveleteket a string fájl tartalmazza)
• Fontosabb műveletek: • karakter első előfordulásának helye (indexe, ha nem találja string::npos a visszatérési érték): <szöveg>.find()
• Fontosabb műveletek: • adott karakter lekérdezése: <szöveg>[] • szöveg összefűzése: <szöveg1> + <szöveg2> • szöveg hosszának lekérdezése: <szöveg>.length() • üres-e a szöveg: <szöveg>.empty() • szöveg törlése: <szöveg>.erase() • résszöveg lekérdezése:
• karaktertömbbé konvertálás: <szöveg>.c_str() • szöveg hozzáfűzése: <szöveg>.append(<új szövegrész>)
• új szövegrész beszúrása: <szöveg>.insert(, <új szövegrész>)
• szövegrész lecserélése: <szöveg>.replace(, , <új szövegrész>)
<szöveg>.substr(,) ELTE TTK, Alkalmazott modul: Programozás
37
ELTE TTK, Alkalmazott modul: Programozás
C++ alapismeretek
C++ alapismeretek
Szövegkezelés
Szövegkezelés
• Pl.:
• Pl.:
string s; // s.empty() igaz lenne string s1 = "árvíztűrő"; string s2 = "tükörfúrógép"; s = s1 + " " + s2; // s = "árvíztűrő tükörfúrógép" lesz // s.empty() hamis lenne s.append("!"); // s = "árvíztűrő tükörfúrógép!" lesz s.replace(0,1,"Á"); // s = "Árvíztűrő tükörfúrógép!" lesz int length = s.length(); // length = 23 lesz char ch = s[2]; // ch = 'v' lesz ELTE TTK, Alkalmazott modul: Programozás
38
string sub1 = s.substr(0,5); // sub1 = "Árvíz" lesz int index1 = s.find('ő'); // index1 = 8 lesz int index2 = s.find('r'); // index2 = 1 lesz, mindig az elsőt találja meg string sub2 = s.substr(0, s.find(' ')); // sub2 = "Árvíztűrő" lesz string sub3 = s.substr(s.find("fú"), s.length() - s.find("fú")); // megkeresi az "fú"-t, annak a helye a 15 // a szöveg hossza 23, tehát venni fogja a // 8 hosszan a szöveget, sub3 = "fúrógép!" lesz s.erase(); // s = "" lesz 39
ELTE TTK, Alkalmazott modul: Programozás
40
7