C++ - strumienie. C++ - strumienie. C++ - strumienie. C++ - strumienie. C++ - strumienie. C++ - strumienie

Podobne dokumenty
Referencje. Zasady zaliczeń. Zasady zaliczeń. Zasady zaliczeń. Zasady zaliczeń. Zaawansowane Programowanie Obiektowe. Informacje organizacyjne:

C++ - strumienie. Strumienie. C++ - strumienie. C++ - strumienie. C++ - strumienie. C++ - strumienie. Formatowanie strumieni wyjściowych

Referencje. Zasady zaliczeń. Zasady zaliczeń. Zasady zaliczeń. Zasady zaliczeń. Zaawansowane Programowanie Obiektowe. Informacje organizacyjne:

Operacje wejścia/wyjścia (odsłona druga) - pliki

jest mocny, skoro da się w nim wyrazić nowe pojęcia; łatwiej przenieść go na nową platformę jest mniejszy.

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Część 4 życie programu

C++ - szablony. C++ - szablony. C++ - strumienie. C++ - strumienie. C++ - strumienie STRUMIENIE

C++ - szablony. C++ - szablony. C++ - szablony. C++ - szablony SZABLONY SZABLONY FUNKCJI

Pliki wykład 2 -przekazywanie strumieni do funkcji -funkcje get(char &) i getline(string)

Pliki wykład 2. Dorota Pylak

Programowanie w C++ Wykład 9. Katarzyna Grzelak. 14 maja K.Grzelak (Wykład 9) Programowanie w C++ 1 / 30

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

Wejście wyjście strumieniowe

Programowanie Obiektowe i C++

1 Podstawy c++ w pigułce.

Wstęp do informatyki- wykład 8 Pętla while, do while,for -pętla w pętli- przykłady Operator rzutowania Manipulatory

1 Podstawy c++ w pigułce.

Programowanie Obiektowo Zorientowane w języku c++ Przestrzenie nazw

Podstawy programowania skrót z wykładów:

Język C++ wykład VIII

Wstęp do Programowania, laboratorium 02

I - Microsoft Visual Studio C++

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

Pliki wykład 2. Dorota Pylak

Podstawy Informatyki. Inżynieria Ciepła, I rok. Wykład 10 Kurs C++

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 21 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 24

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak

Wstęp do programowania obiektowego

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Co nie powinno być umieszczane w plikach nagłówkowych:

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

1 P roste e t ypy p d a d n a ych c - c ąg ą g d a d l a szy 2 T y T py p z ł z o ł żo ż ne e d a d n a ych c : T BLICE

Operacje wejścia/wyjścia odsłona pierwsza

Wstęp do programowania obiektowego. Przekazywanie parametrów do funkcji w C++ Metody i funkcje operatorowe Strumienie: standardowe, plikowe, napisowe

Programowanie w językach

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 26 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28

Wykład 2 Operacje wejściawyjścia. Ewa Gajda

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

Języki i metodyka programowania. Wprowadzenie do języka C

Podział programu na moduły

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

4. Funkcje. Przykłady

Programowanie komputerowe. Zajęcia 1

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

3. Instrukcje warunkowe

Podstawy programowania w C++

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

C++ wprowadzanie zmiennych

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Podstawy Programowania Podstawowa składnia języka C++

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

C++ - szablony. C++ - szablony. C++ - szablony. C++ - szablony. C++ - szablony. C++ - szablony

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

C++ - strumienie. C++ - strumienie. C++ - strumienie. C++ - strumienie. C++ - strumienie STRUMIENIE

Pliki wykład. Dorota Pylak

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Programowanie - wykład 4

Spis treści OPERACJE WEJŚCIA-WYJŚCIA W JĘZYKU C++. STEROWANIE FORMATEM, MANIPULATORY. Informatyka 2

Paostwowa Wyższa Szkoła Zawodowa w Płocku Dariusz Wardowski

Przekazywanie argumentów wskaźniki

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Pliki wykład. Dorota Pylak

