Programozási Nyelvek (C++) Gyakorlat Gyak 02.

Slides:



Advertisements
Hasonló előadás
C# nyelvi áttekintő A „Programozás C# nyelven (Illés Zoltán)”
Advertisements

Összetett adattípusok 8/b tétel
ADATBÁZIS KEZELÉS – Adattípusok
LEgyméretű tömbök, vektorok Alkalmazott Informatikai Tanszék SZÁMÍTÁSTECHNIKA I. dr.Dudás László 17./0. lVektorok definiálása lVektorok definiálása kezdőértékekkel.
Objective- C Bereczki Gréta Tamara
2009 Bevezetés a programozásba Krankovits Melinda.
Programozási Nyelvek (C++) Gyakorlat Gyak 01.
Programozási Nyelvek (C++) Gyakorlat Gyak 03.
JavaScript.
© Kozsik Tamás Tömbök, kollekciók és egyéb alaposztályok.
Hernyák Zoltán Magasszintű Programozási Nyelvek I.
Programozás alapjai.
Turbo Pascal Változók.
Programozás alapjai.
Csala Péter ANDN #4. 2 Tartalom  C# - ban előre definiált típusok  Változók  Változókkal műveletek  Elágazás  Ciklus.
Bevezetés a Java programozásba
Bevezetés a Java programozásba
11. előadás (2005. május 10.) A make segédprogram Alacsony szintű műveletek és bitmezők Fájl, katalógus rendszer hívások 1.
1 Programozás alapjai GEIAL312B (ANSI C) BSc (Bachelor of Science) / Alap képzés 2005/2006. őszi félév Miskolci Egyetem Általános Informatikai Tanszék.
6. előadás (2005. április 5.) Struktúrák Úniók Új adattípus definíálása Dinamikus memória foglalás 1.
5. előadás (2005. március 22.) Függvények definíciója, deklarációja, hívása Enumerációs adattípus 1.
4. előadás (2005. március 8.) Pointerek Pointer aritmetika
UNIVERSITY OF SZEGED D epartment of Software Engineering UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás II. 6. Gyakorlat const, static, dinamikus 2D.
Függvények, mutatók Csernoch Mária.
Borland C/C++ mintapéldák
Borland C/C++ mintapéldák függvényekre. 1. példa Írjunk olyan függvényt amely egy számot kiirat.
Java Típuskonverziók.
Programozás I. Horváth Ernő 1. Elérhetőségek Bauer Péter Horváth Ernő Tanszéki honlap
Programozás I. Horváth Ernő 1. Elérhetőségek Bauer Péter Horváth Ernő Tanszéki honlap
A Java programozási nyelvSoós Sándor 1/17 Java programozási nyelv 4. rész – Osztályok II. Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai.
LDinamikus tömbök, kétdimenziós tömbök Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 21./0. lVektorok létrehozása futásidőben, dinamikusan.
WEB Technológiák Dr. Pance Miklós – Kolcza Gábor Miskolci Egyetem.
C# Alapok Krizsán Zoltán.
1 Programozás alapjai GEIAL312B (ANSI C) BSc (Bachelor of Science) / Alap képzés 2005/2006. őszi félév Miskolci Egyetem Általános Informatikai Tanszék.
Web-grafika (VRML) 10. gyakorlat Kereszty Gábor. Script típusok Elemi típusok: szám: egész vagy lebegőpontos – int / float – 1 / 1.1 string: ‘Hello World!’
C++ Alapok, első óra Elemi típusok Vezérlési szerkezetek
Rendszer és Szoftvertechnológia Tanszék
PHP I. Alapok. Mi a PHP? PHP Hypertext Preprocessor Szkriptnyelv –Egyszerű, gyors fejlesztés –Nincs fordítás (csak értelmező) Alkalmazási lehetőségek:
Programozás Az adatokról C# -ban.
Szoftvertechnológia alapjai Java előadások Förhécz András, doktorandusz tárgy honlap:
Programozási nyelvek Páll Boglárka.
Készítette: Csíki Gyula
Hernyák Zoltán Programozási Nyelvek II.
A D programozási nyelv Angeli Dávid. Nagy vonalakban  C++  
Komoróczy Tamás 1 Java programozási nyelv Stringek.
Java programozási nyelv Metódusok
UNIVERSITY OF SZEGED D epartment of Software Engineering UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás II. 4. Gyakorlat Függvény paraméterek, dinamikus.
Objektum orientált programozás
Objektum orientált programozás
Objektum orientált programozás
Függvények a C nyelvben 1 Függvényeket a következő esetekben szokás írni: Ha ugyanazt a tevékenységet többször is el kell végeznünk ugyanolyan típusú,
Programozás alapjai Csernoch Mária.
2012. március 21. Paulik Áron.  Ha a függvényünk feladata olyan, hogy nem lenne értelme a visszatérési értéknek, vagy csak nincs rá szükség, void típusúként.
Free pascal feladatok
Típuskonverzió a C++ nyelvben
Excel programozás (makró)
UNIVERSITY OF SZEGED D epartment of Software Engineering UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás I. 3. gyakorlat.
Függvények, mutatók Csernoch Mária. Függvények függvény definíciója az értelmezési tartomány tetszőleges eleméhez hozzárendel egy értéket –függvény helyettesítési.
TÁMOP /1-2F JAVA programozási nyelv NetBeans fejlesztőkörnyezetben I/13. évfolyam Típusosztályok. Számosztályok. Math és StrictMath matematikai.
TÁMOP /1-2F JAVA programozási nyelv NetBeans fejlesztőkörnyezetben I/13. évfolyam Osztályok, objektumok definiálása és alkalmazása. Saját.
Informatikai gyakorlatok 11. évfolyam
a programegységek között
Kifejezések C#-ban.
Programozási alapismeretek
Programozási nyelvek típusossága.
Hernyák Zoltán Magasszintű Programozási Nyelvek I.
Változók.
JAVA programozási nyelv NetBeans fejlesztőkörnyezetben I/13. évfolyam
JAVA programozási nyelv NetBeans fejlesztőkörnyezetben I/13. évfolyam
Konverziós operátorok
Előadás másolata:

