Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Programozási Nyelvek (C++) Gyakorlat Gyak 01. Török Márk D-2.620 1.

Hasonló előadás


Az előadások a következő témára: "Programozási Nyelvek (C++) Gyakorlat Gyak 01. Török Márk D-2.620 1."— Előadás másolata:

1 Programozási Nyelvek (C++) Gyakorlat Gyak 01. Török Márk D

2 Jelmagyarázat Elméleti vizsgán lesz! Interjúkérdés lehet Haladó C++-n kifejtve! 2

3 Tartalom Hello Világ! Fordítás, futtatás, debuggolás Interpretált vs bájtkód, fordítás Névtér printf vs cout Fejállományok Streamek 3

4 Tartalom – Hello Világ C vs C++ – Különbségek, okai – Egyszerűsítés (?) Mi az a belépési pont? Mikor van vége? stdio, stdlib 4

5 Hello Világ (C) Példa 1 : #include /* * Több soros komment */ int main() { printf("Hello World\n"); return 0; // egy soros komment } 5

6 Hello Világ (C) Példa 2 : #include /* * Több soros komment */ int main() { printf("Hello World\n"); system("pause"); return 0; // egy soros komment } 6

7 Hello Világ (C) – Fordítás $ gcc main.c $ ls main.c, a.out (ez futtatható) $./a.out Hello Világ! $ gcc main.c -o main $ ls main.c, main (ez futtatható) $./main Hello Világ! $ 7

8 Hello Világ (C++) #include /* * Komment maradt a régi */ int main() { std::cout << "Hello World\n" << std::endl; } 8

9 Hello Világ (C++) Kiiratáshoz: std::ostream::operator<< Hol van az ostream include? include-oltuk az iostream-et. Az iostream-en belüli include-ok: – istream, ostream, … 9

10 Hello Világ (C++) – Fordítás $ g++ main.cpp $ ls main.cpp, a.out (ez futtatható) $./a.out Hello Világ! $ g++ main.cpp -o main $ ls main.cpp, main (ez futtatható) $./main Hello Világ! $ 10

11 Hello Világ – C vs C++ C : procedurális, strukturális C++: objektumorientált paradigmával bővítve (később) stdio.h  iostream printf  std::cout A változások okai az objektumorientált programozási paradigmák követése, új könyvtárak, állományok implementálása Belépési pont: – int main() vagy – int main(int argc, char* argv[]) vagy – int main(int argc, char** argv) 11

12 Hello Világ – C vs C++ ISO C++ standard (mind a kettő helyes) – void main(/*…*/) { … } – Error: main must return int – main(/*…*/) { … } – Fordul, szép, jó és fut! Kilépési pont, visszatérési érték típusa mindig int. Visszatérés legyen 0! Minden más érték a hibáké! C++ esetében: – Nem kötelező megadni visszatérési értéket – main() esetében ez mindig 0 lesz! – Más esetén egy memóriaszemét. 12

13 Hello Világ – stdio.h C Standard Input and Output Library ―C-ben stdio.h ―C++ cstdio ―Az input-output műveletekért felelős ―macrok, típusok, függvények, konstansok ―Billentyűzet, nyomtató, egyéb perifériaeszközök ―stream: lehetőséget biztosít ezek írására, olvasására. ―stdin, stdout, stderr (később) 13

14 Hello Világ – stdlib.h C Standard General Utilities Library Memóriahasználathoz szükséges metódusok – calloc, malloc, realloc, free Véletlenszám generálás Környezettel kommunikáló metódusok: – exit, system, … Konverzió Keresés, rendezés... 14

15 Fordítás, futtatás, debuggolás Ahogy már láttuk: – $ g++ main.cpp -o main – $./main Parancssori paraméterekkel – $./main param1 param2 – argv[0] maga a futtatható állomány; argv[1],... a tényleges paraméterek Hibákat irassuk ki: – $ g++ -Wall main.cpp -o main Error, warning Hiba kiírása: – fájlnév:sor száma:hibaüzenet 15

