PB přednáška (19. října 2015)

Podobné dokumenty
PB161 Programování v jazyce C++ Přednáška 5

PB161 Programování v jazyce C++ Přednáška 6

PB161 Programování v jazyce C++ Přednáška 6

PB161 Programování v C++ Proudy pro standardní zařízení Souborové proudy Paměťové proudy Manipulátory

PB161 Programování v jazyce C++ Přednáška 9

PB161 Programování v jazyce C++ Přednáška 9

Prostory jmen. při vkládání několika hlavičkových souborů může vzniknout kolize. logika.h const int x=5; typedef struct {...

Datové proudy objektový vstup a výstup v C++

PB161 Programování v jazyce C++ Objektově Orientované Programování. Podzim 2014

18. února 2015, Brno Připravil: David Procházka. Programovací jazyk C++

Pokročilé programování v jazyce C pro chemiky (C3220) Vstup a výstup v C++

PB161 Programování v jazyce C++ Přednáška 9

PB161 Programování v jazyce C++ Přednáška 4

Práce se soubory. Základy programování 2 Tomáš Kühr

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Vstupy a výstupy v jazyce C++

Programování v C++ 1, 6. cvičení

Vstupní a vstupní proudy v C++

Jazyk C++, některá rozšíření oproti C

PB161 Programování v jazyce C++ Přednáška 8

přetížení operátorů (o)

přetížení operátorů (o)

Zpracoval:

Programování v C++ 1, 5. cvičení

Úvod do programování. Lekce 1

PB161 Programování v jazyce C++ Přednáška 4

<surface name="pozadi" file="obrazky/pozadi/pozadi.png"/> ****************************************************************************

PREPROCESOR POKRAČOVÁNÍ

Základy C++ I. Jan Hnilica Počítačové modelování 18

Programování v C++ První kroky

PB161 Programování v jazyce C++ Přednáška 10

Programování v C++ 3, 3. cvičení

Práce se soubory. Úvod do programování 2 Tomáš Kühr

for (int i = 0; i < sizeof(hodnoty) / sizeof(int); i++) { cout<<hodonoty[i]<< endl; } cin.get(); return 0; }

Abstraktní třídy, polymorfní struktury

Objekty a třídy. Procedurální a objektově orientované programování. V této kapitole se naučíte: Procedurální a objektově orientované programování

Úvod do programování. Lekce 3

Práce se soubory. Úvod do programování 2 Tomáš Kühr

C++ objektově orientovaná nadstavba programovacího jazyka C

Pokročilé programování v jazyce C pro chemiky (C3220) Pokročilá témata jazyka C++

Dědění, polymorfismus

Funkční objekty v C++.

SYSTÉMOVÉ PROGRAMOVÁNÍ Cvičení č.1

Programovací jazyk C++ Cvičení 2

PROGRAMOVÁNÍ V C++ CVIČENÍ

Vector datový kontejner v C++.

PROGRAMOVÁNÍ V C++ URČENO PRO VZDĚLÁVÁNÍ V AKREDITOVANÝCH STUDIJNÍCH PROGRAMECH ROSTISLAV FOJTÍK

ZPRO v "C" Ing. Vít Hanousek. verze 0.3

PB161 Programování v jazyku C++

VISUAL BASIC. Práce se soubory

Pokročilé programování v jazyce C pro chemiky (C3220) Statické proměnné a metody, šablony v C++

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

PB161 Programování v jazyce C++ Přednáška 1

PB161 Programování v jazyce C++ Přednáška 2

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

PB161 Programování v jazyce C++ Přednáška 1

Jazyk C++ 1. Blok 3 Objektové typy jazyka C++ Třída. Studijní cíl. Doba nutná k nastudování. Průvodce studiem

Objektově orientované programování

map, multimap - Asociativní pole v C++.

PB161 Programování v jazyce C++ Přednáška 10

8. Načítání a zápis PDB souboru

Preprocesor. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze. Karel Richta, Martin Hořeňovský, Aleš Hrabalík, 2016

IB111 Úvod do programování skrze Python Přednáška 7

Mělká a hluboká kopie