C++ - [3-5] Pliki i strumienie w C++

Wyjątki (exceptions)

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane

ZASADY PROGRAMOWANIA KOMPUTERÓW ZAP zima 2015

Podstawy Informatyki. Kompilacja. Historia. Metalurgia, I rok. Kompilatory C++ Pierwszy program. Dyrektywy preprocesora. Darmowe:

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 5. Karol Tarnowski A-1 p.

Programowanie C++ Wykład 2 - podstawy języka C++ dr inż. Jakub Możaryn. Warszawa, Instytut Automatyki i Robotyki

Zajęcia nr 1 Podstawy programowania. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

1. Wypisywanie danych

Wstęp do programowania. Wykład 1

Spis treści OBSŁUGA PLIKÓW W JĘZYKU C++ Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu. Numer ćwiczenia INF32

Operatory na rzecz typu TString

dr inż. Jarosław Forenc

Podstawy Informatyki. Metalurgia, I rok. Wykład 6 Krótki kurs C++

Laboratorium 3: Preprocesor i funkcje ze zmienną liczbą argumentów. mgr inż. Arkadiusz Chrobot

Referencje. Referencje. Zasady zaliczeń. Zasady zaliczeń. Zasady zaliczeń. Zaawansowane Programowanie Obiektowe. Informacje organizacyjne:

Laboratorium 1. Programowanie II - Kierunek Informatyka. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej

Pytania sprawdzające wiedzę z programowania C++

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 12. Karol Tarnowski A-1 p.

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 25 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 38

TEMAT : KLASY DZIEDZICZENIE

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 5

Projektowanie klas c.d. Projektowanie klas przykład

PROE wykład 4 pozostałe operatory, forward declaration, dziedziczenie. dr inż. Jacek Naruniec

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

4. Wyrzuć wyjątek jeśli zmienna ist nie istnieje bloki: try, catch i wyrzucanie wyjątku

Transkrypt:

Ustawianie szerokości, wypełnienia i dokładności: streamsize precision( ) const; streamsize precision( streamsize _Prec ); Metoda zwraca precyzję liczb zmiennoprzecinkowych lub ją ustawia. Precyzja określa, ile cyfr zostanie wykorzystanych przy wypisywaniu liczby (łącznie, tj. przed i po przecinku): float i = 313.12345; cout.precision( 4 ); Ustawianie szerokości, wypełnienia i dokładności: char_type fill( ) const; char_type fill( char_type _Char ); Metoda zwraca znak wypełniający lub go ustawia float i = 313.12345; cout.width( 20 ); cout.fill('*'); cout.precision( 4 ); cout << i << endl << i << endl; Wyjście: 313.1 Wyjście: ***************313.1 313.1 327 328 Dane wejściowe pobierane wierszami: int_type get( ); basic_istream& get( char_type& _Ch ); basic_istream& get(char_type *_Str, streamsize _Count); basic_istream& get( char_type *_Str, streamsize _Count, char_type _Delim ); Przerywa swoje działanie zaraz po znalezieniu ogranicznika, ale tego ogranicznika już nie pobiera ze strumienia. char c[10]; c[0] = cin.get( ); // pobiera jeden element i zwraca pobraną wartość cin.get( c[1] ); // pobiera jeden element i wpisuje do argumentu cin.get( &c[2],3 );// pobiera do napotkania znaku \n, ale max. 3 cin.get( &c[4], 4, '7' );// pobiera do napotkania znaku 7, ale max. 4 cout << c << endl; Dane wejściowe pobierane wierszami: basic_istream& getline( char_type *_Str, streamsize _Count ); basic_istream& getline( char_type *_Str, streamsize _Count, char_type _Delim ); Przerywa swoje działanie zaraz po znalezieniu ogranicznika, którego pobiera ze strumienia. int main( ) char c[10]; // pobiera max. 3 elementy do napotkania 2 cin.getline( &c[0], 5, '2' ); cout << c << endl; 329 330 Dane wejściowe pobierane wierszami: Funkcja globalna getline() z pliku nagłówkowego <string> wprowadza dane ze strumienia do obiektu typu string. Wczytuje do napotkania ogranicznika, znaku końca pliku, lub gdy liczba wczytanych znaków przekroczy is.max_str : int main() string s1; cout << wprowadź tekst (uzyj <spacja> jako znaku końca): "; getline(cin,s1, ' '); cout << Wprowadziłeś: " << s1 << endl;; const int SZ = 100; // rozmiar bufora char buf[sz]; ifstream in("test1.txt"); ofstream ou("test2.txt", ios::app); while(in.getline(buf, SZ)) // uwaga: getline usuwa \n char* cp = buf; while(*cp!= ':') ++cp; *cp = 0; cp += 2; cout << cp << endl; ou << cp << ":" << buf << endl; Test1.txt: Iksiński:00 Kowalski:01 Nowak:02 Okno terminala: 0 1 2 Co zawiera Test2.txt? 331 332 1