16 Fordítás, futtatás, debuggolás printf – format specifiers int a = 9; int b = 10; int c = 100; printf("%d|%d|%d\n", a, b, c); // 9|10|100 printf("%3d|%3d|%2d\n", a, b, c); // 9| 10|100 printf("%03d|%03d|%02d\n", a, b, c); // 009|010| %i or %dint %cchar %ffloat %lfdouble %sstring

17 Fordítás, futtatás, debuggolás Nézzünk egy példát: #include bool f() { } int main() { std::cout << f(); } 17

18 Fordítás, futtatás, debuggolás $ g++ main.cpp -Wall -o main main.cpp: In function ‘bool f()’: main.cpp:4: warning: control reaches end of non-void function 18

19 Fordítás, futtatás, debuggolás Nézzünk egy példát: #include int main() { printf("%f", 99); } $ g++ main.cpp -Wall -o main main.cpp: In function ‘int main()’: main.cpp:8: warning: format ‘%f’ expects type ‘double’, but argument 2 has type ‘int’ 19

20 Fordítás, futtatás, debuggolás Több állomány fordítása: void sayhello (const char* name); // hello.h #include // hello.c #include "hello.h” void sayhello(const char* name) { printf ("hello, %s", name); } #include "hello.h” // main.c int main() { sayhello ("world"); return 0; } 20

21 Fordítás, futtatás, debuggolás $ gcc -Wall main.c hello.c -o hmain Header: – Két féle include-olást különböztetünk meg. – #include : system header fájlok között nézi meg. (linuxon: /usr/include/stdio.h) – #include ”fájl.h”: a lokális mappában keres, majd a system headerek között. 21

22 Fordítás, futtatás, debuggolás Fordítás lépései: – Forrásból object: először nem is futtatható fájl keletkezik, hanem egy object. Ennek kiterjesztése.o. – A második lépés a linkelés: a linker az objectfájlok összefésülését végzi függőségek szerint. Ebből lesz a futtatható állomány. – Csak fordítás -c kapcsolóval: $ gcc -Wall -c main.c – Eredmény egy main.o, mely a főprogramunk gépi kódját tartalmazza. – $ gcc main.o -o main 22

23 Fordítás, futtatás, debuggolás Külső könyvtárakból: – Archive állományok, kiterjesztése:.a // statikus könyvtárak – Matematikai függvények Math.h-ban, implementációja viszont a libm.a könyvtárban (fordított állomány!). – $ gcc -Wall calc.c /usr/lib/libm.a -o calc – Kapcsoló: elkerülhető a hosszú elérésiút: $ gcc -Wall calc.c -lm -o calc – Ez annyit jelent, hogy lm = libm.a – Elmondható, hogy lNAME = libNAME 23

24 Fordítás, futtatás, debuggolás Library-k: – Static library és shared library (dynamic) – Static library kiterjesztése:.a A linkelést követően a használt függvény gépi kódja a library-ból bemásolódik a futtatható állományba. – Shared library kiterjesztése:.so Dinamikus kötés (dynamic linking): a shared library táblázatot tartalmaz hivatkozással az egyes függvényekre. Fordításkor a linker egy ilyen hivatkozást rak be a futtatható állományba, a teljes gépi kód helyett. A futtatáskor a gépi kód bemásolódik a memóriába a megadott hivatkozás alapján. 24

25 Fordítás, futtatás, debuggolás -Wall kapcsoló: – -Wreturn-type: figyelmeztet, hogy az adott függvény definíció szerint kér visszatérési értéket (azaz nem void), de ezt az implementációjában nem tettük meg. – -Wformat: hibás formatstring a printf, scanf függvényekben. Eltér a format a paraméter típusától. – -Wunused: figyelmeztet, ha használatlan változók vannak a kódban. – -Wimplicite: ha előzőleg nem adtuk meg a függvény specifikációját. 25

26 Fordítás, futtatás, debuggolás Preprocesszor: – A fordító által meghívott, a tényleges fordítás előtt lefutó program. – Mit csinál? Kezeli az alábbi direktívákra: #include : forrásmegjelölés #define: macro definiálása #if: feltételes forrásbetöltés, macrodefiniálás 26