Základy jazyka C# Obsah přednášky. Architektura.NET Historie Vlastnosti jazyka C# Datové typy Příkazy Prostory jmen Třídy, rozhraní

C++ přetěžování funkcí a operátorů. Jan Hnilica Počítačové modelování 19

Více o konstruktorech a destruktorech

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. October 17, 2016

PB161 Programování v jazyce C++ Přednáška 7

PB161 Programování v jazyce C++ Přednáška 7

Úvod do programovacích jazyků (Java)

PB přednáška (23. listopadu 2015)

Šablony, kontejnery a iterátory

Zpracoval:

Úvod do programovacích jazyků (Java)

Zápis programu v jazyce C#

Množina čísel int stl-set-int.cpp

Syntaxe vyjímek. #include <iostream> #include <string> using namespace std; // Trida vyjimek class Vyjimka { private:

Šablony, kontejnery a iterátory

Programování v Javě I. Únor 2009

C++ Akademie SH. 2. Prom nné, podmínky, cykly, funkce, rekurze, operátory. Michal Kvasni ka. 20. b ezna Za áte níci C++

Jazyk C++ I. Šablony 2

Řetězce. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze. Karel Richta, Martin Hořeňovský, Aleš Hrabalík, 2016

Vstup a výstup datové proudy v C

Jazyk C# a platforma.net

Programování v Javě I. Leden 2008

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39

Motivace. Vstup a výstup. Minimální komunikace. Motivace. ÚDPJ - Vstup a výstup. Ing. Lumír Návrat katedra informatiky, A

Teoretické minimum z PJV

Programování v C++ 2, 4. cvičení

Jazyk C# (seminář 5)

C++ objektově orientovaná nadstavba programovacího jazyka C

Jazyk C práce se soubory. Jan Hnilica Počítačové modelování 16

IB111 Programování a algoritmizace. Objektově orientované programování (OOP)

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Jazyk C++ I. Polymorfismus

Druhy souborů. textové. binární. nestrukturované txt strukturované - ini, xml, csv. veřejné bmp, jpg, wav proprietární docx, cdr, psd

