języka C Bogdan Kreczmer bogdan.kreczmer@pwr.wroc.pl Zakład Podstaw Cybernetyki i Robotyki Instytut Informatyki, Automatyki i Robotyki Politechnika Wrocławska Kurs: Copyright c 2012 Bogdan Kreczmer Niniejszy dokument zawiera materiały do wykładu dotyczącego programowania obiektowego. Jest on udostępniony pod warunkiem wykorzystania wyłącznie do własnych prywatnych potrzeb i może on być kopiowany wyłącznie w całości, razem z niniejszą stroną tytułową. języka C
Niniejsza prezentacja została wykonana przy użyciu systemu składu PDFL A TEX oraz stylu beamer, którego autorem jest Till Tantau. Strona domowa projektu Beamer: http://latex-beamer.sourceforge.net języka C
1 Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła 2 języka C
Moje dane Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła Bogdan Kreczmer, dr inż., pok. 307 bud C-3 Terminy konsultacji: wt. 14:00 15:00 cz. 13:00 14:00 pt. 13:00 15:00 Strona kursu: http://rab.iiar.pwr.wroc.pl/ kreczmer/zamp
Warunki zaliczeń Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła Kurs kończy się zaliczeniem. Warunkiem uzyskania zaliczenia jest otrzymanie oceny pozytywnej z kolokwium i oceny pozytywnej z laboratorium. Istnieje możliwość zwolnienia z kolokwium na podstawie oceny z laboratorium. Warunki zwolnienia: brak opóźnień w oddawaniu programów na laboratorium, ocena z laboratorium 5, 0 ocena z kursu: 5, 0, ocena z laboratorium 4, 5 ocena z kursu: 4, 0. Sposób liczenia oceny w przypadku pisania kolokwium: Ocena z kursu = 40% oceny laboratorium + 60% oceny z kolokwium Ocena celująca z kursu kolokwium: 5, 0; laboratorium: 5, 5 lub kolokwium: 5, 5; laboratorium: 5, 0
Warunki zaliczeń Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła Kurs kończy się zaliczeniem. Warunkiem uzyskania zaliczenia jest otrzymanie oceny pozytywnej z kolokwium i oceny pozytywnej z laboratorium. Istnieje możliwość zwolnienia z kolokwium na podstawie oceny z laboratorium. Warunki zwolnienia: brak opóźnień w oddawaniu programów na laboratorium, ocena z laboratorium 5, 0 ocena z kursu: 5, 0, ocena z laboratorium 4, 5 ocena z kursu: 4, 0. Sposób liczenia oceny w przypadku pisania kolokwium: Ocena z kursu = 40% oceny laboratorium + 60% oceny z kolokwium Ocena celująca z kursu kolokwium: 5, 0; laboratorium: 5, 5 lub kolokwium: 5, 5; laboratorium: 5, 0
Warunki zaliczeń Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła Kurs kończy się zaliczeniem. Warunkiem uzyskania zaliczenia jest otrzymanie oceny pozytywnej z kolokwium i oceny pozytywnej z laboratorium. Istnieje możliwość zwolnienia z kolokwium na podstawie oceny z laboratorium. Warunki zwolnienia: brak opóźnień w oddawaniu programów na laboratorium, ocena z laboratorium 5, 0 ocena z kursu: 5, 0, ocena z laboratorium 4, 5 ocena z kursu: 4, 0. Sposób liczenia oceny w przypadku pisania kolokwium: Ocena z kursu = 40% oceny laboratorium + 60% oceny z kolokwium Ocena celująca z kursu kolokwium: 5, 0; laboratorium: 5, 5 lub kolokwium: 5, 5; laboratorium: 5, 0
Warunki zaliczeń Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła Kurs kończy się zaliczeniem. Warunkiem uzyskania zaliczenia jest otrzymanie oceny pozytywnej z kolokwium i oceny pozytywnej z laboratorium. Istnieje możliwość zwolnienia z kolokwium na podstawie oceny z laboratorium. Warunki zwolnienia: brak opóźnień w oddawaniu programów na laboratorium, ocena z laboratorium 5, 0 ocena z kursu: 5, 0, ocena z laboratorium 4, 5 ocena z kursu: 4, 0. Sposób liczenia oceny w przypadku pisania kolokwium: Ocena z kursu = 40% oceny laboratorium + 60% oceny z kolokwium Ocena celująca z kursu kolokwium: 5, 0; laboratorium: 5, 5 lub kolokwium: 5, 5; laboratorium: 5, 0
Warunki zaliczeń Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła Kurs kończy się zaliczeniem. Warunkiem uzyskania zaliczenia jest otrzymanie oceny pozytywnej z kolokwium i oceny pozytywnej z laboratorium. Istnieje możliwość zwolnienia z kolokwium na podstawie oceny z laboratorium. Warunki zwolnienia: brak opóźnień w oddawaniu programów na laboratorium, ocena z laboratorium 5, 0 ocena z kursu: 5, 0, ocena z laboratorium 4, 5 ocena z kursu: 4, 0. Sposób liczenia oceny w przypadku pisania kolokwium: Ocena z kursu = 40% oceny laboratorium + 60% oceny z kolokwium Ocena celująca z kursu kolokwium: 5, 0; laboratorium: 5, 5 lub kolokwium: 5, 5; laboratorium: 5, 0
Warunki zaliczeń Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła Kurs kończy się zaliczeniem. Warunkiem uzyskania zaliczenia jest otrzymanie oceny pozytywnej z kolokwium i oceny pozytywnej z laboratorium. Istnieje możliwość zwolnienia z kolokwium na podstawie oceny z laboratorium. Warunki zwolnienia: brak opóźnień w oddawaniu programów na laboratorium, ocena z laboratorium 5, 0 ocena z kursu: 5, 0, ocena z laboratorium 4, 5 ocena z kursu: 4, 0. Sposób liczenia oceny w przypadku pisania kolokwium: Ocena z kursu = 40% oceny laboratorium + 60% oceny z kolokwium Ocena celująca z kursu kolokwium: 5, 0; laboratorium: 5, 5 lub kolokwium: 5, 5; laboratorium: 5, 0
Plan kursu (wykład) Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła 1 języka C, wstęp do programowania uogólnionego w języku C 2 Programowanie uogólnione w języku C oraz w języku C++ 3 Wybrane szablony z STL C++, C++ 0x, wstęp do XML 4 XML i XML Scheme, automake - tworzenie pakietów instalacyjnych, latex bibtex 5 Interpetery. bash, Lisp, Python - wybrane zagadnienia Strona kursu: http://rab.iiar.pwr.wroc.pl/ kreczmer/zamp
Plan kursu (laboratorium) Konsultacje Warunki zaliczenia Plan kursu Źródła 1 Interpreter opisu działań robota mobilnego wykorzystanie preprocesora 2 Interpreter opisu działań robota mobilnego XML 3 Interpreter opisu działań robota mobilnego Urbi 4 Pakiet instalacyjny interpretera opisu działań robota mobilnego Strona kursu: http://rab.iiar.pwr.wroc.pl/ kreczmer/zamp
Literatura Organizacja kursu Konsultacje Warunki zaliczenia Plan kursu Źródła Jerry Cain, Programming Paradigms, wykłady David Vandevoorde, Nicolai M. Josuttis, C++ szablony, Helion, 2003 Thomas G. Habing, XML Tutorial, 2004 (prezentacja) D. MacKenzie, T. Tromey, A. Duret-Lutz; GNU Automake, 2009 D. MacKenzie, B. Elliston, A. Demaille; GNU Autoconf, 2010 Ch. Ramey, B. Fox; Bash Reference Manual, 2009
Definiowanie symbolu Organizacja kursu #define ROZMIAR TAB 100
Definiowanie symbolu Organizacja kursu #define ROZMIAR TAB 100 Treścią definiowanego symbolu jest to, co znajduje się za nim w tej samej linii.
Definiowanie symbolu Organizacja kursu #define ROZMIAR TAB 100 Treścią definiowanego symbolu jest to, co znajduje się za nim w tej samej linii. #define ROZMIAR TAB 100 int Tablica[ROZMIAR TAB]; /* W tym programie niewiele się dzieje :( */ for (int i = 0; i < ROZMIAR TAB-1; ++i) Tablica[i] = Tablica[i+1]; // Przepisywanie wartości w w dół
Definiowanie symbolu Organizacja kursu #define ROZMIAR TAB 100 Przed zasadniczą kompilacją tekst programu przetwarzany jest przez preprocesor. int Tablica[100]; for (int i = 0; i < 100-1; ++i) Tablica[i] = Tablica[i+1];
Wieloliniowe definicje symboli #define WARTOSCI POCZATKOWE 437, 567, 201, 109, 309,\ 561, 789, 401, 271, 901,\ 654, 978, 982, 729, -1 Jeżeli treść symbolu chcemy umieścić w kilku liniach, to na końcu linii poprzedniej musi być znak kontynuacji \. będzie traktował całość jako jedną długą linię.
Wieloliniowe definicje symboli #define WARTOSCI POCZATKOWE 437, 567, 201, 109, 309,\ 561, 789, 401, 271, 901,\ 654, 978, 982, 729, -1 Jeżeli treść symbolu chcemy umieścić w kilku liniach, to na końcu linii poprzedniej musi być znak kontynuacji \. będzie traktował całość jako jedną długą linię. #define WARTOSCI POCZATKOWE 437, 567, 201, 109, 309,\ 561, 789, 401, 271, 901,\ 654, 978, 982, 729, -1 int Tablica[ ] = WARTOSCI POCZATKOWE ; for (int i = 1; Tablica[i] > 0; ++i) Tablica[i-1] = Tablica[i];
Wieloliniowe definicje symboli #define WARTOSCI POCZATKOWE 437, 567, 201, 109, 309,\ 561, 789, 401, 271, 901,\ 654, 978, 982, 729, -1 Tekst makra jest rozwijany po uprzedniej redukcji wielokrotnych spacji prowadzących. int Tablica[ ] = 437, 567, 201, 109, 309, 561, 789, 401, 271, 901, 654, 978, 982, 729, -1; for (int i = 1; Tablica[i] > 0; ++i) Tablica[i-1] = Tablica[i];
Definiowanie symboli pustych #define WSTEPNY TEST Definicje symboli pustych wykorzystywane są do sterowania przebiegiem kompilacji kodu. Realizowane to jest poprzez kompilację warunkową.
Dyrektywa warunkowa #ifdef #define WSTEPNY TEST Definicje symboli pustych wykorzystywane są do sterowania przebiegiem kompilacji kodu. Realizowane to jest poprzez kompilację warunkową. #define WSTEPNY TEST int Zm; #ifdef WSTEPNY TEST if (Zm!= 0) return 1; #endif
Dyrektywa warunkowa #ifdef #define WSTEPNY TEST Kod znajdujący się wewnątrz dyrektywy #ifdef, dla której spełniony jest warunek istnienia definicji symbolu, zostaje dołączony do kompilowanego tekstu programu. int Zm; if (Zm!= 0) return 1;
Dyrektywa warunkowa #ifndef #define WSTEPNY TEST Dyrektywa warunkowa #ifndef, testuje warunek nieistnienia definicji danego symbolu. #define WSTEPNY TEST int Zm; #ifndef WSTEPNY TEST if (Zm!= 0) return 1; #endif
Dyrektywa warunkowa #ifndef #define WSTEPNY TEST Jeśli dla dyrektywy warunkowej warunek nie jest spełniony, to kod nie zostaje dołączony do kompilowanego tekstu programu. int Zm;
Dyrektywa warunkowa #ifndef #define WSTEPNY TEST Czy można zmienić zapis tej dyrektywy #ifndef tak, aby tekst był dołączany wtedy gdy symbol jest zdefiniowany? #define WSTEPNY TEST int Zm; #ifndef WSTEPNY TEST if (Zm!= 0) return 1; #endif
Dyrektywa warunkowa #ifndef #define WSTEPNY TEST Aby to otrzymać wystarczy dopisać dyrektywę #else. #define WSTEPNY TEST int Zm; #ifndef WSTEPNY TEST #else if (Zm!= 0) return 1; #endif
Dyrektywa warunkowa #ifndef #define WSTEPNY TEST Tym razem dołączany jest kod, który znajduje się w sekcji else dyrektywy #ifndef. int Zm; if (Zm!= 0) return 1;
Dyrektywa warunkowa #if #define WSTEPNY TEST Do sprawdzania istnienia definicji symbolu można wykorzystać ogólną postać dyrektywy #if wraz z odpowiednim operatorem. #define WSTEPNY TEST int Zm; #if defined(wstepny TEST) if (Zm!= 0) return 1; #endif
Dyrektywa warunkowa #if #define WSTEPNY TEST W wyrażeniu logicznym można użyć operatora negacji. #define WSTEPNY TEST int Zm; #if! defined(wstepny TEST) #else if (Zm!= 0) return 1; #endif
Dyrektywa warunkowa #if #define WSTEPNY TEST Można też użyć operatora koniunkcji i alternatywy. Ich oznaczenie jest takie samo jak w języku C/C++. Operator negacji ma najwyższy priorytet. #define WSTEPNY TEST int Zm; #if! defined(wstepny TEST) && ( defined( GNUG ) defined( BORLANDC ) ) #else if (Zm!= 0) return 1; #endif
Dyrektywa warunkowa #if #define WSTEPNY TEST Równoważna postać. #define WSTEPNY TEST int Zm; #if (! defined(wstepny TEST)) && ( defined( GNUG ) defined( BORLANDC ) ) #else if (Zm!= 0) return 1; #endif
Dyrektywa warunkowa #if #define WSTEPNY TEST Równoważna postać. #define WSTEPNY TEST int Zm; #if! defined WSTEPNY TEST && (defined GNUG defined BORLANDC ) #else if (Zm!= 0) return 1; #endif
Pragma dyrektywa dla kompilatora #pragma implementation
Pragma dyrektywa dla kompilatora #pragma implementation Pragma nie jest dyrektywą preprocesora, choć rozpoczyna się od znaku #. Jest to dyrektywa dla kompilatora.
Pragma dyrektywa dla kompilatora #pragma implementation Zawiera ona informacje dla kompilatora, która steruje jego pracą. #define ROZMIAR TAB 100 #pragma interface #pragma implementation int Tablica[ROZMIAR TAB]; for (int i = 0; i < ROZMIAR TAB-1; ++i) Tablica[i] = Tablica[i+1];
Pragma dyrektywa dla kompilatora #pragma implementation Dlatego też preprocesor nie przetwarza dyrektywy #pragma i pozostawia ją w tekście programu. #pragma interface #pragma implementation int Tablica[100]; for (int i = 0; i < 100-1; ++i) Tablica[i] = Tablica[i+1];
Pragma dyrektywa dla kompilatora #pragma implementation Treść i znacznie dyrektywy zależy od konkretnego kompilatora. Dlatego też jej wystąpienie wiąże się z kompilacją warunkową. #define ROZMIAR TAB 100 #ifdef GNUG #pragma interface #pragma implementation #endif int Tablica[ROZMIAR TAB]; for (int i = 0; i < ROZMIAR TAB-1; ++i) Tablica[i] = Tablica[i+1];
Pragma dyrektywa dla kompilatora #pragma implementation Znak # nie musi bezpośrednio poprzedzać nazwę dyrektywy. Dotyczy to zarówno dyrektywy kompilatora jak też preprocesora. #define ROZMIAR TAB 100 #ifdef GNUG # pragma interface # pragma implementation #endif int Tablica[ROZMIAR TAB]; for (int i = 0; i < ROZMIAR TAB-1; ++i) Tablica[i] = Tablica[i+1];
Pragma dyrektywa dla kompilatora #pragma implementation Nie muszą też rozpoczynać się od pierwszej kolumny. #define ROZMIAR TAB 100 #ifdef GNUG # pragma interface # pragma implementation #endif int Tablica[ROZMIAR TAB]; for (int i = 0; i < ROZMIAR TAB-1; ++i) Tablica[i] = Tablica[i+1];
Pragma dyrektywa dla kompilatora #pragma implementation Muszą być jednak pierwszym elementem w linii. int Zm; #define ROZMIAR TAB 100 #ifdef GNUG # pragma interface # pragma implementation #endif int Tablica[ROZMIAR TAB]; for (int i = 0; i < ROZMIAR TAB-1; ++i) Tablica[i] = Tablica[i+1];
Dyrektywa #include Organizacja kursu #include <iostream> Plik, który ma być dołączony, szukany jest w katalogach systemowych kompilatora.
Dyrektywa #include Organizacja kursu #include mojplik.h Plik najpierw szukany jest w katalogu bieżącym, a w razie niepowodzenia w drugiej kolejności przeszukiwane są katalogi systemowe kompilatora.
Dyrektywa #include #include <iostream> #include mojplik.h Organizacja kursu Dla obu dyrektyw listę przeszukiwanych katalogów można rozszerzyć stosując opcje -I. Katalogi występujące po -I przeszukiwane są przed katalogami systemowymi. Konsola jkowalsk@panamint> gcc -Iinc -Iinc/kernel mojplik.c
Dyrektywa #include #include <iostream> #include ext/mojplik.h Organizacja kursu W jakim katalogu będzie szukany teraz plik mojplik.h? Konsola jkowalsk@panamint> gcc -Iinc -Iinc/kernel mojplik.c
Dyrektywa #include #include <iostream> #include mojplik.h Organizacja kursu Opcja -iquote rozszerza listę przeszukiwanych kartotek tylko dla dyrektywy #include.... Konsola jkowalsk@panamint> gcc -iquote inc -iquote inc/kernel mojplik.c
LZespolona.hh Organizacja kursu struct LZespolona double re, im; ; WektorZ.hh struct WektorZ LZespolona x, y; ; prog.cpp #include LZespolona.hh #include WektorZ.hh WektorZ Wz;
Organizacja kursu struct LZespolona double re, im; ; struct WektorZ LZespolona x, y; ; WektorZ Wz;
LZespolona.hh Organizacja kursu struct LZespolona double re, im; ; WektorZ.hh struct WektorZ LZespolona x, y; ; prog.cpp #include LZespolona.hh #include WektorZ.hh WektorZ Wz;
LZespolona.hh Organizacja kursu struct LZespolona double re, im; ; WektorZ.hh struct WektorZ LZespolona x, y; ; prog.cpp #include WektorZ.hh #include LZespolona.hh WektorZ Wz;
Organizacja kursu struct WektorZ LZespolona x, y; ; struct LZespolona double re, im; ; WektorZ Wz;
Dołączanie w pliku nagłówkowym LZespolona.hh struct LZespolona double re, im; ; WektorZ.hh #include lzespolona.hh struct WektorZ LZespolona x, y; ; prog.cpp #include WektorZ.hh WektorZ Wz;
Efekt dołączenia w pliku głównym i nagłówkowym struct LZespolona double re, im; ; struct WektorZ LZespolona x, y; ; WektorZ Wz;
Wielokrotne wystąpienie pliku nagłówkowego LZespolona.hh struct LZespolona double re, im; ; WektorZ.hh #include lzespolona.hh struct WektorZ LZespolona x, y; ; prog.cpp #include WektorZ.hh WektorZ Wz;
Wielokrotne wystąpienie pliku nagłówkowego LZespolona.hh struct LZespolona double re, im; ; WektorZ.hh #include lzespolona.hh struct WektorZ LZespolona x, y; ; prog.cpp #include WektorZ.hh #include LZespolona.hh WektorZ Wz;
Efekt dołączenia wszystkich plików nagłówkowych struct LZespolona double re, im; ; struct WektorZ LZespolona x, y; ; struct LZespolona double re, im; ; WektorZ Wz;
Zapobieganie wielokrotnemu dołączaniu tego samego pliku LZespolona.hh #ifndef LZESPOLONA HH #define LZESPOLONA HH struct LZespolona double re, im; ; #endif WektorZ.hh #ifndef WEKTORZ HH #define WEKTORZ HH #include lzespolona.hh struct WektorZ LZespolona x, y; ; #endif prog.cpp #include WektorZ.hh #include LZespolona.hh WektorZ Wz;
Organizacja kursu struct LZespolona double re, im; ; struct WektorZ LZespolona x, y; ; WektorZ Wz;
Jaki wpływ ma zamiana kolejności dołączania plików? LZespolona.hh #ifndef LZESPOLONA HH #define LZESPOLONA HH struct LZespolona double re, im; ; #endif WektorZ.hh #ifndef WEKTORZ HH #define WEKTORZ HH #include lzespolona.hh struct WektorZ LZespolona x, y; ; #endif prog.cpp #include WektorZ.hh #include LZespolona.hh WektorZ Wz;
Jaki wpływ ma zamiana kolejności dołączania plików? LZespolona.hh #ifndef LZESPOLONA HH #define LZESPOLONA HH struct LZespolona double re, im; ; #endif WektorZ.hh #ifndef WEKTORZ HH #define WEKTORZ HH #include lzespolona.hh struct WektorZ LZespolona x, y; ; #endif prog.cpp #include LZespolona.hh #include WektorZ.hh WektorZ Wz;
Wielokrotne definiowanie symbolu #define word unsigned short int
Wielokrotne definiowanie symbolu #define word unsigned short int #define word short int
Wielokrotne definiowanie symbolu #define word unsigned short int #define word unsigned short int
Wielokrotne definiowanie symbolu #define word unsigned short int #undef word #define word unsigned short int
Wielokrotne definiowanie symbolu #define word unsigned short int #ifdef word # define word unsigned short int #endif
Rozwijanie definicji makra #define MAX( aa, bb ) aa > bb? aa : bb double Zm = 9; Zm = MAX( Zm, 20);
Po rozwinięciu makra Organizacja kursu double Zm = 9; Zm = Zm > 20? Zm : 20; Zawartość zmiennej na końcu programu Zm: 20
Wypływ priorytetu operatorów na wynik operacji #define MAX( aa, bb ) aa > bb? aa : bb double Zm = 9; Zm = 35 + MAX( Zm, 20);
Wypływ priorytetu operatorów na wynik operacji double Zm = 9; Zm = 35 + Zm > 20? Zm : 20;
Wypływ priorytetu operatorów na wynik operacji double Zm = 9; Zm = 35 + Zm > 20? Zm : 20; Zawartość zmiennej na końcu programu Zm: 9
Wypływ priorytetu operatorów na wynik operacji #define MAX( aa, bb ) aa > bb? aa : bb double Zm = 9; Zm = 35 + MAX( Zm, 20);
Wypływ priorytetu operatorów na wynik operacji #define MAX( aa, bb ) (aa > bb? aa : bb) double Zm = 9; Zm = 35 + MAX( Zm, 20);
Wypływ priorytetu operatorów na wynik operacji #define MAX( aa, bb ) (aa > bb? aa : bb) double Zm = 9, Z tmp; Zm = 35 + MAX( Zm, Z tmp=20);
Wypływ priorytetu operatorów na wynik operacji #define MAX( aa, bb ) (aa > bb? aa : bb) double Zm = 9, Z tmp; Zm = 35 + MAX( Zm, Z tmp=20); Komunikat kompilatora prog.cpp: In function : prog.cpp:12: error: lvalue required as left operand of assignment
Wypływ priorytetu operatorów na wynik operacji #define MAX( aa, bb ) (aa > bb? aa : bb) double Zm = 9; Zm = 35 + (Zm > Z tmp = 20? Zm : Z tmp = 20); Komunikat kompilatora prog.cpp: In function : prog.cpp:12: error: lvalue required as left operand of assignment
Wypływ priorytetu operatorów na wynik operacji #define MAX( aa, bb ) ((aa) > (bb)? (aa) : (bb)) double Zm = 9; Zm = 35 + MAX( Zm, Z tmp=20);
Skutki wywołania funkcji w makrze #define MAX( aa, bb ) ((aa) > (bb)? (aa) : (bb)) double Compute(double r, double angle) return log(pow(r,4.32)*sin(4.5*angle/3.14+2.3)); double Zm = 9; Zm = MAX( Compute(2.5*Zm, 0.25), 20 );
Skutki wywołania funkcji w makrze #define MAX( aa, bb ) ((aa) > (bb)? (aa) : (bb)) double Compute(double r, double angle) return log(pow(r,4.32)*sin(4.5*angle/3.14+2.3)); double Zm = 9; Zm = ((Compute(2.5*Zm, 0.25)) > (20)? (Compute(2.5*Zm, 0.25)) : (20));
Rozwijanie makr w makrze #define MAX( aa, bb ) ((aa) > (bb)? (aa) : (bb)) #define PI 3.14 double Zm = 9; Zm = MAX( PI/15, pow(log(pi),8) );
Rozwijanie makr w makrze double Zm = 9; Zm = ( (3.14/15) > (pow(log(3.14),8))? (3.14/15) : (pow(log(3.14),8) );
Rozwijanie makr w makrze #define MAX( aa, bb ) ((aa) > (bb)? (aa) : (bb)) #define PI 3.14 double Zm = 9; Zm = MAX( PI/15, pow(log(pi),8) );
Rozwijanie makr w makrze #define MAX( aa, bb ) ((aa) > (bb)? (aa) : (bb)) #define FUN( arg1, arg2 ) pow(log((arg1)),(arg2)) #define PI 3.14 double Zm = 9; Zm = MAX( PI/15, FUN(PI, 8) );
Rozwijanie makr w makrze double Zm = 9; Zm = ( (3.14/15) > (pow(log((3.14)),(8)))? (3.14/15) : (pow(log((3.14)),(8)) );
Jaka jest kolejność rozwijania makr #define FUN( arg1, arg2 ) pow(log((arg1)),(arg2)) double ZmA = 9, ZmB; ZmA = pow(log(zma *= 2), (ZmB = ZmA+10, ZmA *= 3));
Jaka jest kolejność rozwijania makr #define FUN( arg1, arg2 ) pow(log((arg1)),(arg2)) double ZmA = 9, ZmB; Zm = FUN(ZmA *= 2, ZmB = ZmA+10, ZmA *= 3 );
Jaka jest kolejność rozwijania makr #define FUN( arg1, arg2 ) pow(log((arg1)),(arg2)) double ZmA = 9, ZmB; Zm = FUN(ZmA *= 2, (ZmB = ZmA+10, ZmA *= 3) );
Jaka jest kolejność rozwijania makr #define FUN( arg1, arg2 ) pow(log((arg1)),(arg2)) #define ARG ZmB = ZmA+10, ZmA *= 3 double ZmA = 9, ZmB; Zm = FUN(ZmA *= 2, ARG );
Makra wywoływane przez makra #define MAX( aa, bb ) ((aa) > (bb)? (aa) : (bb)) double Zm; Zm = MAX( Zm, MAX( Zm, 5 ) );
Makra wywoływane przez makra double Zm; Zm = ((Zm) > ((Zm) > (5)? (Zm) : (5))? (Zm) : ((Zm) > (5)? (Zm) : (5)));
Makra wywoływane przez makra #define MAX( aa, bb ) ((aa) > (bb)? (aa) : (bb)) #define ARG MAX( Zm, 5 ) double Zm; Zm = MAX( Zm, ARG );
Makra wywoływane przez makra double Zm; Zm = ((Zm) > ((Zm) > (5)? (Zm) : (5))? (Zm) : ((Zm) > (5)? (Zm) : (5)));
Czy są możliwe rekurencyjne wywołania makr? #define SILNIA(x) (((x) > 1)? (x)*silnia((x)-1) : 1) double Zm; Zm = SILNIA(20);
Czy są możliwe rekurencyjne wywołania makr? double Zm; Zm = ((20) > 1? (20)*SILNIA((20)-1) : 1);
Tworzenie napisu Organizacja kursu #define STR(x) #x const char *wnapis = STR(Ten tekst bedzie napisem);
Tworzenie napisu Organizacja kursu const char *wnapis = Ten tekst bedzie napisem ;
A jaki teraz będzie rezultat rozwinięcia makra? #define STR(x) #x #define TEKST Ten tekst bedzie napisem const char *wnapis = STR(TEKST);
Końcowy rezultat Organizacja kursu const char *wnapis = TEKST ;
Przykład użycia Organizacja kursu #define STR(x) #x #define DEF FUN( Nazwa, Ciag Instr ) \ void Nazwa( LZespolona& Z ) \ Ciag Instr; \ cout << Funkcja: STR(Nazwa) << endl; \ DEF FUN(Zamien, double x; x = Z.re; Z.re = Z.im; Z.im = x) DEF FUN(Inwersja, Z.re = -Z.re; Z.im = -Z.im) DEF FUN(Potega2, Z *= Z)
Przykład użycia Organizacja kursu void Zamien(LZespolona& Z) double x; x = Z.re; Z.re = Z.im; Z.im = x; cout << Funkcja: Zamien <<endl; void Inwersja(LZespolona& Z) Z.re = -Z.re; Z.im = -Z.im; cout << Funkcja: Inwersja <<endl; void Potega2(LZespolona& Z) Z *= Z; cout << Funkcja: Potega2 <<endl;
Sformułowanie problemu void FunZesp Zamien(LZespolona& Z) double x; x = Z.re; Z.re = Z.im; Z.im = x; cout << Funkcja: Zamien <<endl; void FunZesp Inwersja(LZespolona& Z) Z.re = -Z.re; Z.im = -Z.im; cout << Funkcja: Inwersja <<endl; void FunZesp Potega2(LZespolona& Z) Z *= Z; cout << Funkcja: Potega2 <<endl;
Sformułowanie problemu #define DEF FUN( Nazwa, Ciag Instr ) \ void FunZesp Nazwa( LZespolona& Z ) \ Ciag Instr; \ cout << Funkcja: STR(Nazwa) << endl; \ DEF FUN(Zamien, double x; x = Z.re; Z.re = Z.im; Z.im = x) DEF FUN(Inwersja, Z.re = -Z.re; Z.im = -Z.im) DEF FUN(Potega2, Z *= Z)
Sformułowanie problemu void FunZesp Zamien(LZespolona& Z) double x; x = Z.re; Z.re = Z.im; Z.im = x; cout << Funkcja: Zamien <<endl; void FunZesp Inwersja(LZespolona& Z) Z.re = -Z.re; Z.im = -Z.im; cout << Funkcja: Inwersja <<endl; void FunZesp <<endl; Potega2(LZespolona& Z) Z *= Z; cout << Funkcja: Potega2
Sformułowanie problemu #define DEF FUN( Nazwa, Ciag Instr ) \ void FunZesp Nazwa( LZespolona& Z ) \ Ciag Instr; \ cout << Funkcja: STR(Nazwa) << endl; \ DEF FUN(Zamien, double x; x = Z.re; Z.re = Z.im; Z.im = x) DEF FUN(Inwersja, Z.re = -Z.re; Z.im = -Z.im) DEF FUN(Potega2, Z *= Z)
Sformułowanie problemu void FunZesp Nazwa(LZespolona& Z) double x; x = Z.re; Z.re = Z.im; Z.im = x; cout << Funkcja: Zamien <<endl; void FunZesp Nazwa(LZespolona& Z) Z.re = -Z.re; Z.im = -Z.im; cout << Funkcja: Inwersja <<endl; void FunZesp Nazwa(LZespolona& Z) Z *= Z; cout << Funkcja: Potega2 <<endl;
Łączenie napisów Organizacja kursu #define DOLACZ NAPIS( x ) Prefix ##x
Łączenie napisów Organizacja kursu #define DOLACZ NAPIS( x ) DOLACZ NAPIS( RdzenNazwy ) Prefix ##x
Łączenie napisów Organizacja kursu #define DOLACZ NAPIS( x ) DOLACZ NAPIS( RdzenNazwy ) Prefix RdzenNazwy Prefix ##x
Łączenie napisów Organizacja kursu #define DOLACZ NAPIS( x ) DOLACZ NAPIS( RdzenNazwy ) PrefixRdzenNazwy Prefix##x
Przykład użycia Organizacja kursu #define STR(x) #x #define DEF FUN( Nazwa, Ciag Instr ) \ void FunZesp ##Nazwa( LZespolona& Z ) \ Ciag Instr; \ cout << Funkcja: STR(Nazwa) << endl; \ DEF FUN(Zamien, double x; x = Z.re; Z.re = Z.im; Z.im = x) DEF FUN(Inwersja, Z.re = -Z.re; Z.im = -Z.im) DEF FUN(Potega2, Z *= Z)
Przykład użycia Organizacja kursu void FunZesp Zamien(LZespolona& Z) double x; x = Z.re; Z.re = Z.im; Z.im = x; cout << Funkcja: Zamien <<endl; void FunZesp Inwersja(LZespolona& Z) Z.re = -Z.re; Z.im = -Z.im; cout << Funkcja: Inwersja <<endl; void FunZesp Potega2(LZespolona& Z) Z *= Z; cout << Funkcja: Potega2 <<endl;
Konstruowanie rozwinięcia makr w makrach #define STR( x ) #x #define MAX int #define MAX double std::numeric limits<int>::max() std::numeric limits<double>::max()
Konstruowanie rozwinięcia makr w makrach #define STR( x ) #x #define MAX int #define MAX double std::numeric limits<int>::max() std::numeric limits<double>::max() #define DISPLAY MAX( Typ ) cout << Maks. STR(Typ) : << MAX ##Typ << endl;
Konstruowanie rozwinięcia makr w makrach #define STR( x ) #x #define MAX int #define MAX double std::numeric limits<int>::max() std::numeric limits<double>::max() #define DISPLAY MAX( Typ ) cout << Maks. STR(Typ) : << MAX ##Typ << endl; void main( ) DISPLAY MAX(int) DISPLAY MAX(double)
Konstruowanie rozwinięcia makr w makrach void main( ) cout << Maks. int : << std::numeric limits<int>::max() << endl; cout << Maks. double : << std::numeric limits<double>::max() << endl;
Rozwinięcia makr parametrycznych w makrach #define STR( x ) #x #define LIMIT int(fun) #define LIMIT double(fun) std::numeric limits<int>::fun() std::numeric limits<double>::fun() #define DISPLAY LIMIT( T, L ) cout << Maks. STR(T) : << LIMIT ##T(L) << endl; void main( ) DISPLAY LIMIT(int, max) DISPLAY LIMIT(double, min)
Rozwinięcia makr parametrycznych w makrach void main( ) cout << Maks. int : << std::numeric limits<int>::max() << endl; cout << Maks. double : << std::numeric limits<double>::min() << endl;
Przykładowy implementacja głównej pętli parsera bool CommandsParser::ReadCmdsList( istream &IStrm, CommandsList &CmdLst) string Keyword; while (IStrm >> Keyword) if (Keyword == Move ) if (!ReadCmd Move(IStrm,CmdLst)) return false; continue ; if (Keyword == Turn ) if (!ReadCmd Turn(IStrm,CmdLst)) return false; continue ; if (Keyword == Rotate ) if (!ReadCmd Rotate(IStrm,CmdLst)) return false; continue ; return true;
Definicja pomocniczego makra #define STR(x) #x #define IF CMD THEN READ( CmdName ) \ if (Keyword == STR(CmdName)) \ if (!ReadCmd ##CmdName(IStrm,CmdLst)) return false; \ continue ; \ bool CommandsParser::ReadCmdsList( istream &IStrm, CommandsList &CmdLst) string Keyword; while (IStrm >> Keyword) if (Keyword == Move ) if (!ReadCmd Move(IStrm,CmdLst)) return false; continue ;... return true;
Przykład użycia Organizacja kursu #define STR(x) #x #define IF CMD THEN READ( CmdName ) \ if (Keyword == STR(CmdName)) \ if (!ReadCmd ##CmdName(IStrm,CmdLst)) return false; \ continue ; \ bool CommandsParser::ReadCmdsList( istream &IStrm, CommandsList &CmdLst) string Keyword; while (IStrm >> Keyword) IF CMD THEN READ( Move ) IF CMD THEN READ( Turn ) IF CMD THEN READ( Rotate ) return true;
Przykład użycia Organizacja kursu #define STR(x) #x #define IF CMD THEN READ( CmdName ) \ if (Keyword == STR(CmdName)) \ if (!ReadCmd ##CmdName(IStrm,CmdLst)) return false; \ continue ; \ bool CommandsParser::ReadCmdsList( istream &IStrm, CommandsList &CmdLst) string Keyword; while (IStrm >> Keyword) IF CMD THEN READ( Move ) IF CMD THEN READ( Turn ) IF CMD THEN READ( Rotate ) return false; return true;
Kontrola błędów Organizacja kursu double Operacja Podzialu( double Dzielna, double Dzielnik ) if (Dzielnik == 0) cerr << Blad operacji dzielenia w funkcji Operacja Podzialu << endl; abort(); return Dzielna/Dzielnik;
Kontrola błędów Organizacja kursu double Operacja Podzialu( double Dzielna, double Dzielnik ) if (Dzielnik == 0) cerr << Blad operacji dzielenia w funkcji Operacja Podzialu << endl; cerr << Modul: FILE << endl; cerr << Linia: << LINE abort(); return Dzielna/Dzielnik; << endl;
Kontrola błędów Organizacja kursu double Operacja Podzialu( double Dzielna, double Dzielnik ) assert(dzielnik == 0); return Dzielna/Dzielnik;
Kontrola błędów Organizacja kursu #include <cassert> double Operacja Podzialu( double Dzielna, double Dzielnik ) assert(dzielnik == 0); return Dzielna/Dzielnik;
Kontrola błędów Organizacja kursu #define NDEBUG #include <cassert> double Operacja Podzialu( double Dzielna, double Dzielnik ) assert(dzielnik == 0); return Dzielna/Dzielnik;
Postać makra assert (język C) #include <assert.h> double Operacja Podzialu( double Dzielna, double Dzielnik ) assert(dzielnik == 0); return Dzielna/Dzielnik;
Postać makra assert (język C) double Operacja Podzialu( double Dzielna, double Dzielnik ) ((Dzielnik == 0)? (void) (0) : assert fail("dzielnik == 0", "kontrola.c", 6, PRETTY FUNCTION )); return Dzielna/Dzielnik;
Postać makra assert (język C) #define NDEBUG #include <assert.h> double Operacja Podzialu( double Dzielna, double Dzielnik ) assert(dzielnik == 0); return Dzielna/Dzielnik;
Postać makra assert (język C) double Operacja Podzialu( double Dzielna, double Dzielnik ) (void) (0); return Dzielna/Dzielnik;
Postać makra assert (język C++) #include <cassert> double Operacja Podzialu( double Dzielna, double Dzielnik ) assert(dzielnik == 0); return Dzielna/Dzielnik;
Postać makra assert (język C++) double Operacja Podzialu( double Dzielna, double Dzielnik ) ((Dzielnik == 0)? static cast<void>(0) : assert fail("dzielnik == 0", "kontrola.c", 6, PRETTY FUNCTION )); return Dzielna/Dzielnik;
Postać makra assert (język C++) #define NDEBUG #include <cassert> double Operacja Podzialu( double Dzielna, double Dzielnik ) assert(dzielnik == 0); return Dzielna/Dzielnik;
Postać makra assert (język C++) double Operacja Podzialu( double Dzielna, double Dzielnik ) (static cast<void>(0)); return Dzielna/Dzielnik;
Czytanie pliku generowanego przez preprocesor #define LINE SIZE 500 bool Exec( const char NazwaPliku, istringstream &IStrm4Cmds ) string Cmd4Preproc = cpp -P ; char Line[LINE SIZE]; ostringstream OTmpStrm; Cmd4Preproc += NazwaPliku; FILE pproc = popen(cmd4preproc.c str(), r ); if (!pproc) return NULL; while (fgets(line,line SIZE,pProc)) OTmpStrm << Line; IStrm4Cmds.str(OTmpStrm.str()); return pclose(pproc) == 0;
I to już koniec. języka C