Programozás II 1. Alapok
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
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 using namespace std; int main() { int a; cout << "Hello World!\n"; cin >> a; }
14
Hello World! 3. #include 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 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 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; const int b; a = 4; int * pa = (int*)&a; int * pb = &a; *pa = 60;
// // // // // //
1 2 3 4 5 6 20
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 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 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 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 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 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; // 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 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ó 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ó 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ó 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ó 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; // 3 pb = &b; // 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 for (i = a[i]
{ = new int*[5]; 0; i < 5; 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:
pa
a 60 0
0
0
FF 0A 54 01
26
Referencia int a = 60; int * pa = &a; int & b = a; Név:
pa
a, b 60 0
0
Egy memóriaterületnek egynél több neve is lehet!
0
FF 0A 54 01
26
Referencia int int int int d = c = d = d =
a0 = 0, a1 = 42; & b; Név & c = a0; a0 & d = c; a1 40; b 30; c a1; d 100;
Érték
0 42
27
Referencia int int int int d = c = d = d =
a0 = 0, a1 = 42; & b; //Kezdeti érték! & c = a0; Név Érték & d = c; a0 0 40; a1 42 c 30; d a1; 27 100;
Referencia int int int int d = c = d = d =
a0 = 0, a1 = 42; & b; //Kezdeti érték! & c = a0; Név Érték & d = c; a0 0 40; a1 42 c 0 30; d a1; 27 100;
Referencia int int int int d = c = d = d =
a0 = 0, a1 = 42; & b; //Kezdeti érték! & c = a0; Név Érték & d = c; a0 0 40; a1 42 c 0 30; d 0 a1; 27 100;
Referencia int int int int d = c = d = d =
a0 = 0, a1 = 42; & b; //Kezdeti érték! & c = a0; Név Érték & d = c; a0 40 40; a1 42 c 40 30; d 40 a1; 27 100;
Referencia int int int int d = c = d = d =
a0 = 0, a1 = 42; & b; //Kezdeti érték! & c = a0; Név Érték & d = c; a0 30 40; a1 42 c 30 30; d 30 a1; 27 100;
Referencia int int int int d = c = d = d =
a0 = 0, a1 = 42; & b; //Kezdeti érték! & c = a0; Név Érték & d = c; a0 42 40; a1 42 c 42 30; d 42 a1; 27 100;
Referencia int int int int d = c = d = d =
a0 = 0, a1 = 42; & b; //Kezdeti érték! & c = a0; Név Érték & d = c; a0 100 40; a1 42 c 100 30; d 100 a1; 27 100;
Mit ír ki? #include 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 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 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 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 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 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 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"; }
A függvényben lévő referenciákon keresztül nincs mit megváltoztatni!
30
Konstans referenciák #include 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 using namespace std; int & foo() { int valami = 50; return valami; }
int main() { cout<
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 using namespace std; int & foo() { static int valami = 50; return valami; }
int main() { cout<
Statikus lokális változó referenciáját visszaadhatjuk 32
Alapértelmezett érték #include 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 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 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 35 értéke!
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 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 38 bővítsd ki!
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 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