1. Alapok Programozás II
Elérhetőség Név: Smidla József Elérhetőség: smidla dcs.uni-pannon.hu Szoba: I916 2
Irodalom Bjarne Stroustrup: A C++ programozási nyelv 3
Irodalom Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Programtervezési minták 4
Irodalom Robert C. Martin: Tiszta kód Az agilis szoftverfejlesztés kézikönyve 5
A kezdetek A legrövidebb C++ program: int main() { A C++-ban a main függvénynél elhagyhatjuk a return utasítást! 6
Kiíratás Kiíratás C-ben: printf("hello World! %d\n",3); Kiíratás C++-ban: std::cout<<"hello World! " <<3<<endl; 7
Beolvasás Beolvasás C-ben: int a; scanf("%d", &a); Beolvasás C++-ban: int a; std::cin>>a; 8
Adatfolyamok Az adatokat adatfolyamokra helyezzük rá, vagy azokról olvasunk be Az adatfolyamok az iostream header fileban találhatóak meg Az adatfolyamok az std névtéren belül vannak: std::cout, std::cin 9
Adatfolyamok cout: Karakterek szabványos kimeneti folyama cin: Karakterek szabványos bemeneti folyama cerr: Hibaüzenetek szabványos, nem pufferelt kimeneti folyama 10
Hello World! 1. #include <iostream> int main() { std::cout << "Hello World!\n"; 11
Névterek használata Az std névtér objektumait, függvényeit gyakran használjuk, ezért kényelmetlen lehet sokszor beírni az std::-t 12
Névterek használata Nem kell az std::-t beírni az std névtér elemei elé: using namespace std; Csak bizonyos elemei elé nem kell beírni: using std::cout; 13
Hello World! 2. #include <iostream> using namespace std; int main() { int a; cout << "Hello World!\n"; cin >> a; 14
Hello World! 3. #include <iostream> using std::cout; int main() { int a; cout << "Hello World!\n"; std::cin >> a; 15
Feladat Írj programot, amely beolvas egy egész, majd egy lebegőpontos számot, végül egy legfeljebb 30 karaktert tartalmazó stringet, a beolvasott értékeket írja ki a képernyőre! 16
Megoldás #include <iostream> using namespace std; int main() { int a; double b; char str[31]; cin >> a >> b >> str; cout << a << ", " << b << ", " << str << "\n"; 17
bool típus Új, két állapotot tároló típus, értéke true vagy false bool b = 5 == 2+3; b = true; b =!b; 18
std::string típus Egyszerűbbé válik a stringek kezelése: #include <iostream> using namespace std; int main() { string text1 = "alma"; string text2; cin >> text2; if (text1 == text2) { cout << "azonos" << endl; else { cout << text1 + text2 << endl; 19
const előtag A const előtaggal rendelkező változók értékei megváltoztathatatlanok const int a = 0; // 1 const int b; // 2 a = 4; // 3 int * pa = (int*)&a; // 4 int * pb = &a; // 5 *pa = 60; // 6 20
const előtag A const előtaggal rendelkező változók értékei megváltoztathatatlanok const int a = 0; // 1 const int b; // 2 a = 4; // 3 int * pa = (int*)&a; // 4 int * pb = &a; // 5 *pa = 60; // 6 17
const előtag A const előtaggal rendelkező változók értékei megváltoztathatatlanok const int a = 0; // 1 const int b; // 2 a = 4; // 3 int * pa = (int*)&a; // 4 int * pb = &a; // 5 *pa = 60; // 6 17
const előtag A const előtaggal rendelkező változók értékei megváltoztathatatlanok const int a = 0; // 1 const int b; // 2 a = 4; // 3 int * pa = (int*)&a; // 4 int * pb = &a; // 5 *pa = 60; // 6 17
const előtag A const előtaggal rendelkező változók értékei megváltoztathatatlanok const int a = 0; // 1 const int b; // 2 a = 4; // 3 int * pa = (int*)&a; // 4 int * pb = &a; // 5 *pa = 60; // 6 17
const előtag A const előtaggal rendelkező változók értékei megváltoztathatatlanok const int a = 0; // 1 const int b; // 2 a = 4; // 3 int * pa = (int*)&a; // 4 int * pb = &a; // 5 *pa = 60; // 6 17
const előtag A const előtaggal rendelkező változók értékei megváltoztathatatlanok const int a = 0; const int b; a = 4; int * pa = (int*)&a; int * pb = &a; *pa = 60; // 1 // 2 // 3 // 4 // 5 // 6 17
const előtag Ha valami eleve const, akkor inkább ne castoljuk át (vagy hibás döntést hoztunk, mikor valamit const-á tettünk). const int a = 0; // 1 const int b; // 2 a = 4; // 3 int * pa = (int*)&a; // 4! int * pb = &a; // 5 *pa = 60; // 6 17
const mutatóknál Amire a pointer mutat, az konstans: int a; const int * pa; // 1 pa = &a; // 2 *pa = 70; // 3 18
const mutatóknál Amire a pointer mutat, az konstans: int a; const int * pa; // 1 pa = &a; // 2 *pa = 70; // 3 18
const mutatóknál Amire a pointer mutat, az konstans: int a; const int * pa; pa = &a; // 1 // 2 *pa = 70; // 3 18
const mutatóknál Amire a pointer mutat, az konstans: int a; const int * pa; pa = &a; *pa = 70; // 1 // 2 // 3 18
const mutatóknál A mutató konstans: int a, b; int * const pa; // 1 int * const pb = &a; // 2 pb = &b; // 3 *pb = 42; // 4 19
const mutatóknál A mutató konstans: int a, b; int * const pa; // 1 int * const pb = &a; // 2 pb = &b; // 3 *pb = 42; // 4 19
const mutatóknál A mutató konstans: int a, b; int * const pa; int * const pb = &a; // 1 // 2 pb = &b; // 3 *pb = 42; // 4 19
const mutatóknál A mutató konstans: int a, b; int * const pa; int * const pb = &a; pb = &b; // 1 // 2 // 3 *pb = 42; // 4 19
const mutatóknál A mutató konstans: int a, b; int * const pa; int * const pb = &a; pb = &b; *pb = 42; // 1 // 2 // 3 // 4 19
const mutatóknál A mutató és a mutatott változó is konstans: int a, b; const int * const pa; // 1 const int * const pb = &a;// 2 *pb = 53; // 3 pb = &b; // 4 20
const mutatóknál A mutató és a mutatott változó is konstans: int a, b; const int * const pa; // 1 const int * const pb = &a;// 2 *pb = 53; // 3 pb = &b; // 4 20
const mutatóknál A mutató és a mutatott változó is konstans: int a, b; const int * const pa; // 1 const int * const pb = &a;// 2 *pb = 53; // 3 pb = &b; // 4 20
const mutatóknál A mutató és a mutatott változó is konstans: int a, b; const int * const pa; // 1 const int * const pb = &a;// 2 *pb = 53; // 3 pb = &b; // 4 20
const mutatóknál A mutató és a mutatott változó is konstans: int a, b; const int * const pa; // 1 const int * const pb = &a;// 2 *pb = 53; pb = &b; // 3 // 4 20
Dinamikus memóriakezelés Dinamikus tömb C-ben: #include <stdlib.h> int main() { int * tomb; tomb = (int*)malloc( sizeof(int) * 5 ); tomb[0] = 43; tomb[2] = 53; free(tomb); tomb = 0; A memóriafoglaló / felszabadító függvények nem nyelvi elemek 21
Dinamikus memóriakezelés Dinamikus tömb C++-ban: int main() { int * tomb = new int[5]; tomb[0] = 43; tomb[2] = 53; delete [] tomb; tomb = 0; A new és delete nyelvi elemek A new a típusból és a darabszámból tudja, hogy hány bájtot kell lefoglalni 22
Dinamikus memóriakezelés Dinamikus tömb C++-ban: int main() { int * tomb = new int[5]; tomb[0] = 43; tomb[2] = 53; delete [] tomb; tomb = 0; Tömb felszabadításánál kötelező a [] a delete után! 22
Dinamikus memóriakezelés Egyetlen elem lefoglalása: int * a = new int; *a = 54; delete a; a = 0; Egyetlen elem felszabadításánál tilos []-t írni a delete után! 23
Feladat Írd át az alábbi C programot úgy, hogy a dinamikus memóriakezeléshez a C++ eszközeit használja! #include <stdlib.h> int main() { int i; int ** a = (int**)malloc(sizeof(int*) * 5); for (i = 0; i < 5; i++) a[i] = (int*)malloc(sizeof(int) * 4); for (i = 0; i < 5; i++) free(a[i]); free(a); a = 0; return 0; 24
Megoldás int main() { int i; int ** a = new int*[5]; for (i = 0; i < 5; i++) a[i] = new int[4]; for (i = 0; i < 5; i++) delete [] a[i]; delete [] a; a = 0; return 0; 25
Referencia int a = 60; int * pa = &a; Név: a pa 60 0 0 0 FF 0A 54 01 26
Referencia int a = 60; int * pa = &a; int & b = a; Egy memóriaterületnek egynél több neve is lehet! Név: a, b pa 60 0 0 0 FF 0A 54 01 26
Referencia int a0 = 0, a1 = 42; int & b; int & c = a0; int & d = c; d = 40; c = 30; d = a1; Név Érték a0 0 a1 42 b c d d = 100; 27
Referencia int a0 = 0, a1 = 42; int & b; //Kezdeti érték! int & c = a0; int & d = c; d = 40; c = 30; d = a1; Név Érték a0 0 a1 42 c d d = 100; 27
Referencia int a0 = 0, a1 = 42; int & b; //Kezdeti érték! int & c = a0; int & d = c; d = 40; c = 30; d = a1; Név Érték a0 0 a1 42 c 0 d d = 100; 27
Referencia int a0 = 0, a1 = 42; int & b; //Kezdeti érték! int & c = a0; int & d = c; d = 40; c = 30; d = a1; Név Érték a0 0 a1 42 c 0 d 0 d = 100; 27
Referencia int a0 = 0, a1 = 42; int & b; //Kezdeti érték! int & c = a0; int & d = c; d = 40; c = 30; d = a1; Név Érték a0 40 a1 42 c 40 d 40 d = 100; 27
Referencia int a0 = 0, a1 = 42; int & b; //Kezdeti érték! int & c = a0; int & d = c; d = 40; c = 30; d = a1; Név Érték a0 30 a1 42 c 30 d 30 d = 100; 27
Referencia int a0 = 0, a1 = 42; int & b; //Kezdeti érték! int & c = a0; int & d = c; d = 40; c = 30; d = a1; Név Érték a0 42 a1 42 c 42 d 42 d = 100; 27
Referencia int a0 = 0, a1 = 42; int & b; //Kezdeti érték! int & c = a0; int & d = c; d = 40; c = 30; d = a1; Név Érték a0 100 a1 42 c 100 d 100 d = 100; 27
Mit ír ki? #include <iostream> using namespace std; void foo(int a, int * b, int & c) { a = 10; *b = 20; c = 30; int main() { int a = 0, b = 0, c = 0; foo(a, &b, c); cout << a << " " << b << " " << c << "\n"; 28
Mit ír ki? #include <iostream> using namespace std; void foo(int a, int * b, int & c) { a = 10; *b = 20; c = 30; int main() { int a = 0, b = 0, c = 0; foo(a, &b, c); cout << a << " " << b << " " << c << "\n"; 0 20 30 28
Referencia mint visszatérési érték #include <iostream> int & max(int & a, int & b) { return a > b? a : b; int main() { int egyik = 50, masik = 70; max(egyik, masik) = 0; std::cout << egyik << " " << masik << "\n"; 29
Helyes? #include <iostream> int & max(int & a, int & b) { return a > b? a : b; int main() { int egyik = 50, masik = 70; int & harmadik = 50; // 1 max(egyik + 30, 200) = 0; // 2 std::cout << egyik << " " << masik << "\n"; 30
Helyes? #include <iostream> int & max(int & a, int & b) { return a > b? a : b; int main() { int egyik = 50, masik = 70; int & harmadik = 50; // 1 max(egyik + 30, 200) = 0; // 2 std::cout << egyik << " " << masik << "\n"; 30
Helyes? #include <iostream> int & max(int & a, int & b) { return a > b? a : b; int main() { int egyik = 50, masik = 70; int & harmadik = 50; // 1 max(egyik + 30, 200) = 0; // 2 std::cout << egyik << " " << masik << "\n"; 30
Nem konstans referenciák #include <iostream> int & max(int & a, int & b) { return a > b? a : b; int main() { int egyik = 50, masik = 70; int & harmadik = 50; max(egyik + 30, 200) = 0; std::cout << egyik << " " << masik << "\n"; A függvényben lévő referenciákon keresztül nincs mit megváltoztatni! // 1 // 2 30
Konstans referenciák #include <iostream> const int & max(const int & a, const int & b) { return a > b? a : b; int main() { int egyik = 50, masik = 70; const int & harmadik = 50; // 1 max(egyik + 30, 200); // 2 std::cout << egyik << " " << masik << "\n"; A referenciák most konstansak, tehát eleve nem lehet megváltoztatni az értékeket. 65
Lokális függvény referenciája 1. #include <iostream> using namespace std; int & foo() { int valami = 50; return valami; int main() { cout<<foo()<<"\n"; Automatikus lokális változó referenciáját nem adjuk vissza, mert csak a függvényen belül létezik! 31
Lokális függvény referenciája 2. #include <iostream> using namespace std; int & foo() { static int valami = 50; return valami; int main() { cout<<foo()<<"\n"; Statikus lokális változó referenciáját visszaadhatjuk 32
Alapértelmezett érték #include <iostream> using namespace std; int novel(int mit, int mivel = 1) { return mit + mivel; int main() { cout<<novel(2)<<"\n"; // mivel erteke 1 cout<<novel(2, 5)<<"\n"; Az alapértelmezett értéknek köszönhetően a második paramétert nem kötelező megadni 33
Alapértelmezett érték #include <iostream> using namespace std; int novel(int mit, int mivel = 1, int valami) { return mit + mivel + valami; int main() { cout<<novel(2, 3)<<"\n"; cout<<novel(2, 5)<<"\n"; Mi történik? 34
Alapértelmezett érték #include <iostream> using namespace std; int novel(int mit, int mivel = 1, int valami) { return mit + mivel + valami; int main() { cout<<novel(2, 3)<<"\n"; cout<<novel(2, 5)<<"\n"; Ez értelmezhetetlen, az első alapértelmezett értékkel rendelkező paraméter után az összes azt követőnek legyen alapértelmezett értéke! 35
Függvénytúlterhelés C-ben a függvényt a neve egyértelműen azonosítja C++-ban a függvényt a nevén kívül a paraméterei is meghatározzák 36
Függvénytúlterhelés #include <iostream> using namespace std; void fg() { void fg(int a, int b) { void fg(double a, double b) { int main() { fg(); fg(1, 2); fg(1.0, 2.0); // fg() // fg(int, int) // fg(double, double) 37
Feladat Írj függvényt, amely: Lefoglal egy mátrixot, a mátrix sorainak és oszlopainak számát paraméterben kapja meg Opcionálisan megadható a mátrix elemeinek kezdeti értéke, alapesetben ez 0 Írj függvényt, amely megjeleníti a mátrixot Írj függvényt, amely felszabadítja a mátrixot A következő oldalamon található forráskódot bővítsd ki! 38
Feladat Ezt bővítsd ki: int main() { int ** m1; int ** m2; lefoglal(5, 4, m1); lefoglal(3, 3, m2, 5); kiir(5, 4, m1); kiir(3, 3, m2); felszabadit(5, m1); felszabadit(3, m2); 39
Megoldás #include <iostream> using namespace std; void lefoglal(int s, int o, int ** & m, int v = 0) { m = new int*[s]; int i, j; for (i = 0; i < s; i++) { m[i] = new int[o]; for (j = 0; j < o; j++) m[i][j] = v; 40
Megoldás void kiir(int s, int o, int ** m) { int i, j; for (i = 0; i < s; i++) { for (j = 0; j < o; j++) cout<<m[i][j]<<" "; cout<<endl; 41
Megoldás void felszabadit(int s, int ** & m) { int i; for (i = 0; i < s; i++) delete [] m[i]; delete [] m; m = 0; 42
Házi feladat Írj egy menüt kezelő programot. A menü tartalmazzon 4 menüpontot, ahol az utolsó a kilépés legyen. A többi menüpont neve tetszőleges lehet, mindegyik mást és mást írjon ki a képernyőre, majd térjünk vissza újra a menübe. A menüpontok közül egész számok megadásával lehet választani. 78