basic_istream& ignore( streamsize _Count = 1, int_type _Delim = traits_type::eof( ) ); pomija określoną liczbę znaków w strumieniu wejściowym, lub nieokreśloną aż do wystąpienia określonego znaku: char chardynamicznystos[10]; cout << Napisz 'abcdef': "; cin.ignore( 5, 'c' ); cin >> chardynamicznystos; cout << chardynamicznystos; Wyjście: def int_type peek( ); zwraca jeden znak ze strumienia (w postaci zmiennej typu int, aby mógł to być również znak EOF). Znak pozostaje w strumieniu i będzie pierwszym znakiem wczytanym przy następnej operacji czytania char c[10], c2; cout << Napisz 'abcde': "; c2 = cin.peek( ); cin.getline( &c[0], 9 ); cout << c2 << " " << c << endl; Wyjście: Napisz 'abcde': abcde a abcde 333 334 basic_istream& putback( char_type _Ch ); wstawia znak _Ch do strumienia; będzie on pierwszym znakiem wczytanym przez następną operację czytania. Zwraca odnośnik do strumienia na rzecz którego została wywołana. Nie do każdego strumienia i nie zawsze można wstawić znak char c[10], c2, c3; c2 = cin.get( ); // użytkownik nacisnął klawisz q c3 = cin.get( ); // użytkownik nacisnął klawisz w cin.putback( c2 ); cin.getline( &c[0], 9 ); cout << c << endl; basic_istream& unget( ); wstawia ostatnio przeczytany znak z powrotem do strumienia; będzie on pierwszym znakiem wczytanym przez następną operację czytania. Zwraca odnośnik do strumienia na rzecz którego został wywołany. char c[10], c2; cout << Napisz 'abc': "; c2 = cin.get( ); cin.unget( ); cin.getline( &c[0], 9 ); cout << c << endl; Wyjście: qw q Wyjście: Napisz abc : abc abc 335 336 Przykład: cout << "Wpisuj linie tekstu. Zakończ znakiem końca pliku\n << "(Ctr-Z w Windows, Ctr-D w Linuksie). Komentarze\n << "od \'//\' do końca linii będą pomijane\n\n"; char c; while ( cin.get(c) ) if ( c == '/' ) if ( cin.peek() == '/') // sprawdź, czy następny to też slash cin.ignore(1024,'\n'); // pomiń 1024 znaki lub do końca linii cout << endl; continue; cout << c; Działania na flagach stanu: Zerowanie flagi błędu: void clear( iostate _State=goodbit ); zeruje flagi błędu (wywołanie bez argumentu) i ewentualnie ustawia niektóre z nich podane w argumencie wywołania. 337 338 2