27 Fordítás, futtatás, debuggolás Macro-k: – C-ben fontosabb, C++-ban kevésbé fontos szerepet töltenek be. – Ha tehetjük, akkor kerüljük őket. (Nagyon erősen ajánlott!) – Mivel a fordítóprogram futása előtt a macro-k meghívásra kerülnek, és belenyúlnak a kódba, nem ajánlatos használni őket. Csökken a hatékonysága azon eszközöknek, melyekkel a programunk hatékonyságát, biztonságát tudjuk mérni. Pl.: hibakeresők, kereszthivatkozás-vizsgálók. 27

28 Fordítás, futtatás, debuggolás Macro-k: – #define CSERELD_EZT erre – csere = CSERELD_EZT – A macro lefutását követően az eredmény ez lesz: csere = erre –#define SQUARE(a) a*a –Ebből: int b = 0; int i = SQUARE(b + 2); –Igen ám! De ebből: b + 2*b + 2 => 3b + 2 lesz! 28

29 Fordítás, futtatás, debuggolás Macro-k: –Feltétel: … #ifdef AAA printf(”ez az ág lefutott!”); #endif … –Fordítás: $ gcc -Wall -DAAA main.c –A -D kapcsoló prefixe az adott AAA nevű macro-nak. Így tudunk a macro-nak értéket is adni. –Nyilván ha ezt a kapcsolót kihagyjuk, az adott ág lefutása is elmarad.

30 Fordítás, futtatás, debuggolás Debuggoláshoz: –Fordítsunk a -g kapcsolóval. –Hogy miért? Amikor a programunk abnormális futást produkál (elszáll menetközben), az operációs rendszer elmenti a program memóriabeli állapotát egy core nevű fájlba. –Nézzük meg, hogy mi van a core fájlba.

31 Fordítás, futtatás, debuggolás Töltsük be a core fájlt a GNU Debuggerbe az alábbi módon: –$ gdb futtatható-állomány core-állomány –Csak együtt tudjuk őket használni, külön nem tudjuk betölteni a core-állományt. –$ gdb a.out core Core was generated by ‘./a.out’. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 #0 0x080483ed in a (p=0x0) at null.c:13 13 int y = *p; (gdb)

32 Fordítás, futtatás, debuggolás Debuggolás: –Stack backtrace kilistázása: (gdb) backtrace Kilistázza a hívási listát.

33 Interpretált vs bájtkód, fordítás C++-forráskód lefordításával hagyományos natív kódot kapunk. A natív kód a processzornak megfelelő módon lefordított gépi kód. Ha natív C++-alkalmazásunkat több különböző környezetben (32bites, 64bites platformon) is szeretnénk futtatni, akkor külön le kell fordítanunk.

34 Interpretált vs bájtkód, fordítás Hogy megy ez máshol? – C# kód fordításával (interpretálásával) kezelt kódot kapunk. Ez egy közbenső nyelv (intermediate language, IL). A magas szintű (C#) és a legalacsonyabb szintű nyelv (assem., gépi kód) között helyezkedik el. – A közös nyelvű futási idejű környezet (Common Language Runtime, CLR) futási időben, menet közben fordítja le a kódot a Just-in-time (JIT) fordító alkalmazásával.

35 Interpretált vs bájtkód, fordítás Mit csinál a JIT fordító? – Nem túl hatékony a kódot futásidőben fordítani? – A JIT-fordító nem fordít le egy adott metódust vagy függvényt annak minden egyes meghívásakor, ezt csak az első esetben teszi meg, és ekkor a platformnak megfelelő gépi kódot állít elő. – Használatával csökken az alkalmazás munkahalmaza, a közbenső kód munkaigénye kisebb lesz.

36 Interpretált vs bájtkód, fordítás Hogy megy ez Java-ban? – A forrásfájlokban (.java) definiált minden egyes típus interpretálásának eredményeként külön létrejövő típusnév.class fájl tartalmazza a végrehajtható bináris bájtkódot. – A hordozható bájtkódot interpretálás helyett, közvetlenül futtatás előtt platformfüggő gépi kódra fordítja át, mely kód sokkal gyorsabban fut majd, mint a bájtkód interpretálása. – Előnye, a biztonság és a hordozhatóság, hátránya, hogy néhol lassú.

