1 Podstawy programowaniaAdam Naumowicz
2 Sprawy formalne 30 godz. wykładu + 30 godz. ćwiczeń (15 godz. w laboratorium) zaliczenie laboratorium i egzamin obecność na wykładach nieobowiązkowa!
3 Plan wykładu Podstawowe informacje o języku C (podstawowe typy danych, deklaracje zmiennych i stałych) Operacje wejścia-wyjścia Operatory i wyrażenia (priorytety, konwersja typów) Instrukcja warunkowa i instrukcja wyboru Instrukcje iteracyjne i sterujące wykonaniem programu Typy wskaźnikowe i tablicowe Funkcje (metody przekazywania argumentów) Preprocesor i budowa programu (generowanie kodu wynikowego) Typy złożone - struktury i unie Operacje plikowe Funkcje rekurencyjne Standardowe biblioteki (matematyczne, łańcuchy znakowe) Dynamiczne struktury danych (lista, kolejka, stos) Struktury drzewiaste (sterta, drzewo) Grafika tekstowa i punktowa
4 Programowanie Język C kompilator GCCB. W. Kernighan, Dennis M. Ritchie – „Język ANSI C” kompilator GCC system operacyjny Microsoft Windows XP środowisko programistyczne DEV-C++
5 Odrobina historii języka C1969 – Martin Richards – język BCPL 1970 – Ken Thompson – język B adaptacja dla UNIX na maszynie DEC PDP-7 1972 – Dennis Ritchie – język C DEC PDP-11 – standaryzacja ANSI American National Standards Institute 1990 – standard ISO International Organization for Standardization
6 Podstawowe cechy języka Cjęzyk ogólnego stosowania względnie „niski poziom” język imperatywny (proceduralny) podstawowe konstrukcje sterujące programowania strukturalnego: grupowanie instrukcji, podejmowanie decyzji, wybór przypadku, powtarzanie ze sprawdzaniem warunku zatrzymania na początku i końcu pętli, przerwanie pętli
7 Podstawowe cechy języka C – c.d.język typowy typy podstawowe: znaki, liczby całkowite i zmiennopozycyjne w różnych zakresach typy pochodne: wskaźniki, tablice, struktury, unie wyrażenia buduje się z operatorów i ich argumentów wyrażenie może pełnić rolę instrukcji włącznie z przypisaniem i wywołaniem funkcji input/output jest częścią biblioteki a nie języka przenośny - niezależny od architektury system UNIX jest rozwijany w języku C
8 Elementarz „Nie można się nauczyć programowania bez samodzielnego pisania programów!” proces kompilacji edycja kodu źródłowego (*.c) asemblacja (*.o) konsolidacja (plik uruchamialny, np. *.exe) pierwszy program Wypisanie na konsoli napisu „Hello World!”
9 Podstawowe typy danychint (przynajmniej 2 bajty) float 1.E-36 … 1.E+36 (4 bajty, precyzja do 7 miejsc) double 1.E-303 … 1.E+303 (8 bajtów, precyzja do 13 miejsc) char 0 … 255 (1 bajt)
10 Deklaracje zmiennych i stałychtyp nazwa-zmiennej; int a; int x,y,z; int count=7; const typ nazwa-stałej = wartość; const int NUM=123; const float PI=3.14;
11 Dodatkowe deklaratory typushort short int = short long long int = long signed unsigned
12 Stałe znakowe i liczbowe"string" ‘A’, ‘a’, … ‘A’ = 65 ‘\ooo’ ‘\xhh’ \n, \t, \r, … 1234 L ( l) 123U (123u) 31 = 037 = 0x1f = 0X1F
13 Formatowany input/outputprintf(…); int res=7; printf("Result: %d",res); int a=2; int res; res=a+7; printf("In:%d, Result: %d",a,res); scanf(…); int dat; scanf("%d",&dat); char str[20]; scanf("%s",str);
14 Formatowany input/output – c.d.Usual variable type Display %c char single character %d (%i) int signed integer %e (%E) float or double exponential format %f float or double signed decimal %g (%G) float or double use %f or %e as required %o int unsigned octal value %p pointer address stored in pointer %s array of char sequence of characters %u int unsigned decimal %x (%X) int unsigned hex value
15 Formatowany input/output – c.d.flag width.precision flag meaning left justify always display sign space display space if there is no sign pad with leading zeros # use alternate form of specifier
16 Formatowany input/output – c.d.%#o adds a leading 0 to the octal value %#x adds a leading 0x to the hex value %#f or %#e ensures decimal point is printed %#g displays trailing zeros
17 Operacje i operatory Arytmetyczne: Inkrementacja: Przypisanie:+, -, *, /, % (modulo) Inkrementacja: ++, -- (++x, x++) Przypisanie: =, +=, -=, *=, /=, … Relacyjne: ==, !=, <, >, <=, >= Logiczne &&, ||, ! Bitowe: & (AND), | (OR), ^ (XOR), <<, >>, ~ Koercja/rzutowanie (ang. cast) (typ) wyrażenie (float)2/5
18 Wyrażenia warunkowe wyr1 ? wyr2 : wyr3 Np. z=(a>b) ? a : b;/*z=max(a,b)*/
19 Instrukcja warunkowa if (wyrażenie) instrukcja{…} – instrukcja złożona if (wyrażenie) instrukcja1 else instrukcja2 if (wyrażenie1) instrukcja1 else if (wyrażenie2) instrukcja2 … else if (wyrażenieX) instrukcjaX else instrukcja
20 Instrukcja wyboru switch (wyrażenie) { case wyrażenie-stałe1: instrukcje1 case wyrażenie-stałe2: instrukcje2 default: instrukcje } break
21 Instrukcje skoku bezwarunkowe przekazanie sterowania do innego miejscareturn wyrażenieopc; break; continue; goto etykieta; etykieta: - poprawny identyfikator skok w obrębie tej samej funkcji nie należy nadużywać! uzasadnione w przypadku wyskoku z kilku pętli jednocześnie
22 Instrukcje iteracyjne (pętli)while (wyrażenie) instrukcja do instrukcja while (wyrażenie); for (wyr1opc; wyr2opc; wyr3opc) instrukcja można opuścić wyrażenia for (;;) instrukcja for (;;) ; ominięcie wyr2 jest równoważne wystąpieniu stałej różnej od zera
23 Instrukcje pętli - przerywaniebreak; przerwanie "najciaśniej otaczającej" pętli continue; przekazanie sterowania do miejsca wznowienia "najciaśniej otaczającej" pętli
24 Przerywanie pętli - c.d. while (...){ do { for(...){ } } while (...); } br: ; br: ; br: ; break; jest równoważne goto br; jeśli w ciele pętli nie występuje "ciaśniejsza" pętla
25 Przerywanie pętli - c.d. while (...){ do { for(...){ contin: ; contin: ; contin: ; } } while (...); } continue; jest równoważne goto contin; jeśli w ciele pętli nie występuje "ciaśniejsza" pętla
26 Instrukcje pętli - równoważnośćfor (wyr1; wyr2; wyr3) instrukcja wyr1; while (wyr2){ instrukcja wyr3 ; } Uwaga: pętle są równoważne gdy instrukcja nie zawiera continue;
27 Instrukcje pętli - porównaniewhile (wyrażenie) instrukcja wyrażenie sprawdzane na początku - instrukcja nie musi być wykonana ani razu np. odczyt z pliku do instrukcja while (wyrażenie); wyrażenie sprawdzane na końcu - instrukcja musi być wykonana przynajmniej raz for (wyr1; wyr2; wyr3) instrukcja zwykle wyr1 to inicjalizacja a wyr3 to inkrementacja np. ustalona liczba iteracji
28 Tablice deklaracja: typ identyfikator [rozmiar]; indeksowanie:np. int array[7]; char tab[256]; Wniosek: elementy jednolitego typu indeksowanie: x=array[6]; tab[i]='Z'; Uwaga: indeksowanie od 0 !
29 Tablice -c.d. deklaracja tablicy wielowymiarowej: typ identyfikator [rozmiar1][rozmiar1]...; np. int array[7][2]; char tab[256][10][100]; inicjowanie int arr[4] = {2,3,4,5}; int arr[] = {2,3,4,5}; float f[2][3]={ {1,2,3}, {4,5,6} }; Uwaga: najłatwiej przetwarzać pętlą for
30 Tablice i wskaźniki wskaźnik to zmienna zawierająca adres innej zmiennej postać deklaracji: typ * zmienna; np. char * c; korzyści z użycia wskaźników bardziej zwarty i efektywny kod czasami jedyny sposób implementacji pewnych algorytmów w języku C możliwość dynamicznego tworzenia zmiennych (w trakcie pracy programu) Uwaga: łatwo można napisać zupełnie niezrozumiały lub błędny kod gdy nie zachowuje sie ostrożności!
31 Tablice i wskaźniki -c.d.pamięć komputera można przedstawić jako tablicę kolejno numerowanych (adresowanych) komórek pamięci komórkami pamięci można manipulować indywidualnie lub całymi grupami bajtowi odpowiada typ char dwóm bajtom odpowiada typ short int czterem bajtom odpowiada typ long int wskaźnik jest grupą komórek, która może pomieścić adres 2 bajty (komputery 16-bitowe) 4 bajty (komputery 32-bitowe)
32 Tablice i wskaźniki -c.d.operator adresowy (&) i wskaźnikowy (*) & - referencja, * - dereferencja przykład int x=1, y=2, z[10]; int *ip; ip jest wskaźnikiem do obiektów typu int ip=&x; teraz ip wskazuje na x y=*ip; y ma teraz wartość 1 *ip=0; x ma teraz wartość 0 ip=&z[0]; teraz ip wskazuje na element z[0]
33 Tablice i wskaźniki -c.d.równoważność tablic i wskaźników przykład int a[10]; int *pa; pa=&a[0]; x=*pa; x=a[0]; pa=&a[0]; pa=a; x=a[3]; x=pa[3]; arytmetyka na adresach adresy można inkrementować (++) i dekrementować (--) pa+1 - wskazuje na następny obiekt pa+i &a[i] *(pa+i) a[i]
34 Specjalne typy wskaźnikowewskaźniki na znak (tablice znakowe) można inicjować poprzez stałe łańcuchowe char str[ ] = "blah, blah, blah"; nie można zmienić wartości str char * ptr = " blah, blah, blah"; można przypisać zmiennej ptr inne wskaźniki wskaźnik na typ void może przechowywać wskaźniki na dowolny typ void * v; char *p; int *q; ... v=p; ... v=q; ... v nie może być użyty do adresowania pośredniego (wymaga rzutowania - cast) p=(*char)v;
35 Funkcje w języku C program w C jest "zbiorem funkcji"musi zawierać przynajmniej jedna funkcję (main) funkcja to podprogram realizujący określone zadanie mogący zwracać do miejsca wywołania wartość określonego typu można stosować wielokrotnie może przyjmować parametry ukrywa szczegóły implementacji przed innymi częściami programu można pisać funkcje w różnych plikach kompilowanych oddzielnie można łączyć funkcje w biblioteki Uwaga: raczej kilka małych niż jedna duża funkcja!
36 Funkcje w C - ograniczeniafunkcji nie można "zagnieżdżać" cała funkcja musi być umieszczona w jednym pliku funkcje zawsze przekazują parametry "przez wartość" konieczne jest używanie wskaźników używana funkcja musi być uprzednio zadeklarowana
37 Funkcje w C - c.d. deklaracja: typ-wyniku nazwa (parametryopc);definicja: typ-wyniku nazwa (parametryopc); { ... instrukcje ... return wyrażenieopc; } standaryzacja w ANSI C
38 Funkcje w C - c.d. domyślny typ wyniku to intgdy funkcja nie zwraca wartości stosuje się typ void parametry mają postać: typ1 zmienna1[, typ2 zmienna2]... w deklaracji mogą występować tylko nazwy typów listę parametrów można pominąć w deklaracji - nie będą wtedy sprawdzane przez kompilator! dla funkcji bez parametrów stosuje się zapis (void) jako listę parametrów
39 Funkcje w C - c.d. zmienne globalne - zewnętrzne (extern)deklaracja poza ciałem funkcji dostępne z każdej funkcji nie należy nadużywać - komplikuje to większe programy inicjalizacja na 0 gdy brak przypisania extern int x; extern jest domyślne poza funkcją zmienne statyczne (static) przechowują wartość we wszystkich wywołaniach tej samej funkcji static int x;
40 Funkcje rekurencyjne w CFunkcja może wywoływać samą siebie bezpośrednio pośrednio (również rekurencja wzajemna!) konieczny jest mechanizm stosowy każde wznowienie funkcji otrzymuje na stosie swój komplet wszystkich zmiennych automatycznych (niezależny od poprzedniego) zalety rekurencji bardziej zwarta postać bardzo łatwo implementować struktury danych zdefiniowane w sposób rekurencyjny, np. drzewa wady rekurencji zwykle dłuższy czas działania zwykle większe zużycie pamięci
41 Rekurencja - przykładypotęga xn=x * x *...* x (n razy) x0=1 , xn+1=x * xn silnia n!=1*2*...*n 0!=1, n!=(n-1)!*n liczby Fibonacciego realizacja iteracyjna realizacja rekurencyjna realizacja poprzez formułę Bineta
42 Rekurencja - przykłady c.d.klasyczny problem "Wieże Hanoi" szybkie sortowanie (QuickSort)
43 Struktury struktura w C to obiekt złożony z jednej lub kilku zmiennych, być może różnych typów, zgrupowanych "dla wygody" pod jedną nazwą ułatwiają zorganizowanie skomplikowanych danych umożliwiają traktowanie związanych ze sobą danych jako jeden obiekt przykład - pozycja listy płac pracownik ma imię, nazwisko, adres, wynagrodzenie, itp. adres to miejscowość, ulica, numer domu, itp. - elementem struktury może być inna struktura
44 Struktury - c.d. standard ANSI C daje możliwośćprzypisywania struktur przypisywania wartości początkowych przekazywania jako parametrów do funkcji zwracania jako wartość funkcji Uwaga: przekazywanie do funkcji przez wartość może być kosztowne - czasami lepiej użyć wskaźnika
45 Struktury - c.d. definicja odwołaniastruct nazwaopc { typ1 składowa1; typ2 składowa2; ... } zmienneopc; nazwa jest etykietą - może być wykorzystana przy późniejszych deklaracjach bez zmiennych mamy tylko opis kształtu struktury - nie jest rezerwowana żadna pamięć odwołania nazwa-struktury . składowa wskaźnik-do-struktury -> składowa (np. p->s zamiast (*p).s) inicjalizacja jak dla tablicy (poprzez stałe)
46 Struktury - przykłady struct point { int x; int y;};struct point pt; struct point maxpoint={640,480}; struct point { int x; int y;} p,q,r; struct rect { struct point pt1; struct point pt2; }; struct rect r; r.pt1.y=100;
47 Struktury - przykłady - c.d.struct rect r, *rp = &r; równoważne wyrażenia: r.pt1.x rp->pt1.x (r.pt1).x (rp->pt1).x Uwaga: operatory strukturowe (.), (->), podobnie jak nawiasy otaczające parametry funkcji (()) i indeksowanie tablic ([ ]) znajdują się na szczycie hierarchii priorytetów - wiążą najmocniej
48 Deklaracja typedef mechanizm typedef umożliwia tworzenie nowych nazw dla typów danych, np. typedef int Length; Length len, maxlen; typedef char *String; typ deklarowany w typedef pojawia się składniowo w miejscu zmiennej konstruowanie struktur "rekurencyjnie" - np. drzew typedef struct tnode *Treeptr; typedef struct tnode { char *word; int count; Treeptr left; Treeptr right; } Treenode;
49 Unie unia w C to zmienna, która może zawierać obiekty różnych typów i rozmiarów przykład definicji union u_tag { int ival; floaf fval; char *sval; } u; odwołania nazwa-unii . składowa wskaźnik-do-unii -> składowa
50 Unie - c.d. kompilator "troszczy" się o zgodność położenia i pamięciunia jest wystarczająco obszerna żeby pomieścić wartość największego z zadeklarowanych w niej typów składnia zbliżona do struktury unia de facto jest strukturą o składowych nie przesuniętych względem jej początku inicjalizacja tylko wartością pierwszego typu programista musi się troszczyć o to, aby pobierane dane były zgodne z typem ostatnio zapisanym
51 Unie - przykład unii w strukturzestruct{ char *name; int flags; int utype; union { int ival; float fval; char *sval; } u; } symtab[NSYM]; odwołanie do składowej ival symtab[i].u.ival odwołanie do pierwszego znaku tekstu w sval *symtab[i].u.sval symtab[i].u.sval[0]
52 Pola bitowe mogą reprezentować znaczniki jednobitoweumożliwiają upakowanie wielu znaczników w jedno słowo maszyny (zależne od implementacji) oszczędność narzucone fomaty danych, np. łącza z urządzeniami zewnętrznymi mogą wymagać dostępu do kawałków słów
53 Pola bitowe - c.d. Przykładmaski odpowiadające właściwym pozycjom bitów mogą być zdefiniowane jako stałe #define KEYWORD 01 #define EXTERNAL 02 #define STATIC 04 lub poprzez typ wyliczeniowy enum {KEYWORD=01, EXTERNAL=02,STATIC=04}; (liczby w maskach muszą być potęgami dwójki)
54 Pola bitowe - c.d. flags |= EXTERNAL | STATIC;ustawia bity EXTERNAL i STATIC w zmiennej flags flags &= ~(EXTERNAL | STATIC); kasuje powyższe bity if (flags & (EXTERNAL | STATIC)==0)... warunek jest prawdziwy gdy oba bity są skasowane
55 Pola bitowe - c.d. definicja poprzez pola bitowe:struct { unsigned int is_keyword : 1; unsigned int is_extern : 1; unsigned int is_static : 1; } flags; flags.is_extern=flags.is_static=1; flags.is_extern=flags.is_static=0; if (flags.is_extern==0 && flags.is_static==0) ...
56 Pola bitowe - c.d. podobna definicja poprzez pola bitowe:struct { unsigned int is_keyword : 1; unsigned int is_extern : 1; unsigned int is_static : 1; } flags; unsigned int gwarantuje wartość bez znaku nazwaopc : rozmiar brak nazwy można wykorzystać do "załatania dziury" rozmiar 0 wymusza przesunięcie kolejnych pól do następnego słowa maszyny wypełniają pola od lewej do prawej lub odwrotnie Uwaga: pola nie mają adresów - nie można stosować operatora &
57 Obsługa plików standardowe wejście (stdin), wyjście (stdout) i wyjście błędów (stderr) typ plikowy FILE struktura zdefiniowana w pliku nagłówkowym stdio.h w programach wykorzystuje się wskaźnik do struktury FILE jako stałą umożliwiającą otwarcie odczyt zapis
58 Obsługa plików - c.d. podstawowe operacjeFILE *fopen(char *name, char *mode) "r" - read "w" - write "a" - append "b" - dla plików binarnych "r+", "w+", "a+" - aktualizacja = czytanie i pisanie między czytaniem należy wywołać funkcję pozycjonującą int fclose(FILE *fp) wywoływana automatycznie na końcu programu int fflush(FILE *fp) FILE *reopen(char *name, char *mode, FILE *fp) zwykle używa się do zmiany plików związanych z stdin, stdout, stderr
59 Obsługa plików - c.d. int ferror(FILE *fp)wartość niezerowa gdy wystąpił jakiś błąd int feof(FILE *fp) wartość niezerowa po napotkaniu końca pliku int getc(FILE *fp) zwraca wczytany znak lub EOF gdy wystąpi błąd getchar int putc(int c, FILE *fp) zwraca wypisany znak lub EOF gdy wystąpi błąd putchar int ungetc(int c, FILE *fp) "oddaje" znak do pliku
60 Obsługa plików - c.d. pliki tekstowechar *fgets(char *line, int maxline, FILE *fp) czyta co najwyżej maxline-1 znaków wraz ze wskaźnikiem nowej linii do tablicy line i dodaje znak '\0' normalnie wartością jest wskaźnik do tablicy line po napotkaniu błędu lub końca pliku wartością jest NULL int fputs(char *line, FILE *fp) wpisuje tekst do pliku (nie musi zawierać znaku nowej linii) wartością jest 0 lub EOF w przypadku błędu gets używa stdin, kasuje znak nowej linii puts używa stdout, dodaje znak nowej linii
61 Obsługa plików - c.d. formatowane wejście/wyjścieint *fprintf(FILE *fp, char *format, ...) int *fscanf(FILE *fp, char *format, ...) int *sprintf(char *s, char *format, ...) int *sscanf(char *s, char *format, ...)
62 Obsługa plików - c.d. bezpośrednie wejście/wyjściesize_t fread(void *p, size_t s, size_t n, FILE *fp) size_t fwrite(void *p, size_t s, size_t n, FILE *fp) dostęp bezpośredni (nie sekwencyjny) int fseek(FILE *fp, long offset, int origin) SEEK_SET, SEEK_CUR, SEEK_END long ftell(FILE *fp) void rewind(FILE *fp) int fgetpos(FILE *fp, fpos_t *ptr) int fsetpos(FILE *fp, fpos_t *ptr)
63 Biblioteka standardowa:
64 Biblioteka standardowa:
65
66
67 Biblioteka standardowa:
68 Biblioteka standardowa:
69
70
71 Dynamiczny przydział pamięci
72 Lista jednokierunkowatypedef struct intelem *list; struct intelem { int val; list next; }; funkcje: read / print insert reverse join empty
73 Drzewa binarne typedef struct tnode *TreePtr; struct tnode { char *word; int count; TreePtr left; TreePtr right; }; przykład zastosowania: szybkie zliczanie wystąpień słów w tekście
74 Preprocesor kompilatora CPierwsza faza (przebieg) kompilacji przed tłumaczeniem, asemblacją i konsolidacją gcc -E ... dyrektywy preprocesora to wiersze rozpoczynające sie od znaku # gramatyka niezależna od języka C mogą wystąpić w dowolnym miejscu programu działanie kończy się wraz z końcem jednostki tłumaczenia
75 Preprocesor - c.d. Kolejne (logiczne) fazy preprocesorazastępowanie tzw. sekwencji trzyznakowych sklejanie wierszy wystąpienia \
76 Sekwencje trzyznakowe??= # ??/ \ ??' ^ ??( [ ??) ] ??! | ??< { ??> } ??- ~ zgodność ze zbiorem znaków ISO niezależność od zestawu znaków gcc -trigraphs ...
77 Definicje stałych i makr# define identyfikator ciąg-leksemów zlecenie zastępowania wszystkich wystąpień identyfikator przez ciąg-leksemów opuszczając odstępy otaczające ciąg-leksemów ponowne użycie #define jest błędne gdy definiowane ciągi się różnią # define identyfikator( lista-identyfikatorów ) ciąg-leksemów Uwaga: konieczny jest brak odstępu pomiędzy identyfikatorem a otwierającym nawiasem opuszczanie odstępów i ponowne definiowanie - j/w # undef identyfikator "zapomnienie" (być może niezdefiniowanej) definicji
78 Rozwijanie makr wystąpienie identyfikator( lista-identyfikatorów ) jest wywołaniem makra po nawiasie może wystąpić odstęp lista jest separowana przecinkami przecinki są "chronione" przez apostrofy, cudzysłów i zagnieżdzone nawiasy ilość argumentów musi odpowiadać definicji argumenty są izolowane poprzez usunięcie otaczających odstępów - makra występujące w argumentach nie są na razie rozwijane specjalna obróbka znaku # i operatora ## rozwijanie makrowywołań występujących w leksemach argumentów tuż przez zastąpieniem
79 Rozwijanie makr - c.d. jeśli w definicji makra w zastępującym ciągu znaków wystąpienie argumentu jest poprzedzone znakiem # to parametr jest zastępowany ciągiem otoczonym przez cudzysłów znaki " i \ występujące w argumencie w stałych znakowych napisach są poprzedzane przez znak \ jeśli w definicji makra wystąpi infiksowy operator ## to po zastąpieniu parametrów jest on usuwany powodując "sklejenie" sąsiadujących leksemów operator ## nie może wystąpić na początku ani końcu zastępującego ciągu leksemów
80 Rozwijanie makr - przykłady#define ABSDIFF(a,b) ((a)>(b) ? (a) - (b) : (b) - (a)) w przeciwieństwie do podobnej funkcji, argumenty i wynik mogą być dowolnego typu arytmetycznego lub nawet moga być wskaźnikami Uwaga: argumenty są tu obliczane dwa razy - różnica gdy mają "efekty uboczne" #define tempfile(dir) #dir "/%s" wywołanie tempfile(/usr/tmp) produkuje "/usr/tmp" "/%s" co jest następnie sklejane w jeden napis
81 Rozwijanie makr - przykłady - c.d.#define cat(x,y) x ## y cat(1,2) produkuje 12 cat(cat(1,2),3) produkuje niepoprawny cat ( 1, 2 )3 #define xcat(x,y) cat(x,y) makro "drugiego poziomu" xcat(xcat(1,2),3) produkuje 123
82 Preprocesor - włączanie plików# include "nazwa-pliku" lub # include
83 Preprocesor - kompilacja warunkowa# if wyrażenie-stałe # ifdef identyfikator # ifndef identyfikator # else # elif wyrażenie-stałe # endif defined (identyfikator) lub defined identyfikator Uwagi: wyrażenia są przedmiotem makrorozwinięć wyrażenia są podstawiane przez 0L lub 1L
84 Preprocesor - symbole specjalnezawsze zdefiniowane - nie można ich zmienić (podobnie jak operatora defined) _ _LINE_ _ dziesiętna stała o numerze bieżącego wiersza programu _ _FILE_ _ nazwa tłumaczonego pliku _ _DATE_ _ napis w postaci "Mmm dd rrrr" - data kompilacji _ _TIME_ _ napis w postaci "gg:mm:ss" - czas kompilacji _ _STDC_ _ 1 dla kompilatorów dostosowanych do standardu
85 Preprocesor - pozostałe dyrektywy# error ciąg-leksemów wypisanie komunikatu diagnostycznego podczas kompilacji # line stała lub # line stała "nazwa-pliku" przypisanie numeru linii - może być wykorzystywane do celów diagnostycznych # pragma ciąg-leksemów zależne od implementacji kompilatora ignorowane jeśli kompilator nie obsługuje # pusta dyrektywa preprocesora
86 Zmienne listy argumentówprzykład z biblioteki standardowej int printf(const char *format, ...) plik nagłówkowy
87 Skoki odległe (long jumps)zastosowanie - ominięcie ciągu wywołań funkcji i powrotów (wyskok z zagnieżdżonych funkcji) plik nagłówkowy
88 Interakcja z systemem operacyjnymplik nagłówkowy
89 Obsługa daty i czasu plik nagłówkowy
90 Obsługa daty i czasu - c.d.wybrane funkcje do obsługi czasu time_t time(time_t *tp) aktualny czas kalendarzowy (tp może być NULL) double difftime(time_t t1, time_t t2) różnica czasów wyrażona w sekundach struct tm *gmtime(const time_t *tp) struct tm *localtime(const time_t *tp) char *asctime(const struct tm *tp) size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tp) format podobny do printf, np. %d - dzień miesiąca, %H - godzina, itp.
91 Obsługa sygnałów plik nagłówkowy
92 Obsługa diagnostycznaplik nagłówkowy
93 Microsoft Windows API API (Application Programming Interface)kernel32.dll, user32.dll, gdi32.dll, shell32.dll, ... C/C++ #include
94 Microsoft Windows API - c.d.WinMain #include
95 Microsoft Windows API - c.d.Funkcja "Call-back" LRESULT CALLBACK WindowProcedure( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { ... switch (message) { default: return DefWindowProc (hwnd, message, wParam, lParam); } ... }
96 Microsoft Windows API
97 Wstęp do technik tworzenia parserówCo to jest parser? program przetwarzający dane zapisane w sformalizowanym języku zgodnie z jego gramatyką liczne przykłady zastosowania: kompilatory języków programowania interpretatory poleceń obsługa interfejsów użytkownika przetwarzanie formalnych dokumentów HTML, TEX, XML, Mizar, ...
98 Techniki tworzenia parserów - c.d.Formalny opis języka gramatyka gramatyka bezkontekstowa (context-free grammar) zbiór rodzajów syntaktycznych wyrażeń zestaw reguł ich tworzenia z podwyrażeń notacja BNF (Backus-Naur Form) stworzona do specyfikacji języka Algol 60 gramatyki (LA)LR możliwość przetworzenia dowolnych danych wejściowych z pojedynczym wyprzedzeniem (look-ahead) tokenizacja (scanning) symbole terminalne i nieterminalne
99 Techniki tworzenia parserów - c.d.Przykład tokenizacji int /* keyword `int' */ square (int x) /* identifier,open-paren,keyword `int',identifier,close-paren */ { /* open-brace */ return x * x; /* keyword `return', identifier, asterisk, identifier, semicolon */ } /* close-brace */ jest to definicja funkcji zawiera ona jedną deklarację i jedną instrukcję w instrukcji każdy 'x' jest wyrażeniem a także 'x * x' jest wyrażeniem
100 Tworzenie skanerów LEX GNU Flex (fast scanner generator)wyrażenia regularne w pliku wejściowym output w postaci kodu C (lex.yy.c) funkcja int yylex() konsolidacja z biblioteką fl (gcc -l fl ...) format pliku wejściowego definitions %% rules %% user code
101 Tworzenie parserów Yacc GNU Bison (general-purpose LALR generator)wyrażenia regularne w pliku wejściowym output w postaci kodu C (plik.tab.c) - parser funkcja int yyparse() wymaga funkcji yylex kompatybilny z Lex format pliku wejściowego %{ Prologue %} Bison declarations %% Grammar rules %% Epilogue