Działania na flagach stanu: iostate rdstate( ) const; odczytuje stan bitów dla flag void TestFlags( ios& x ) cout << ( x.rdstate() & ios::badbit ) << ' '; cout << ( x.rdstate() & ios::failbit ) << ' '; cout << ( x.rdstate() & ios::eofbit ) << endl; cout << endl; int main( ) ofstream ofx( "test.txt" ); ofx.clear( ); TestFlags( ofx ); ofx.clear( ios::badbit ios::failbit ios::eofbit ); TestFlags( ofx ); basic_ostream<elem, Traits> *tie( ) const; basic_ostream<elem, Traits> *tie( basic_ostream<e, T> *_Str ); gwarantuje kolejność wykonywania operacji na strumieniach Pierwsza metoda zwraca wskaźnik wiązania dla strumienia, druga umieszcza wskaźnik do strumienia w swoim polu wskaźnika wiązania. W ten sposób gwarantuje, że działania na powiązanym drugim strumieniu nie rozpoczną się, zanim w pełni nie zostaną zakończone działania na pierwszym. int i; cin.tie( &cout ); cout << Wprowadź liczbę:"; cin >> i; Wyjście: 0 0 0 Przykład jest sztuczny, ponieważ domyślnie strumienie cin i cout są powiązane 1 4 2 339 340 Metoda operator void*() explicit operator bool() // (C++98) // (C++11) Metoda bool operator!( ) const; wywołuje na rzecz strumienia metodę fail(): wywołuje na rzecz strumienia metodę good(): int i; while (mystream >> i) cout << i << endl if (!mystream) // wykonaj obsługę tej sytuacji 341 342 Manipulatory Są to funkcje zdefiniowane w klasie ios i wywoływane poprzez podanie ich nazw jako elementów wstawianych do lub wyjmowanych ze strumienia. Ich działanie może, ale nie musi, polegać na modyfikacji flagi stanu formatowania strumienia Strumienie Manipulatory bezargumentowe W zasadzie nie muszą to być wyłącznie funkcje. Mogą to też być obiekty funkcyjne. Obiekty funkcyjne? 344 3

Dygresja obiekty funkcyjne Obiekty funkcyjne to coś co da się wywołać. Istnieje specjalny operator wywołania (), który można dodać do klasy i odpowiednio go przeciążyć. Obiekt takiego typu staje się obiektem wywoływalnym (callable object, function object, functor). Operator wywołania jest jedynym, który może mieć dowolną liczbę argumentów (np. więcej niż dwa) Instrukcja zawierająca nazwę obiektu tej klasy z podanymi argumentami w nawiasach powoduje wywołanie metody przeciążającej operator (). Definicja dla operatora wywołania () : typ klasa::operator() (argumenty) // ciało funkcji Przykład: klasa posiadająca przeciążony operator wywołania służący do policzenia wartości wielomianu wg schematu Hornera Schemat Hornera sposób obliczenia wartości wielomianu dla danej wartości argumentu wykorzystujący minimalną liczbę mnożeń. Np.: 3x 4 +2x 3 +7x 2 +9x+5 Weźmy pod uwagę pierwsze cztery elementy naszego wielomianu. Możemy dla tych elementów wyłączyć wspólny czynnik przed nawias. Tym czynnikiem jest x: (3x 3 +2x 2 +7x+9)x+5 Teraz "wyciągamy" przed nawias x z pierwszych trzech elementów w nawiasie: ((3x 2 +2x+7)x+9)x+5) Następnie wyłączmy przed nawias następne x z dwóch pierwszych elementów w wewnętrznym nawiasie: (((3x+2)x+7)x+9)x+5 345 346 double tab[] = 5, 9, 7, 2, 3 ; class Wielom double a; public: double operator() (double) const; ; double Wielom::operator()(double x) const double d = 0; for(int i = 4; i >= 0; i--) d = d*x + tab[i]; return d; ; int main(int argc, char *argv[]) Wielom p; double x = p(7); cout << x << endl; Wywołania obiektów z przeciążonym operatorem wywołania można wstawić wszędzie tam, gdzie może występować wywołanie funkcji. Mają tę przewagę nad funkcjami, że tworząc je można, na przykład poprzez konstruktor, przekazać do nich dodatkową informację prócz samych tylko argumentów wywołania. Obiekty funkcyjne zapewniają większą elastyczność algorytmów wyrażonych poprzez szablony. koniec dygresji o obiektach funkcyjnych 347 348 Manipulatory bezargumentowe hex, oct, dec podstawa dla wczytywanych/pisanych liczb całkowitych Wykorzystanie metod: int i = 10; cout.setf( ios_base::oct ); cout.setf( ios_base::hex, ios_base::oct ); cout.unsetf( ios_base::hex ); cout.setf( ios_base::dec ); Wykorzystanie manipulatorów: int i = 10; cout << oct; cout << hex; cout.unsetf( ios_base::hex ); cout << dec; 349 350 4