37 Interpretált vs bájtkód, fordítás Jittelés Java-ban: – A gyorsabb futás érdekében dinamikus fordítási technika használata: JIT (Just-in-time compiler). – Minden osztály bájtkódjának betöltése után az egész osztály bájtkódját lefordítja gépi kódra. (A további használatban a kód már nem interpretált.) – Előny: többszörösen is gyorsabb lehet a Java kód végrehajtása, viszont egy osztály bájtkódjának (vagy egy metódus végrehajtása) betöltési ideje növekszik.

38 Fejállományok Azaz a header-ök! Lehetővé teszik a kód elkülönítését. Tartalma: forward declaration (forward reference) – Osztályok: class Clazz; – Alprogramok: void get(Clazz &clazz); – Váltózókat: hivatkozhatsz egy változóra, mielőtt definiálnád. class Clazz { public: int get() { return value; } private: int value; } – Egyéb azonosítók. 38

39 Fejállományok Programok kisebb részekre bontása –Osztályokra –Alprogramokra Definiálása: –#define … Használata: –#include –#include ”fajl.h”

40 Fejállományok A többszörös include-ok: – Több fejállományt include-oltunk, melyek között van olyan, mely include-ol egy másikat. – Így akár egy fejállomány kétszer vagy többször is include-olásra kerülhet. – A fordítás tovább tart, mert lesznek állományok, melyek többször kerülnek feldolgozásra. – Hatalmasra nő a szemantikus gráfunk. Ezek megelőzésére: – include guardok 40

41 Fejállományok Include guard: – #ifndef, azaz ha még nincs definiálva – #define, akkor definiáljuk – … jön a kód – #endif lezárom az if-et Más: – #pragma once 41

42 Fejállományok Egyéb kulcsszavak: – #ifdef – #if – #elif – #else 42

43 Fejállományok Nézzük meg, hogy épül fel: // get.h #include #ifndef GET_H_GUARD #define GET_H_GUARD void get(int a); vector getAll(int a); #endif 43

44 Fejállományok // a masik allomany #include #include ”get.h” int f() { vector getAll(5); return get(10); } 44

45 Névtér Programok tagolásának egy eszköze Mindig valamilyen logikai csoportosítást fejeznek ki. (Egyes deklarációk valamilyen jellemzői alapján összetartoznak.) Külön hatókört alkotnak Másik névtérből származó osztályt a névtér nevének minősítésével tudjuk elérni. namespace kulcsszó. Konvenció szerint : lowelCamelCase Legismertebb, legtöbbet használt (a félév során!): std

46 Névtér std: – C++ Standard Library Osztályok és függvények gyüjteménye Containers (array, list, map,…) General (algorithm, memory, iterator,…) Streams … 46

47 Névtér Más nyelveknél: – Java: package Itt láthatósági módosító is van! C++-ben nincs – Ada: csomag Félúton az osztály és a namespace fogalma között. Működhet úgy is, mint egy C++-s namespace. – C#: namespace Még fejlettebb láthatóságikör 47

48 Névtér Példa névtér definiálására: // a.h namespace NS { class A { // functions… } int f(char a) { // … } 48

49 Névtér Fordítás: $ g++ a.h -c -c kapcsoló: – Csak fordít, de nem keres main belépési pontot. – -c kapcsoló nélkül fordítási hiba! 49

50 Névtér Használata: – :: operator – NS:: az NS névtérben lévő neveket (fgv, osztály, …) akarjuk használni 50

51 Névtér Használat: #include ”a.h” … NS::A a; a.f(); NS::f(); … 51