Programozási Nyelvek (C++) Gyakorlat Gyak 02. Török Márk tmark@caesar.elte.hu D-2.620

Tartalom Erősen típusos nyelvek fogalma Vezérlési szerkezetek Mutatók és dereferálás Függvények bevezetése Paraméterátadás Kódelemzés

Típusozás Erősen és gyengén típusos nyelvek Statikus és dinamikus típusrendszerek

Típusozás Típus: névvel azonosított halmaz, melyen műveleteket értelmezünk. értékhalmaz típusműveletek

Erősen típusos nyelv Különböző típusú értékek hogyan adhatóak egymásnak értékül. Valójában nincs egzakt meghatározás rá. Forrás: Ada for the C++ or Java Developer, Quentin Ochem, Technical Papers, AdaCore Nincs implicit típuskonverzió Operandusok azonos típusúak Primitív művelet esetén A standard műveletekre értjük, a túlterhelés más!

Erősen típusos nyelv (Ada) procedure Strong_Typing is Alpha : Integer := 1 ; Beta : Integer := 10 ; Result : Float; begin Result := Float ( Alpha ) / Float ( Beta ) ; -- 0.1 end Strong;

Gyengén típusos nyelv Implicit típuskonverzió Hibás végeredmény Bővítő automatikus Szűkítő típuskényszerítéssel Hibás végeredmény Konverzió néha kerekít