Manipulatory bezargumentowe left, right, internal wyrównanie przy przypisaniu do lewej, prawej albo obustronnie fixed, scientific format dla wypisywanych liczb zmiennoprzecinkowych showbase, noshowbase przy wypisywaniu zawsze pokaż podstawę (wiodące zero lub 0x) showpoint, noshowpoint - zawsze wypisz kropkę dziesiętną i końcowe zera w części ułamkowej Manipulatory bezargumentowe Dedykowane dla ostream: flush powoduje opróżnienie strumienia wyjściowego endl powoduje wysłanie od strumienia wyjściowego znaku końca linii i opróżnienie bufora związanego z tym strumieniem, czyli natychmiastowe wyprowadzenie znaków z bufora do miejsca przeznaczenia ends powoduje wysłanie do strumienia wyjściowego znaku końca napisu, czyli znaku \0 Dedykowane dla istream: ws powoduje wymuszenie zignorowania wiodących białych znaków przy wczytywaniu 351 352 Własne manipulatory bezargumentowe Tworzymy je jako funkcje globalne 1. z dokładnie jednym parametrem, który musi być typu referencja do strumienia ; 2. wartością zwracaną musi być ten sam odnośnik. ostream& mój_manip(ostream& strum) // tutaj nasz kod działający na strumieniu return strum; ios_base::fmtflags flagi_domyslne; ostream& naukowy(ostream& str) flagi_domyslne = str.flags(); str.setf(ios::showpos ios::showpoint); str.setf(ios::scientific, ios::floatfield); str.precision(12); return str; ostream& normalny(ostream& str) str.flags(flagi_domyslne); return str; ostream& przec(ostream& str) return str << ", "; int main(int argc, char *argv[]) double x = 123.456; cout << naukowy << x << przec << normalny << x << endl; Taki manipulator zwraca referencję do strumienia, na rzecz którego został wywołany, dlatego można wstawiać do strumienia kaskadowo wraz z innymi argumentami czy manipulatorami. 353 354 Własne manipulatory bezargumentowe We wszystkich przypadkach w poprzednim przykładzie parametr wywołania funkcji definiującej manipulator ma typ ostream& To daje elastyczność: nigdzie nie jest powiedziane, że to musi być cout może to być dowolny strumień reprezentowany obiektem ostream lub obiektem dowolnej klasy dziedziczącej po ostream (np. fstream, etc.) PRZESTRZENIE NAZW I STANDARDOWE BIBLIOTEKI 355 5