52 Névtér Egymásba ágyazhatóság namespace Outer { //… namespace Inner { //… } 52

53 Névtér Lehetőség nevesítés feloldására Ha egy nevet sokat használunk saját névterén kívül, egyszerűsíthetünk. Használjuk a using direktívát. using namespace std; 53

54 Névtér using más nyelvekben: – Ada: with (kicsit más) – Java: import – C#: using – Ruby: require (kicsit más) 54

55 Névtér Aliasing: namespace NameSpaceLongName { //… } namespace nsln = NameSpaceLongName; 55

56 Névtér Névtér kiterjesztése: 56 namespace X { int a; } namespace X { int b; } namespace X { int a; int b; }

57 Névtér namespace NS { int a = 10; } namespace NS { void f() { std::cout << a; } } 57

58 Névtér … NS::f();// 10 NS::a = 20; NS::f();// 20 … 58

59 Névtér Veszélyek kiterjesztés esetén (namespace extending) – Átláthatatlan kód kialakulása – Névterek feldolgozása sorrendben történik! – Ha hamarabb használok valamit, mint deklaráltam: Hiba! 59

60 Névtér Nem fordul, nem látja az a változót! namespace NS { void f() { std::cout << a; } } namespace NS { int a = 10; } 60

61 Névtér using használata nem csak névtérre: namespace NS { int x = 5; int y = 10; } // using NS::x; int main() { using NS::x; std::cout << x << std::endl; std::cout << NS::y << std::endl; } 61

62 Névtér overloading: namespace NS { int f(int i) { return i; } } namespace NS { int f(char c) { return c; } } 62

63 Névtér Deklaráció és definíció szétválasztása – Sérült design, körültekintően, csak indokolt esetben! namespace A { namespace B { void f(); } void B::f() { /* defined outside of B */ } } 63

64 Névtér Unnamed namespace – Név nélküli névtér – Globális statikus változók helyett! 64

65 Névtér namespace { int i = 10; } namespace NS { int i = 15; namespace { int i = 20; void f() { return i; } // return 20; } std::cout << i << std::endl; // 10; std::cout << NS::f(); // 20 65

66 Névtér Fordul? namespace foo { int f() { return 1; } } namespace { using namespace foo; } int a() { return f(); } 66

67 Névtér Fordul, fut. A using feloldja a nevesítést, így a nevesítetlen névtérben elérhetővé válik nevesítés nélkül is az f függvény. Vigyázz, hibás design, nagy kód esetén hibához, hibás logikához vezethet. 67

68 Stream istream, ostream, kimeneti és bemeneti műveletekért felelős ifstream, ofstream : (fstream), fájlműveletek – Írás, olvasás – Flagek: in, out, app, … istringstream, ostringstream: stringek írása, olvasása, feldolgozása Stream manipulátor iterátorok 68

69 Stream Kimenet: –#include –using namespace std; –Az iostream minden beépített típusra meghatároz kimenetet. –Alapértelmezésben a cout-ra kerülő kimeneti értékek karaktersorozatra alakítódnak át. – cout << ”hello vilag!” << 10 << endl;

70 Stream Bemenet: –istream: beépített típusok karaktersorozatként történő ábrázolásával dolgozik. –A >> jobb oldalán álló típus határozza meg, hogy bemenet fogadható el, és mi a beolvasó művelet célpontja. int i; cin >> i;

71 Stream Stringstream – Stringek kezeléséhez – Elérése: #include – iostream-ből származtatva Azaz stream műveletek! – Valójában: typedef basic_stringstream stringstream; – Flagek, statek, műveletek 71

72 Stream Stringek: – Karakterláncok reprezentálására – #include – Az std namespace-ben : std::string – typedef basic_string string; string vs stringstream? – A string reprezentál, a stream használja a reprezentációt. 72

73 Stream Műveletek: – Konkatenáció: + – Írás, olvasás a streamről/re: >>, << 73

74 Stream // stringstream::str #include // std::cout #include // std::stringstream, std::stringbuf #include // std::string int main () { std::stringstream ss; ss.str ("Example string"); std::string s = ss.str(); std::cout << s << '\n'; return 0; } 74

75 Stream Többszörös öröklődésnél példa: – istream, ostream osztályokból: iostream – Diamond! 75

76 HF Mi a legrövidebb helyes c++ program? – Fordul, fut hiba nélkül Írj egy egyszerű hellovilag programot, ahol minden lehetséges whitespace helyén újsor karakter van. 76

77 Megoldás es fordítóval: main() {} es fordítóval: #include int main () { std::cout << "hello vilag"; return 0; } 77


Letölteni ppt "Programozási Nyelvek (C++) Gyakorlat Gyak 01. Török Márk D-2.620 1."

Hasonló előadás


Google Hirdetések