Pokud neuvedeme override, vznikne v synu nová (nevirtuální) metoda (a pochopitelně se nezavolá, jak bychom

Ukazatele, dynamická alokace

Transkript:

PB161 5. přednáška (19. října 2015) Jmenné prostory Motivace problém: výskyt dvou entit (např. tříd) se stejným jménem typicky nenastává uvnitř jednoho projektu použití více nezávislých knihoven příp. použití knihoven v existujícím projektu // library1.h class Object { /*... */ ; // library2.h class Object { /*... */ ; // main.cpp #include "library1.h" #include "library2.h" // při překladu main.cpp dojde k chybě // error: redefinition of class Object jak se tomuto problému vyhnout? Implicitní jmenné prostory oblasti platností identifikátorů vznikají automaticky uzavřeny mezi složené závorky deklarace tříd a struktur lokální jmenné prostory: funkce/metody, cykly, bloky (lokální rámce / local scope) globální jmenný prostor (globální rámec / global scope) v jednom jmenném prostoru nemohou být dvě entity se stejným jménem // globální jmenný prostor int x; double x; // CHYBA! class Example { // jmenný prostor třídy Example 1

float x; public: void method() const { // jmenný prostor metody method() double x; for (int i = 0; i < 3; ++i) { // jmenný prostor for cyklu std::string x; { // jmenný prostor vnořeného bloku char x; ; přístup ke jmenným prostorům pomocí operátoru :: globální jméno ::x jméno uvnitř třídy Example::x k lokálním jmenným prostorům není přístup (nemají jméno) #include <iostream> using namespace std; int x = 17; class Example { int x; public: Example() : x(29) { void print() const { int x = 3; { int x = 9; cout << x << endl; // 9 cout << Example::x << endl; // 29 cout << ::x << endl; // 17 cout << x << endl; // 3 ; Example e; e.print(); 2

Explicitní jmenné prostory je možno vytvářet vlastní pojmenované jmenné prostory syntax: namespace jmeno {... jmenné prostory je možno i vnořovat namespace MyLib { void print(); namespace Experimental { void print(); namespace MyLib { class Example { public: void print() const; ; MyLib::Example ex; ex.print(); MyLib::print(); MyLib::Experimental::print(); print(); // CHYBA! už znáte jeden namespace používaný ve standardní knihovně // typický obsah standardních hlavičkových souborů namespace std { //... proto píšeme std::cout, std::string apod. Zpřístupnění jmenného prostoru plná kvalifikace std::string direktiva using namespace jmeno_prostoru; vloží obsah celého jmenného prostoru do aktuálního jmenného prostoru zvyšuje riziko konfliktů analogie import java.* v Javě nebo from library import * v Pythonu 3

nepoužívat v globálním rámci v hlavičkových souborech! #include <string> string s; // CHYBA! void print() { using namespace std; string s; // OK string s; // CHYBA! deklarace using jmeno_prostoru::jmeno_entity vloží pouze odkazovanou entitu má prioritu před using namespace #include "libadam.h" #include "libeve.h" using namespace Adam; // obsahuje funkci getapple(); using namespace Eve; // taky obsahuje getapple(); getapple(); // CHYBA! using Eve::getApple; getapple(); // OK, volá se Eve::getApple(); #include <iostream> using std::cout; using std::endl; cout << "Hello!" << endl; alias jmenného prostoru namespace Widget = System::Window::Widget; using a using namespace v globálním prostoru užívejte rozumně 4

nikdy v hlavičkových souborech vždy až po všech #include using a using namespace můžeme také používat lokálně ve funkcích/metodách ve vnořených blocích není možno používat přímo uvnitř třídy (class scope) class X { using namespace std; // CHYBA! public: void fun() { using namespace std; // OK ; Použití jmenných prostorů ve vlastních knihovnách // cool_library.h #ifndef COOL_LIBRARY_H #define COOL_LIBRARY_H namespace cool_library { class Cool { /*... */ ; #endif oddělení kolidujících jmen při použití cizích knihoven, které nepoužívají explicitní jmenné prostory namespace Lib1 { #include "library1.h" // obsahuje třídu System namespace Lib2 { #include "library2.h" // obsahuje třídu System System s; // CHYBA! Lib1::System s1; // OK Lib2::System s2; // OK 5

Další čtení pro zvídané http://en.cppreference.com/w/cpp/language/namespace http://en.cppreference.com/w/cpp/language/lookup qualified name lookup unqualified name lookup argument-dependent lookup namespace Test { int x; void print(int y) { print(x); // CHYBA! Test::print(x); // CHYBA! Test::print(Test::x); // OK print(test::x); // taky OK, argument-dependent lookup umožňuje používání přetěžovaných operátorů v jiných jmenných prostorech a mnohé jiné věci Vstupní/výstupní proudy Motivace vstup a výstup z různých druhů zařízení soubory klávesnice, obrazovka (terminál) tiskárna, skener síťový socket abstrakce konkrétního zařízení myšlenka proudů (streams) data plynou proudem od zdroje k cíli využívá principů OOP Hierarchie I/O proudů znázornění hierarchie C++ I/O knihovny (převzato z http://cplusplus. com) 6

základní objekty v souboru <iostream> hierarchie umožňuje proudy s různými vlastnostmi všimněte si vícenásobné dědičnosti abstraktní třída ios_base rozhraní pro vstupní proudy istream rozhraní pro výstupní proudy ostream proudy nelze kopírovat; proč? v C++11 lze proudy přesunovat (move) Standardní vstup/výstup hlavičkový soubor <iostream> standardní instance (objekty) cin standardní vstup, instance třídy istream (stdin v C) cout standardní výstup, instance třídy ostream (stdout v C) cerr standardní chybový výstup, instance třídy ostream (stderr v C) clog standardní logovací výstup, instance třídy ostream (stderr v C) rozdíl mezi cerr a clog: cerr nepoužívá vyrovnávací paměť (buffer) speciální funkce pro manipulaci proudů (manipulátory) např. endl vloží konec řádku a zároveň provede vyprázdnění bufferů (flush) Operátor výstupu << zápis do výstupního proudu přetížen pro standardní typy int x = 7; const double pi = 3.14; char cstring [] = " is "; std::cout << x << " + " << pi << cstring << x + pi << std::endl; // 7 + 3.14 is 10.14 7

pozor na prioritu operátorů ve skutečnosti je << přetížený operátor bitového posuvu http://en.cppreference.com/w/cpp/language/operator_precedence přetížení << pro vlastní třídy ostream & operator<<(ostream & out, const Object & object) { //... funkce, nikoli metoda (nemáme jak přidat metodu do třídy ostream) první parametr: reference na výstupní proud nekonstantní: výstupem do proudu se mění jeho vnitřní stav ne hodnotou: proudy se nesmí kopírovat druhý parametr: objekt, který chceme vypsat na výstup typicky konstantní reference (nechceme objekt měnit ani kopírovat) pro malé objekty možno použít i předání hodnotou operátor vrací referenci na výstupní proud umožňuje řetězení výstupů std::cout << 1 << 'x' << std:endl; // se vlastně vyhodnotí jako ((std::cout << 1) << 'x') << std::endl; // neboli operator<<(operator<<(operator<<(std::cout, 1), 'x'), std::endl); takto definovaný operátor nemá přístup k private a protected atributům našeho objektu řešení 0: gettery řešení 1: speciální metoda Object::print(std::ostream &) řešení 2: deklarace friend (později) Příklad: #include <iostream> class Point { int x, y; public: Point(int sx, int sy) : x(sx), y(sy) { int getx() const { return x; int gety() const { return y; ; std::ostream & operator<<(std::ostream & out, const Point & point) { out << '[' << point.getx() << ", " << point.gety() << ']'; return out; 8

// dalo se napsat i na jeden řádek Point p(3,4); std::cout << p << std::endl; std::cerr << p << std::endl; // cerr je taky instance ostream Operátor vstupu >> čtení ze vstupního proudu přetíženo pro standardní typy int x; double d; char cstring [50]; std::cin >> x >> d; std::cin >> cstring; // možná problém std::string s; std::cin >> s; // přečte jedno slovo ze vstupu // čtení celého řádku ze vstupu, viz metodu getline z <istream> // a funkci getline ze <string> přetížení >> pro vlastní třídy podobně jako << istream & operator>>(istream & in, Object & object) { //... druhý parametr: objekt, bereme referencí (budeme jej měnit) přístup k private a protected atributům našeho objektu řešení 0: settery řešení 1: konstruktor + kopírovací konstruktor řešení 2: deklarace friend (později) Příklad: #include <iostream> class Point { int x, y; 9

public: Point(int sx, int sy) : x(sx), y(sy) { void setx(int sx) { x = sx; void sety(int sy) { y = sy; ; std::istream & operator>>(std::istream & in, Point & point) { int x, y; in >> x >> y; point.setx(x); point.sety(y); return in; Point p(0,0); std::cin >> p; // v p teď jsou atributy nastaveny podle vstupu Chybové stavy proudů proudy obsahují příznaky naznačující chybu eofbit, failbit, badbit metody pro testování stavu good(), fail(), eof() přetížené chování proudů jako bool, přetížený operátor! int x; cin >> x; if (cin) { // načtení hodnoty do x se povedlo if (cin.good()) { // načtení hodnoty se povedlo a zatím nedošlo ke konci vstupu (eof) cin.clear(); // po vyřešení problému vyčistíme příznaky metoda pro vyčištění příznaků clear() více viz http://en.cppreference.com/w/cpp/io/ios_base/iostate tabulka stavů dole Souborové proudy 10

hlavičkový soubor <fstream> třídy ifstream, ofstream, fstream díky dědičnosti (viz tabulku nahoře) můžeme využívat známé chování z cin a cout konstruktor se jménem souboru, metody open() a close() #include <fstream> using namespace std; ofstream output("soubor.txt"); output << "Hello, world!\n"; output.close(); output.open("soubor2.txt"); output << 3.14 << endl; // o zavreni se postara destruktor druhý (nepovinný) parametr konstruktoru mód otevření souboru binární příznaky (flags), kombinujeme pomocí typ otevření ios::in (vstup, implicitní pro ifstream) ios::out (výstup, implicitní pro ofstream) ios::in ios::out (obojí, implicitní pro fstream) způsob otevření ios::binary (binární data, implicitní jsou textová data) ios::app (append, výstup na konec souboru) ios::trunc (vymaže soubor) více viz http://cppreference.com nebo http://cplusplus.com/reference hledejte ios a openmode Příklad: čtení souboru po znacích v C a C++ // C #include <stdio.h> int main(void) { FILE *file = NULL; char filename [] = "soubor.txt"; file = fopen(filename, "r"); if (file) { char c; while ((c = getc(file))!= EOF) { putchar(c); fclose(file); 11

// C++ #include <fstream> using namespace std; ifstream file("soubor.txt"); if (file.is_open()) { char c = cin.get(); while (c.good()) { cout << c; c = cin.get(); Třída istream podrobně operátor >> už známe metoda get() bez parametrů vrací jeden znak více znaků pomocí get(buffer, length) (čte do konce řádku) metoda getline(buffer, length) podobně jako get(), ale zahodí znak konce řádku ('\n) metoda read(buffer, count) blokové čtení daného počtu bytů hlavně pro binární soubory metoda gcount() počet znaků načtených při posledním vstupu metoda peek() náhled na další znak na vstup, bez jeho přečtení metoda ignore(count) zahodí count znaků ze vstupu a další viz reference na webu načtení řádku do řetězce typu std::string funkce getline(istream &, string &) std::string s; getline(std::cin,s); Třída ostream podrobně operátor << už známe 12

metoda put() zapíše jeden znak metoda write(output, count) protiklad read() zápis na konci souboru soubor zvětšuje zápis uvnitř souboru soubor přepisuje Pozice a posun v souboru odkud se čte, kam se zapisuje? get ukazatel (třída istream a její potomci) put ukazatel (třída ostream a její potomci) tellg(), tellp() získání pozice ukazatelů seekg(), seekp() nastavení pozice ukazatelů; dva parametry odkud: ios::beg začátek souboru, ios::cur aktuální pozice, ios::end (konec souboru) offset: o kolik se posunout od pozice odkud počáteční pozice v souboru závisí na módu otevření Vyrovnávací buffery data poslaná do proudu nemusí být ihned zapsána do cíle to by nemuselo být efektivní (např. zápis do souboru) vyrovnávací paměť typu streambuf pro každý proud přenos z vyrovnávací paměti do cíle při uzavření souboru (close(), destruktor) při zaplnění bufferu explicitně pomocí manipulátorů (endl, flush, sync, unitbuf) Manipulátory speciální objekty, které je možno předávat operátorům << a >> některé definovány v <iostream>, některé v <iomanip> flush vyprázdní buffer endl zapíše konec řádku a vyprázdní buffer dec, hex, oct změní způsob reprezentace čísel (desítková, šestnáctková, osmičková) setw, setfill, setprecision mění formát vstupu a výstupu left, right mění zarovnání const double pi = 3.1415; cout << setw(10) << setfill('x') << left << setprecision(3) << pi << endl; // výstup: 3.14xxxxxx http://en.cppreference.com/w/cpp/io/manip Řetězcové proudy hlavičkový soubor <sstream> používají pro ukládání dat paměť místo souborů 13

dědičnost: viz tabulku nahoře umí všechno to, co standardní proudy třídy stringstream, istringstream, ostringstream konstruktor může brát řetězec počáteční stav proudu metoda str() nastaví obsah proudu bez parametrů vrací aktuální obsah proudu jako string Příklad použití: #include <string> #include <sstream> using namespace std; string tostring(double d) { // tato metoda už je v C++11 istringstream s; s << d; return s.str(); string s; getline(cin, s); // načtení řádku ze vstupu stringstream ss(s); int x, y; ss >> x >> y; // parsování řádku Shrnutí Jmenné prostory implicitní (lokální bloky, funkce, třídy, globální prostor) explicitní (namespace), mohou být vnořené zpřístupnění pomocí using namespace nebo using Vstupní/výstupní proudy abstrakce skutečných zařízení hierarchie standardní vstup/výstup souborový vstup/výstup vstup/výstup v paměti přetížené operátory << a >> další metody 14