Czasem w plikach C++ zakładanych automatycznie używana jest dyrektywa using: using namespace std; Po co? Ponieważ w C++ wszystko, co programista utworzy i wszystko, co zawarte jest w bibliotekach funkcjonuje w jakiejś przestrzeni nazw. A my najczęściej chcemy używać tego, co należy do przestrzeni nazw std 357 358 Co to jest przestrzeń nazw? Przestrzenie nazw pozwalają na podział kodu na logiczne jednostki. Stąd: przestrzeń nazw fragment kodu programu. Oczekiwania: wewnątrz jednej przestrzeni nazw wszystkie funkcje i klasy powinny logicznie uzupełniać się tworząc całość skierowaną na realizacje określonego celu, np. kompletną implementację złożonego algorytmu, bądź np. jeżeli mamy program łączący się przez internet kompletną funkcjonalność związaną z tą łącznością: namespace net_connect int make_connection(); int test_connection(); // itd... Poza tą przestrzenią można odwoływać się do jej funkcji i klas korzystając z prefixu takiego, jak nazwa przestrzeni oraz operatora zakresu :: Przykład: net_connect::make_connection(); Czemu ma służyć taki podział kodu? Podziałowi składowych programu na grupy, podobne do klas albo struktur. Przestrzenie nazw nie tworzą jednak żadnych obiektów, nie potrzebują tworzenia swoich instancji, żeby być używane. Po prostu aby użyć określonej funkcji piszemy tylko nazwę przestrzeni i nazwę tej funkcji. Ten podział pozwala na nadawanie tych samych nazw funkcjom należącym do różnych przestrzeni nazw, a więc chroni przed potencjalnymi konfliktami nazw w przypadku łączenia bibliotek. Jeżeli nie chcemy za każdym razem pisać nazwy przestrzeni możemy się do niej odwołać przez słowo kluczowe using Jeżeli w bloku kodu napiszemy using namespace nazwa_przestrzeni w obrębie tego bloku możemy odwoływać się do wszystkich funkcji należących do tej przestrzeni bez potrzeby podawania jej nazwy jako prefixu (jeżeli napiszemy tak na początku pliku dostęp do funkcji obowiązuje w obrębie całego pliku) Jeżeli chcemy odwoływać się tylko do wybranej funkcji z pewnej przestrzeni nazw możemy napisać: using nazwa_przestrzeni::nazwa_funkcji 359 360 namespace A const int two = 2; void napisz() printf( A\n ); ; namespace B void napisz() printf( B\n ); ; namespace C const int two = 22; int main () using A::napisz; using namespace C; napisz(); B::napisz(); printf( %i\n,two); return 0; // co się pojawi w oknie konsoli? A jeżeli chcemy w obrębie całego pliku korzystać ze wszystkich funkcji bibliotecznych, piszemy: using namespace std; ponieważ właśnie te funkcje są zadeklarowane w przestrzeni nazw std 361 362 6

Przestrzenie nazw to nowy element w C++. W C też używamy plików nagłówkowych bibliotek standardowych, ale tam wszystkie nazwy w nich zadeklarowane są jednakowo dostępne bez żadnych kwalifikacji nie ma tam mechanizmu przestrzeni nazw. Aby zapewnić możliwość kompilowania programów w C przez kompilatory C++ przyjęto umowę: jeżeli włączymy plik w sposób tradycyjny, podając pełną nazwę pliku nagłówkowego, jest on włączany oraz automatycznie otwierana jest nowa przestrzeń nazw std. Jeżeli ten sam plik włączymy pod nową nazwą, to przestrzeń std nie jest automatycznie otwierana. Przykład: C: #include <string.h> C++: #include <cstring> Przyjęto konwencję, że pliki nagłówkowe o tradycyjnej nazwie nazwa.h są w C++ nazywane cnazwa : assert.h cassert limits.h climits stdio.h cstdio time.h ctime ctype.h cctype stdlib.h cstdlib math.h cmath... iostream (!) W kodzie programu pisanego w C++ należy używać wersji przygotowanej dla C++. 363 364 Cały kod, który został napisany poza jakąkolwiek przestrzenią nazw w rzeczywistości należy do tzw. globalnej przestrzeni nazw Jeżeli chcemy tylko zamknąć kod w swojej przestrzeni nazw, możemy napisać: namespace class Car... // składowe klasy Car // inne składowe przestrzeni nazw bez nazwy (unnamed namespace) Kiedy używamy przestrzeni nazw bez nazwy, kompilator sam wymyśla dla niej unikalną nazwę Po co używać takiej przestrzeni nazw? Jeżeli deklarujemy struktury lub klasy, które będą używane tylko w lokalnym fragmencie kodu, mamy pewność, że ich nazwa nie wejdzie w kolizję z nazwą zadeklarowaną gdziekolwiek w globalnej przestrzeni nazw. 365 366 STANDARDOWE DYREKTYWY PREPROCESORA Preprocessing: Zbiór działań wykonywanych tuż przed kompilacją wskazanego pliku. Aby zobaczyć wynik działania preprocesora należy (VS2017): 368 7