Gyengén típusos nyelv (C++) void weakTyping ( void ) { int alpha = 1 ; int beta = 10 ; float result; result = alpha / beta; // 0 }

Gyengén típusos nyelv (Java) void weakTyping () { int alpha = 1 ; int beta = 10 ; float result; result = alpha / beta; // 0 }

Statikus típusrendszer Statikus típusrendszerű nyelv Minden változódeklarációkor meg kell adni az adott változó típusát. Azaz fordítási időben minden változóról, minden függvény paraméteréről, illetve minden függvény (művelet) visszatérési értékéről kell tudni, hogy milyen típusú. Def szerint: a típus meghatározza, hogy milyen műveleteket végezhetek el rajta.

Dinamikus típusrendszer Értelmezett (interpretált) nyelvek Automatikus memóriakezelés Trükközni mindig lehet Deklaráció típus nélkül Az inicializáláskor dől el, hogy milyen a típusa a változónak Függvények esetén Nincs visszatérési típus deklarálva Paraméterátadás: Duck-typing

Alap típusok és módosítók Típusok: int, float, double, char, (bool már csak C++-ben) Modifiers: short, long, signed, unsigned int: short int: -32,768 -> +32,767 (16 bit) unsigned short int: 0 -> +65,535 (16 bit) unsigned int: 0 -> +4,294,967,295 (32 bit) int: -2,147,483,648 -> +2,147,483,647 (32 bit) long int: -2,147,483,648 -> +2,147,483,647 (32 bit) char: signed char : -128 -> +127 unsigned char: 0 -> +255 float: 32 bit double: double : 96 bit long double : 64 bit

Erőssen (?) típusos nyelv (Na, mégegyszer) Házi feladat: Hogy is van ez? #include <stdio.h> int main() { short s = 10; short int si = 1; printf ("s : %f\t, si : %f\n", sizeof(s), sizeof(si)); }

Típusos nyelv #include <stdio.h> int main() { short s = 10; short int si = 1; printf ("s : %d\t, si : %d\n", sizeof(s), sizeof(si)); }

Erőssen (?) típusos nyelv Házi feladat: Hogy is van ez? #include <stdio.h> int main() { short s = 10; short int si = 1; printf ("s : %f\t, si : %f\n", sizeof(s), sizeof(si)); } A float leveszi a memóriából azt a részt, ami neki kell, így viszont az intnek egy része kimarad!

C++ típusrendszere C++-ben a leggyakoribb alaptípusok: Egész számok típusa: int, short int, long int Lebegopontos számok típusa: float, double, long double Logikai típus: bool C-ben int volt a bool megfelelője! Karakter típus: char Karakterlánc típus: string Ez C-ben char*

C++ típusrendszere C++11 újdonságai auto register dectype fordítás idejű típuskikövetkeztetés register Regiszterekbe rakja az értékét a változónak a memória helyett, gyorsabb elérést biztosít dectype

Statikus típusrendszer (C++-ben) int main() { auto i; return 0; } error: declaration of ‘auto i’ has no initializer

Statikus típusrendszer (C++-ben) int main() { auto i; i = 12; return 0; } error: declaration of ‘auto i’ has no initializer

Statikus típusrendszer (C++-ben) int main() { auto i = 12; return 0; }

Statikus típusrendszer (C++-ben) #include <iostream> #include <typeinfo> int main() { auto i = 12; std::cout << typeid(i).name(); // i return 0; }

Statikus típusrendszer (C++-ben) #include <iostream> #include <typeinfo> class Clazz; int main() { auto i = new Clazz(); std::cout << typeid(i).name(); return 0; } error: unable to deduce ’auto’ from ’<expression error>’

Statikus típusrendszer (C++-ben) #include <iostream> #include <typeinfo> class Clazz { }; int main() { auto i = new Clazz(); std::cout << typeid(i).name(); // PlClazz return 0; }

Statikus típusrendszer (C++-ben) Függvény visszatérési értékének típusa és a függvény paramétere nem lehet auto típusú!

Statikus típusrendszer (C++-ben) int main() { register int i = 12; return 0; }

Statikus típusrendszer (C++-ben) #include <iostream> #include <typeinfo> int main() { int i = 12; decltype(i) j = ’c’; std::cout << typeid(j).name(); // i return 0; }

Statikus típusrendszer (C++-ben) Más, statikus típusrendszerű nyelvek (C/C++): Java, C# Ada (Erősen típusos! Láttuk!) Dinamikus típusrendszerű nyelvek: Python, Ruby, Perl Lua JavaScript (Elképesztő gyenge lábakon álló típusrendszer)

Deklaráció és értékadás típusnév változónév1; típusnév változónév1, változónév2, …; Értékadás: változónév = érték; típusnév változónév = érték; Kezdeti érték: undefined, ha nincs inicializáció.

Deklaráció és értékadás int main() { int i; i = 0; int k; }

Deklaráció és értékadás int main() { int i = 0; int k; }

Deklaráció és értékadás C-ben: #include <stdio.h> int main() { int i, j, k = 0; printf("%d | %d | %d", i, j, k); return 0; }

Deklaráció és értékadás C-ben: Fordítás: gcc dek01.c -o dek01 –Wall Fordítás eredménye: dek01.c: In function ‘main’: dek01.c:5: warning: ‘i’ is used uninitialized in this function dek01.c:5: warning: ‘j’ is used uninitialized in this function Már gondolhatjuk az előrejelzésből: Nem sikerült, amit szeretnénk! Output: 2826228 | 134513739 | 0 Nem tudunk egy lépésben deklarálni és értékül adni? Vagy mégis?!?!

Deklaráció és értékadás C-ben: #include <stdio.h> int main() { int i = j = k = 0; printf("%d | %d | %d", i, j, k); return 0; }

Deklaráció és értékadás C-ben: Fordítás: gcc dek01.c -o dek01 –Wall Fordítás eredménye: dek01.c: In function ‘main’: dek01.c:5: error: ‘j’ undeclared (first use in this function) dek01.c:5: error: (Each undeclared identifier is reported only once dek01.c:5: error: for each function it appears in.) dek01.c:5: error: ‘k’ undeclared (first use in this function) Error! Más út?

Deklaráció és értékadás C-ben: #include <stdio.h> int main() { int i, j, k; i = j = k = 0; printf("%d | %d | %d", i, j, k); return 0; }

Deklaráció és értékadás C-ben: Fordítás: gcc dek01.c -o dek01 –Wall Fordítás eredménye: Nincs hiba, sem warning! Siker! Output: 0 | 0 | 0 Nem tudunk egy lépésben deklarálni és értékül adni? Nem tudunk egy lépésben deklarálni és értékül adni! Házi feladat: És ha egy lépésben deklarálunk, és ott adunk értéket külön-külön az elemeknek?

Deklaráció és értékadás Hogy megy ez C++-ben? #include <iostream> int main() { int i, j, k = 0; std::cout << "|" << i << "|" << j << "|" << k; } Szokásos történet!

Deklaráció és értékadás Hogy néz ez ki másik nyelveken? Nézzük meg Adában! with ada.text_io; procedure dek01inada is i, j, k : integer := 0; begin ada.text_io.put_line( Integer'Image(i) & Integer'Image(j) & Integer'Image(k)); end dek01inada;

Deklaráció és értékadás Az output: $ gnatmake dek01inada.adb … $ ./dek01inada 0 0 0 Siker! Adában meg lehet csinálni!

Üres utasítás A jó öreg skip! ; int main() { ;;; // három üres utasítás return 0; }

Vezérlési szerkezetek Elágazás: Feltétel vizsgálata Ez lehet egész, logikai vagy object Ha nem if, akkor else. Ez opcionális Ha nem if, akkor else if. Ez is opcionális. else if után jöhet több else if. else if után jöhet a végén else, opcionálisan.

Vezérlési szerkezetek Elágazás (C): #include <stdio.h> int main() { int i = 10; if ( i < 15 ) // log kif! // ... } return 0;

Vezérlési szerkezetek Elágazás (C): #include <stdio.h> int main() { int i = 10; if ( i < 15 ) // log kif! // ... } else { } return 0;

Vezérlési szerkezetek Elágazás (C): #include <stdio.h> int main() { int i = 10; if ( i < 15 ) // log kif! // ... } else if ( i > -1 ) { // … } else { } return 0;

Vezérlési szerkezetek Elágazás(C++): #include <iostream> int main() { bool b = true; if ( b ) // log kif! // ... }

Vezérlési szerkezetek Elágazás(C++): #include <iostream> int main() { bool b = false; if ( b == true ) // log kif! // ... } // else … }

Vezérlési szerkezetek Elágazás(C): Ha egy elágazás feltételvizsgálatában nullától különböző számot adunk meg, akkor az megfelel az igaz kiértékelésnek. float, int, double, short, … #include <stdio.h> int main() { int i = 10; if ( i ) // nem log kif, de jó! // ... } // else … }

Vezérlési szerkezetek Elágazás(C): Ha egy elágazás feltételvizsgálatában nulla (0) számot adunk meg, akkor az megfelel a hamis kiértékelésnek. #include <stdio.h> int main() { int i = 0; if ( i ) // nem log kif, de jó! // ... } // else … }

Vezérlési szerkezetek Elágazás(C++): Ha nem NULL egy object, akkor true. Ha NULL egy object, akkor false. #include <iostream> int main() { Kutya k = new Kutya(); // Később megnézzük, mi ez a Kutya! if ( k ) // nem log kif, de jó! // ... } // else … }

Vezérlési szerkezetek Elágazás(C++): Ha nem NULL egy object, akkor true. Ha NULL egy object, akkor false. #include <iostream> int main() { Kutya k = NULL; // Később megnézzük, mi ez a Kutya! if ( k ) // nem log kif, de jó! // ... } // else … }

Vezérlési szerkezetek Elágazás(C++): Nézzük a bugos részt! Mitől döglik a légy? Meg a program? A feltétel kiértékelése : logikai, szám, object Értékadás is lehet benne! Oka: A feltételben szereplő kiértékelés eredményét később is szeretnénk felhasználni. Kevesebb erőforrást használunk! Egyszer értékeljük ki a függvényt, később is használjuk az eredményét

Vezérlési szerkezetek Elágazás(C++): Nézzük a bugos részt! Mitől döglik a légy? Meg a program? Akkor is előfordul, ha nem szeretnénk! (Gépelési hiba!) Míg az első kiértékelés false, a második már true! #include <iostream> int main() { bool b = false; if ( b == true )//log kif std::cout << ”bent”; } // else … } #include <iostream> int main() { bool b = false; if ( b = true )// log kif std::cout << ”bent”; } // else … } => Helyett =>

Vezérlési szerkezetek Elágazás(C++): Nézzük a bugos részt! Mitől döglik a légy? Meg a program! Akkor is előfordul, ha nem szeretnénk! (Gépelési hiba!) Míg az első kiértékelés false, a második már true! #include <iostream> int main() { int i = 10; if (i == 0) // log kif! std::cout << ”bent”; } // else … } #include <iostream> int main() { int i = 10; if ( i = 0 ) // log kif! std::cout << ”bent”; } // else … } => Helyett =>

Vezérlési szerkezetek Elágazás más nyelveken: Vannak nyelvek, melyek erősebb megszorításokat tesznek az if-ben történő értékadásra! Nézzük ezt Java-ban. Szuper! Logikaira ugyanolyan veszélyes! public class Main { public static void main() { boolean l = false; if(l = true) { System.out.println("1"); } else { System.out.println("2"); }

Vezérlési szerkezetek Elágazás más nyelveken: Vannak nyelvek, melyek erősebb megszorításokat tesznek az if-ben történő értékadásra! Nézzük ezt Java-ban. Szuper! int-re már nem megy! Fordítási hiba! public class Main { public static void main() { int i = 10; if( i = 0 ) { System.out.println("1"); } else { System.out.println("2"); }

Vezérlési szerkezetek Elágazás más nyelveken: Vannak nyelvek, melyek erősebb megszorításokat tesznek az if-ben történő értékadásra! Nézzük ezt Ada-ban. Fordítási hiba! procedure Elag01inada is b : Boolean := true; begin if b := false then null; end if; end Elag01inada;

Vezérlési szerkezetek ternary operator (? : ) (condition) ? (if_true) : (if_false) (x == y) ? a : b // GNU C : a = x ? : y; // megegyezik: a = x ? x : y;

Vezérlési szerkezetek Más nyelvekben: Java, C# hasonló C#-ban: ?? Operator int? x = null; // y = x, ha x nem null, ha viszont az, akkor y = -1.  int y = x ?? -1; javascript, ruby, …: obj = obj || {} obj ||= {};

Vezérlési szerkezetek switch: Nem logikai vizsgálat, hanem illesztés / összehasonlítás switch: integer-expression (int alapú vagy arra konvertálható értékek) case kiértékelőág. Utasítások végrehajtása egyenlőség vizsgálat után Egy érték egyszer fordulhat elő Több utasítás esetén blokk: { … } Utasításmentes case ág is lehet. Továbbfolyás lehetséges Továbbfolyás megakadályozása: break; default ág: Ami nem illeszkedik, az ide jön! Nem kötelező a switch végén lennie!

Vezérlési szerkezetek switch: #include <iostream> int main() { int i = 1; switch( i ) case 0: std::cout << 0; break; case 1: std::cout << 1; break; case 4: std::cout << 4; break; case 5: std::cout << 5; default : std::cout << "def"; }

Vezérlési szerkezetek switch: #include <iostream> int main() { int i = 1; switch( i ) case 0: std::cout << 0; std::cout << 1; std::cout << 4; }; break; case 5: std::cout << 5; default : std::cout << "def"; }

Vezérlési szerkezetek switch: Továbbfolyás #include <iostream> int main() { int i = 1; switch( i ) case 0: std::cout << 0; case 1: std::cout << 1; case 4: std::cout << 4; break; case 5: std::cout << 5; default : std::cout << "def"; }

Vezérlési szerkezetek switch: Házi feladat: Mi az eredmény ha: i = 1; i = 6; esetén? #include <iostream> int main() { int i = 1; switch( i ) case 1: std::cout << 1; default : std::cout << "def"; case 4: std::cout << 4; break; case 5: std::cout << 5; }

Vezérlési szerkezetek Ciklus: Előltesztelős #include <iostream> int main() { int i = 0; while (i < 10) i += 1; }

Vezérlési szerkezetek Ciklus: Hátultesztelős #include <iostream> int main() { int i = 0; do { // … } while (i < 10); }

Vezérlési szerkezetek Ciklus: Számlálós #include <iostream> int main() { for(int i = 0; i < 10; i += 1) // … }

Vezérlési szerkezetek Ciklus: Számlálós #include <iostream> int f(int); int main() { for(int i = 0, j = 0; i + j < 10; i = f(j), j += 1) // … }

Vezérlési szerkezetek Ciklus: Végtelen ciklusok #include <iostream> int main() { for(;;) // … } int main() { while ( true ) // … }

Vezérlési szerkezetek Ciklus: Feltétlen vezérlést átadó utasítások #include <iostream> int main() { int i = 1; while ( i < 10 ) i += 1; std::cout << i << std::endl; if ( i != 5 ) break; } std::cout << "kint vagyok" << std::endl;

Vezérlési szerkezetek Ciklus: Feltétlen vezérlést átadó utasítások #include <iostream> int main() { int i = 1; while ( i < 10 ) i += 1; if ( i < 5 ) std::cout << i << std::endl; continue; } std::cout << "kesobb jon!" << std::endl;

Vezérlési szerkezetek break; continue; labels

Vezérlési szerkezetek Összefoglaló: using namespace-name::name; type-name name; type-name name = value; type-name name(args); expression; { statements; }

Vezérlési szerkezetek while(condition) { statement; } for(init-statement; condition; expression) { statement; } if (condition) statement if (condition) statement else statement2 return val;

Mutatók, dereferálás int* p 12 Ha T egy típus, T* a „T-re hivatkozó mutató” típus lesz, azaz egy T* típusú változó egy T típusú objektum címét tartalmazhatja. int* p 12

Mutatók, dereferálás Változó deklarációja: int i; A változó bizonyos (4 bájt) memóriát foglal le. Változó, mely pointer: int *pi = &i; Az i által lefoglalt memória helye az adott változó címe. Címének visszaadása: &i i változó által lefoglalt memória mérete: sizeof(i)

Mutatók, dereferálás Példa: int *pi = 12; char c = 'a'; char *p = &c; // p a c címét tárolja

Mutatók, dereferálás Deklarálása: int* pa, pb; Mi a típusa a változóknak? typeid(pa).name(); // Pi vagy int* typeid(pb).name(); // i vagy int typeid(&pb).name(); // Pi vagy int* typeid a typeinfo headerben Nem mindegy, hogy hova kerül a *!

Mutatók, dereferálás Jobb, ha így: int *pa, *pb; Lint: Használjuk a *-t a változónál, ne a típusnál. Így automatikusan elkerüljük az ismertetett hibát.

Mutatók, dereferálás Értékadás: int *p; p = 47; Mihez rendeltünk értéket? Megváltoztattuk a címét! Nem mindig fordul! g++ -Wall main.cpp -fpermissive Nagy így már fordul fpermissive kapcsoló: hibákat error szintről warningra nyom le.

Mutatók, dereferálás A mutatókon elvégezhető művelet a „dereferencia”, azaz a mutató által mutatott objektumra való hivatkozás. indirekciónak is hívják; jele: *

Mutatók, dereferálás Dereferálás int i = 10; int *pi = &i; *pi = 12; std::cout << i << std::endl; *mutató: a hivatkozott értékhez hozzáférés, lekérdezés, beállítás

Mutatók, dereferálás #include <iostream> int main() { char c = 'a'; char *p = &c; std::cout << p << std::endl; // a }

Konstansokról Néha szeretném, ha egy memóriaterület ne változzon meg. const kulcsszó const int ci = 12; Azaz ci értékét nem tudom megváltoztatni a későbbiekben.

Konstansokról A const a típusrendszer része, const int külön típus! Constot beviszem a típusrendszerbe: egy int *ip nem mutathat rá. Megkövetelem: const int *cip legyen, ekkor cip = &ci; De: cip konstans referencia, ezért *cip = 13 nem lehet! ++cip működik, ++*cip nem!

Konstansokról Más nyelvekben: Java : final C# : const/readonly Ada : constant

Konstansokról Mi lehet konstans? Változó, pointer, paraméter, függvény, osztály?

Konstansok const int i = 12; Deklarálunk egy int változót (i néven). Konstans! Tehát értékét nem tudjuk megváltoztatni! Értékadás a deklarációkor kötelező, mert i értéke a const miatt nem változtatható!

Konstansok int main() { const int i; return 0; } Kimenet: const01.cpp: 3: error: uninitialized const ’i’

Konstansok int main() { const int i = 12; ++i; return 0; } Kimenet: const01.cpp: 4: error: increment of read-only variable ’i’

Konstansok Csináljunk pointert! Ráállítom a pointert a változóra! (nem const-ra) A konstans nem változhat! És a mutatott érték?

Konstansok Olyan pointer, melynek nem változhat! const int *cip = &ci; Cím nem változik És a mutatott érték? const int *cip = &ci; Konstans int-re mutató pointer Nem kötelező inicializálni. Egyszerű pointer! int *const icp = &i; intre mutató konstans pointer Érték változhat, cím nem! Itt is hiba, ha nem inicializáljuk a konstanst.

Konstansok int main() { int i = 12; int *const ip = &i; return 0; } Kimenet: pipa

Konstansok #include <iostream> int main() { int i = 12; int *const ip = &i; std::cout << i << ” ” << ip << std::endl; return 0; } Kimenet: pipa 12 0xf2342da324

Konstansok #include <iostream> int main() { int i = 12; int *const ip = &i; std::cout << ++i << ” ” << *ip << std::endl; return 0; } Kimenet: pipa 13 12 (figyeljünk a kiértékelés sorrendjére!!!)

Konstansok #include <iostream> int main() { int i = 12; int *const ip = &i; i = 11; std::cout << i << ” ” << *ip << std::endl; return 0; } Kimenet: pipa 11 11

Konstansok #include <iostream> int main() { int i = 12; int *const ip = &i; std::cout << ++i << ” ” << ++(*ip); return 0; } Kimenet: pipa Rontsuk el! ;] 14 13 (Kiértékelési sorrend!!! Jobbról kezd!!!)

Konstansok #include <iostream> int main() { int i = 12; int *const ip = &i; std::cout << ++i << ” ” << ++ip; return 0; } Kimenet: const05.cpp: 7: error: increment of read-only variable ’ip’

Konstansok Ok, de én egy olyan pointert akarok, amit tudok változtatni, de az értéket, amire mutat, azt nem!

Konstansok (nézzük csak másképp!) #include <iostream> int main() { int i = 12; const int *ip = &i; std::cout << ++i << ” ” << ++(*ip); return 0; } Kimenet: const05.cpp: 7: error: increment of read-only variable ’* ip’

Konstansok (nézzük csak másképp!) #include <iostream> int main() { int i = 12; const int *ip = &i; std::cout << ++i << ” ” << ++ip; return 0; } Kimenet: 13 0x12df321c5

Konstansok (nézzük csak másképp!) #include <iostream> int main() { const int i = 12; int *ip = &i; std::cout << i << ” ” << ++*ip; return 0; } Kimenet: const08.cpp:6: error: invalid conversion from ’const int*’ to ’int*’

Konstansok Ajánlott odafigyelni a sorrendre: const int* i int* const i

Konstansok Egy olyan pointer kell, amit nem változtathatok és az általa mutatott értéket sem!

Konstansokról const int *const cicp = &ci; Mutathat konstansra, de mindig ugyanoda kell, hogy mutasson.

Konstansok Javítsuk ki, hogy az inkrementációs operátorra panaszkodjon!

Konstansok #include <iostream> int main() { const int i = 12; const int* const ip = &i; std::cout << i << ” ” << ++*ip; return 0; } Kimenet: const08.cpp:7: error: increment of read-only location `*(const int*)ip`

Konstansok #include <iostream> int main() { const int i = 12; int* const ip = &i; std::cout << i << ” ” << ++*ip; return 0; } Kimenet: const08.cpp:6: error: invalid conversion from ’const int*’ to ’int*’

Konstansok Tehát egy olyan pointerünk van a const int változó mellett, mely egy const intre mutat, és ezzel együtt nem lehet megváltoztatni az értékét. const int *const ip = &i; int const *const ip = &i; A fenti kettő megegyezik! De utóbbit kerüljük! Kevésbé érthető, kevésbé használt!

Konstansokról class Date { ... } const Date mybirthday = ...; mybirthday = ... mybirthday.f();

Konstansokról Azok a függvények, melyek nem változtatják meg a függvény belsejét, deklarálhatom konstans tag-függvénynek.

Konstansokról class Date { … // ha ez const lenne, // akkor hibát dobna a fordító! void set_day(int x) { day = x; } int get_day() const { return day; } }

Függvények bevezetése Tartalom: Függvénydeklaráció és –definíció Paraméterátadás Visszatérési érték

Függvények Függvénydefiníció: A program kisebb egységekre bontása. Minden függvényt valahol meg kell határoznunk. Függvénydefiníció olyan deklaráció, ahol megadjuk a függvény törzsét. Felépítése: type name ( parameter1, parameter2, ...) { statements }

Függvények Más nyelvekben: C/C++ alapú nyelvekben szintén void és társai Adában function és procedure keyword

Függvények Definíció: Szignatúra: A teljes specifikáció! type name ( parameter1 [paramname], parameter2, ...) Szignatúra: Visszatérési érték típusát nem tartalmazza Paraméterneveket szintén nem name ( parameter1, parameter2, ...)

Függvények Függvények deklarációja: Forward declaration Megadom a függvény használatának módját Ezt hívjuk még function prototype-nak is

Függvények Példa: void swap(int*, int*); // deklaráció, function proto. // ... void swap(int *p, int *q) // definíció { int t = *p; *p = *q; *q = t; }

Függvények Paraméterátadás Amikor egy függvény meghívódik, a fordítóprogram a formális paraméterek számára tárterületet foglal le, az egyes formális paraméterek pedig a megfelelő valódi (aktuális) paraméter-értékkel töltődnek fel. A paraméterátadás szerepe azonos a kezdeti értékátadáséval A fordítóprogram ellenőrzi, hogy az aktuális paraméterek típusa megegyezik-e a formális paraméterek típusával, és végrehajt minden szabványos és felhasználói típuskonverziót

Függvények Paraméterátadás Érték szerinti Cím szerinti Referencia szerinti Eredmény szerinti

Függvények Paraméterátadás: érték szerint int sum(int a, int b) { return a + b; } int main() std::cout << sum(12, 34) << std::endl;

Függvények Paraméterátadás: cím szerint (pass by address, pass by pointer) int f(int *a) { // a mutatott érték módosítása std::cout << ++*a; return *a; } int main() int i = 10; int *ip = &i; // megkapja i címét! std::cout << f(ip) << ”|” << *ip << std::endl; Kimenet: 11 11|10

Függvények Mi történik itt? A pointerek (címek) mindig érték szerint adódnak át!

Függvények Referencia szerinti paraméterátadás void f(int &a) { } int main() int i = 1; f(i); std::cout << i << std::endl; // 2

Függvények Referencia szerinti paraméterátadás void f(int &a) { } int main() int i = 1; f(10); std::cout << i << std::endl; type ‘int&’ from an rvalue of type ‘int’

Függvények rvalue : (később) int a = 42; int b = 43; // a, b l-value: a = b; // ok b = a; // ok a = a * b; // ok // a * b rvalue: int c = a * b; // ok, rvalue jobb oldalon a * b = 42; // error, rvalue bal oldalon

Függvények Paraméterátadás: Érték és referencia szerint void f(int val, int& ref) { val++; ref++; } void main() { int i = 1; int j = 1; f(i,j); // i == 1, j == 2 }

Függvények Eredmény szerinti pass-by-result vs. pass-by-value-return Az átadott paraméter (pointer) lemásolódik. Maga az érték nem kerül másolásra Ada

Függvények Egyéb: pass-by-name pass-by-value-returned pass-by-lazy-evaluation (lusta kiértékelés)

Függvények Más nyelvekben: Ada: paraméter átadásától függő, in, out, in out Java: minden érték szerint

Függvények Visszatérési érték szerint megkülönböztetünk: Eljárásokat (void) Függvényeket (minden más)

Függvények return: void esetén: visszatérés return; vezérlés megszakítása return 10; hiba! void nem int!

Függvények Függvények esetén: Return utasítás nem kötelező Ez veszélyes! int f() { std::cout << ”Hello”; }

Függvények int f() {} int main() { int i = f(); std::cout << i; // kimenet: 1 }

Függvények int f() { return; } int main() int i = f(); std::cout << i; error: return-statement with no value,...

Függvények Visszatérési érték A main() kivételével minden nem void metódusnak kell visszatérési értékkel rendelkeznie. lokális változóra hivatkozó mutatót soha nem szabad visszaadni

Függvények int f1() { } // hiba: nincs visszatérési érték, ettől még lehet jó void f2() { } // rendben int f3() { return 1; } // rendben void f4() { return 1; } // hiba: visszatérési érték void függvényben int f5() { return; } // hiba: visszatérési érték hiányzik void f6() { return; } // rendben

Függvények Nézzük a rázós eseteket. Kezdjük kicsivel.

Függvények int f() { return ’c’; } int main() std::cout << f() << std::endl; // 99 return 0;

Függvények int f() { int i = a + b; } int main() std::cout << f(10, 12); // 22 return 0;

Függvények int f() { int i = a + b; int k; } int main() std::cout << f(10, 12); // 22 return 0;

Függvények int f() { int i = a + b; int k; 10 + 8; } int main() std::cout << f(10, 12); // 22 return 0;

Függvények int f() { int i = a + b; int k; 10 + 8; i = b + 100; } int main() std::cout << f(10, 12); // 112 return 0;

Függvények int f() { int i = a + b; int k; 10 + 8; i = b + 100; i = a + 1; } int main() std::cout << f(10, 12); // 11 return 0;

Függvények int f() { int i = a + b; int k; 10 + 8; i = b + 100; i = a + 1; std::cout << ”hello”; } int main() std::cout << f(10, 12); // 1234520896 return 0;

Függvények int f() { int i = a + b; int k; 10 + 8; i = b + 100; i = a + 1; std::cout << ”hello”; k = 19 + a; } int main() std::cout << f(10, 12); // 29 return 0;

Függvények bevezetése Túlterhelés: Később!

Konstansok és függvények Függvények visszatérési értéke gubancos lehet! Baj van, ha valami gubanc futás időben derül ki! Javítsuk úgy a kódot, hogy fordítási időben kiszűrjük a bajos részeket!

Konstansok (függvény visszatérési értéke) #include <iostream> char* f() { return ”szoveg”; } int main() f()[0] = ’b’; Segmentation fault

Konstansok (függvény visszatérési értéke) #include <iostream> const char* f() { return ”szoveg”; } int main() f()[0] = ’b’; Kimenet: fconst01.cpp:10: error: assignment of read-only location ’* f()’

Konstansok (függvény visszatérési értéke) #include <iostream> int* f() { int i = 12; const int* ip = &i; return ip; } Kimenet: fconst01.cpp:7: error: invalid conversion from ’const int*’ to ’int*’

Konstansok (paraméterátadás) Érték, referencia, pointer szerint! void f( int i ) { i = 10; } void f( int& i ) void f( int* i ) *i = 10;

Konstansok Kicsit előre ugrunk! User-defined type void f( myType &my ); Ekkor: Valamilyen belső műveletet szeretnénk elvégeztetni rajta! Optimalizálás: csak a címét másoljuk, ne az egész objektumot! Gyorsabb, nő a hatékonyság! De mi van akkor, ha valaki módosítja a saját tudta nélkül? Arra gondol, hogy úgy sem módosul a metódus belsejében! Gubancos! void f( const myType &my );

Konstansok Haladjunk az osztályok mentén még mindig! Osztály specifikációja: class Clazz { void f(); int i; }

Konstansok Ennek az implementációja: void Clazz::f() { ++i; } Mi történik, ha a specifikációban megtiltom, hogy az adott metódus implementációja módosítsa az osztály adott mezőjét? Nézzünk egy példát!

Konstansok class Clazz { void f() const; int i; } Kimenet: increment of data-member ’Clazz::i’ in read-only structure

Konstansok És akkor nézzünk valami nagyon advanced-et! Interjún megkérdezhetik!  Mit csinál az alábbi metódus! Mondj el mindent, amit tudsz róla! const int* const Method3( const int* const& ) const;

Kódelemzés Feladat: Írj olyan programot, mely kiszámolja egy Fahrenheit értékhez tartozó Celsius értéket! -100-tól indulunk, +300-ig megyünk, és 10 a lépésnagyság!

Kódelemzés fahr2cels v1 (C): #include <stdio.h> // a program fahrenheit és ahhoz megfelelő celsius értékeket ír ki int main() { int fahr; for (fahr = -100 ; fahr <= 300; fahr += 10) { printf("fahr = %d\t cels =%d\n", fahr, 5/9 * (fahr - 32)); } return 0; } Kimenet: F = 0 C = 0 F = 40 C = 0 ...

Kódelemzés Mi történik itt? Statikus típusrendszerű nyelvek esetén a fordítóprogramnak már fordítási időben kell tudnia, hogy milyen típusokkal dolgozik, e szerint foglal majd memóriát, vizsgálja a műveleteket! int / int => int Fordító nem foglalkozik azzal, hogy értékvesztéssel jár a művelet, fordítási időben nem tudja, hogy milyen érték kerül a változóba

Kódelemzés fahr2cels v2 (C): Kimenet: #include <stdio.h> // a program fahrenheit és ahhoz megfelelő celsius értékeket ír ki int main() { int fahr; for (fahr = -100; fahr <= 300; fahr += 10) { printf("fahr = %d\t cels =%d\n", fahr, 5./9 * (fahr - 32)); } return 0; Kimenet: fahr2cels2.c: In function ‘main’: fahr2cels2.c:13: warning: format ‘%d’ expects type ‘int’, but argument 4 has type ‘double’

Kódelemzés A kód ugyan lefordul, de a warning mindig rossz ómen! float / int => float

Kódelemzés fahr2cels v3 (C): Kimenet: F = 0 C = -17.777778 #include <stdio.h> // a program fahrenheit és ahhoz megfelelő celsius értékeket ír ki int main() { int fahr; for (fahr = -100; fahr <= 300; fahr += 10) { printf("fahr = %d\t cels =%f\n", fahr, 5./9 * (fahr - 32)); } return 0; Kimenet: F = 0 C = -17.777778 F = 40 C = 4.444444 ...

Kódelemzés fahr2cels v4 (C): #include <stdio.h> #define LOWER -100 #define UPPER 300 #define STEP 10 // a program fahrenheit és ahhoz megfelelő celsius értékeket ír ki int main() { int fahr; for (fahr = LOWER; fahr <= UPPER; fahr += STEP) { printf("fahr = %d\t cels =%f\n", fahr, 5./9 * (fahr - 32)); } return 0; Kimenet: F = 0 C = -17.777778 F = 40 C = 4.444444 ...

Kódelemzés Ha már megoldottuk C-ben, láttuk a hátrányait, akkor nézzük meg ugyanezt a feladatot C++-ben!

Kódelemzés fahr2cels v5 (C++): #include <iostream> using namespace std; int main() { for ( int fahr = 0; fahr <= 200; fahr+=40) { cout << "F = " << fahr << '\t' << "C = " << 5./9*(fahr-32) << endl; } return 0; // Opcionális! }

Kódelemzés Egyszerűen típushelyesen tudom kiíratni, és fordítási időben kapok jelzés, ahelyett, hogy futásidőben szállna el, vagy kapnék rossz eredményt!

Kódelemzés fahr2cels v6 (C++): #include <iostream> using namespace std; int main() { const int lower = 0; const int upper = 200; const int step = 40; for ( int fahr = lower; fahr <= upper; fahr+=step ) { cout << "F = " << fahr << '\t' << "C = " << 5./9*(fahr-32) << endl; } return 0; }

Kódelemzés Mi az a const és miért kell? Növeltük a maintence-t! Kiemeltük a constans értékeket! const : nem állhat az értékadás bal oldalán!

Kódelemzés fahr2cels v7 (C++): #include <iostream> using namespace std; inline double fahr2cels( double f ) { return 5./9 * ( f-32 ); } int main() { const int lower = 0; const int upper = 200; const int step = 40; for ( int fahr = lower; fahr <= upper; fahr+=step ) { cout << "F = " << fahr << '\t' << "C = " << fahr2cels(fahr) << endl; } return 0; }

Kódelemzés inline: az egyik legjobb hatékonyságnövelő eszköz. Abban az esetben, amikor egyszerű fgv-törzsről van szó, behelyettesíti az adott kódot a meghívó helyére! Egy esetben nem lehet ezt megcsinálni, amikor virtuális fgv-eket használok! Ugyanis futásidőben dől el, hogy a dinamikus kötések melyikével, melyik implementációval futtassa a fgv-t! Ezek kiértékelése a fordító számára sokkal lassabb! (De ezekről később)

Kódelemzés Feladat: Írjuk meg a jó öreg cat parancsot! Amit begépelünk, azt adja vissza a következő sorban, ha entert vagy Ctrl+D-t ütöttünk!

Kódelemzés cat (C): #include <stdio.h> int main() { int ch; while ( (ch = getchar()) != EOF) { putchar(ch); } return 0; } Kimenet: asdf asd fasd fas

Kódelemzés cat (C++): #include <iostream> int main() { char ch; std::cin >> ch; // egy előolvasás! while ( std::cin.good() ) std::cout << ch; // ha nem volt hiba, akkor mehetünk tovább! ch << std::cin; } return 0;

Kódelemzés cat (C++): #include <iostream> using namespace std; int main() { char ch; // fontos, defaultból tetsz. karakter while ( cin >> ch ) { cout << ch; } return 0; } Kimenet: asdf asd fasd fas asdfasdfasdfas

Kódelemzés #include <iostream> int main() { char ch; std::cin >> noskipws; std::cin >> ch; // egy előolvasás! while ( std::cin.good() ) // ha nem volt hiba, akkor mehetünk tovább! std::cout << ch; std::cin >> ch; } return 0;

Kódelemzés cat (C++): #include <iostream> using namespace std; int main() { char ch; // fontos, defaultból tetsz. Karakter // cin >> átugorja a whitespace-eket!!! while ( cin.get(ch)) { cout.put(ch); } return 0; } Kimenet: asdf asd fasd fas