Standardowe dyrektywy dzielą się na trzy rodzaje: 1. Dołączające plik we wskazanym miejscu: #include 2. Makra: #define 3. Definiujące warunkową kompilację: #if, #ifdef, #ifndef, #elif, #else, Składnia i zasady stosowania 1. Zawsze na początku linii zaczynają się od # 2. Mogą wystąpić w każdym miejscu w programie 3. Mogą za nimi wystąpić komentarze 4. Zajmują jedną linię, chyba że jawnie wprowadzono znak kontynuacji Dołączanie plików Dołączane pliki powinny być do tego odpowiednio przygotowane. Przyjmuje się, że tak przygotowany przez programistę jest każdy plik z rozszerzeniem h Polecenie: #include <filename> mówi preprocesorowi, aby zastąpił w/w linię zawartością wskazanego pliku. Są dwa formaty: 1. #include "filename" szuka pliku w bieżącym folderze, a jeżeli nie znajdzie, w folderach wskazanych w systemie (w systemowych zmiennych środowiskowych, np. PATH, INCLUDE, itp.) dla plików h użytkownika 2. #include <filename> szuka pliku tylko w folderach wskazanych w systemie (w systemowych zmiennych środowiskowych, np. PATH, INCLUDE, itp.) dla plików h bibliotecznych i systemowych 369 370 Dyrektywa #define Polecenie: #define nazwa dużo_różnego_tekstu mówi preprocesorowi, aby każde wystąpienie nazwa zastąpił przez dużo_różnego_tekstu. Drugi argument, tj. dużo_różnego_tekstu jest opcjonalny. Jeżeli go nie ma, identyfikator nazwa istnieje, ale nie ma wartości. Taki identyfikator też może być przydatny jako flaga (można sprawdzać, czy jest, albo czy go nie ma) Dyrektywa #define 1. Zastępuje tekst powtarzany w wielu miejscach kodu innym tekstem. 2. Najczęściej używana do definiowania stałych. 3. Stałe zwykle pisane są DRUKOWANYMI literami (taka konwencja), aby programistom było łatwiej je rozpoznać. Przykład: to może powodować komunikat ostrzeżenia (warning): #define SOME_VALUE 5 #define SOME_VALUE 6 Polecenie: #undef nazwa mówi preprocesorowi, aby usunął ( oddefiniował ) nazwa. A to pójdzie gładko: #define SOME_VALUE 5 #undef SOME_VALUE #define SOME_VALUE 6 371 372 Makra Tutaj nie wolno dać spacji (!) Makra Ogólna forma definicji makra: #define macro(param1, param2, ) value Przykład: #define SUM(a, b) a + b... x = SUM(2, 6); /* zostanie zamienione na: "x = 2 + 6;" */ Łamanie wierszy: #define INC(A) \ if ((A) < 100) \ (A)++; \ else \ printf ("Błąd: przepełnienie.\n"); Jeżeli makro jest dłuższe, niż zaplanowana szerokość wiersza, można je łamać: #define MIN(a, b) a < b \? a : b 373 374 8

Makra przykłady: #define SQUARE(x) ((x) * (x)) s = SQUARE(5); staje się: s = ((5) * (5)); s = SQUARE(a + 1); staje się: s = ((a + 1) * (a + 1)); Makra przykłady: #define MAX(a, b) \ ((a) > (b)? (a) : (b)) x = 4; y = 9; z = MAX(x, y); staje się: z = ((x) > (y)? (x) : (y)); 375 376 Makra przykłady: Stosowanie makra działa jak polecenie znajdź i zastąp w edytorze tekstu: #define SQUARE1(x) x * x #define SQUARE2(x) (x * x) #define BAD_SUM(x, y) (x) + (y) s = SQUARE1(a + 1); /* s = a + 1 * a + 1; */ s = SQUARE2(a + 1); /* s = (a + 1 * a + 1); */ s = BAD_SUM(a + 1, b + 2) * 3; /* s = (a + 1) + (b + 2) * 3; */ Dlatego stosowanie nawiasów jest takie ważne (!) Makra Działanie preprocesora zamiana symboli na wartości: 1. Argumenty wywołanych makr sprawdzane są, czy same nie reprezentują symboli zdefiniowanych za pomocą #define 2. Argumenty będące zdefiniowanymi symbolami są zastępowane wartościami 3. Zmodyfikowany program jest sprawdzany, czy występują w nim nadal symbole zdefiniowane za pomocą #define, i jeżeli tak powrót do pkt 1. Wyjątek: literały nie są skanowane, np.: #define MAX 10 printf("wartość MAX wynosi %d.\n", MAX); Wyjście: Wartość MAX wynosi 10. 377 378 Makra to nie funkcje! Ponieważ: 1. Są podmieniane tekstowo co może dać szybszy kod w przypadku prostych czynności. 2. Mogą być rekurencyjne. 3. Nie obejmuje ich kontrola typów podczas kompilacji. 4. Mogą generować bardzo skomplikowane błędy zachowania programu mimo poprawnej kompilacji. 5. Mogą mieć identyfikatory typów jako argumenty, np.: #define PRINT_SIZE(type) \ printf("%d\n", (int) sizeof(type)) Makra łatwo dają efekty uboczne Przykład: #define MIN(x, y) ((x) < (y)? (x) : (y)) m = MIN(++a, --b); /* m = ((++a) < (--b)? (++a) : (--b)); */ Co wtedy robić? Nie używać wyrażeń dających efekty uboczne jako argumentów. Ale skąd wiadomo, że wywołuję makro? Należy stosować konwencję nazewniczą dotyczącą makr i robi się łatwiej.. 379 380 9

Dyrektywy wspierające warunkową kompilację: #if #ifdef #ifndef #else #elif #if const-expr1 Linijki kodu znajdujące się tutaj są dołączane przez procesor do pliku wynikowego tylko jeżeli const-expr1 jest prawdziwe #elif const-expr2 Linijki kodu znajdujące się tutaj są dołączane przez procesor do pliku wynikowego tylko jeżeli const-expr1 jest fałszywe a const-expr2 jest prawdziwe #else Linijki kodu znajdujące się tutaj są dołączane przez procesor do pliku wynikowego tylko jeżeli const-expr1 jest fałszywe i const-expr2 też jest fałszywe 381 382 Najbardziej użyteczna dyrektywa: #ifdef identifier 1. Cały kod występujący po niej zostanie dołączony przez preprocesor do pliku wynikowego w zależności od tego, czy identifier istnieje, czy nie. 2. Jej obszar działania ogranicza wystąpienie. Następne linijki kodu traktowane są już jako konieczne do dołączenia chyba, że kolejne wywołanie dyrektywy to zmieni. Przykład użycia funkcja drukująca wartość tylko w trybie DEBUG: void debug_print (int i) #ifdef DEBUG printf ("DEBUG PRINT: %d\n", i); Ale w trybie release to nadal jest wywołanie funkcji. Czy można tego uniknąć?.. 383 384 Makro wykorzystujące warunkową kompilację: #ifdef DEBUG #define debug_print(a) \ printf ("DEBUG PRINT: %d\n", (int)a); #else #define debug_print(a) #ifdef NDEBUG #define assert(ex) #else #define assert(ex) (void)((ex) ( assert (#EX, FILE, LINE ),0)) #ifdef cplusplus extern "C" extern void assert (const char *msg, const char *file, int line); #ifdef cplusplus ; 385 386 10