Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Podstawy programowania Adam Naumowicz. Sprawy formalne 30 godz. wykładu + 30 godz. ćwiczeń (15 godz. w laboratorium) zaliczenie laboratorium i egzamin.

Podobne prezentacje


Prezentacja na temat: "Podstawy programowania Adam Naumowicz. Sprawy formalne 30 godz. wykładu + 30 godz. ćwiczeń (15 godz. w laboratorium) zaliczenie laboratorium i egzamin."— Zapis prezentacji:

1 Podstawy programowania Adam 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 B. 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 C 1969 – Martin Richards – język BCPL 1970 – Ken Thompson – język B adaptacja dla UNIX na maszynie DEC PDP – Dennis Ritchie – język C DEC PDP – standaryzacja ANSI American National Standards Institute 1990 – standard ISO International Organization for Standardization

6 Podstawowe cechy języka C ję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 danych int (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łych typ 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 typu short 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, … L ( l) 123U (123u) 31 = 037 = 0x1f = 0X1F

13 Formatowany input/output printf(…); 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 0 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: +, -, *, /, % (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 miejsca return wyrażenie opc ; 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 (wyr1 opc ; wyr2 opc ; wyr3 opc ) 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 - przerywanie break; 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ównanie while (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]; 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źnikowe wskaź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 - ograniczenia funkcji 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 (parametry opc ); definicja: typ-wyniku nazwa (parametry opc ); {... instrukcje... return wyrażenie opc ; } standaryzacja w ANSI C

38 Funkcje w C - c.d. domyślny typ wyniku to int gdy funkcja nie zwraca wartości stosuje się typ void parametry mają postać: typ 1 zmienna 1 [, typ 2 zmienna 2 ]... 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; inicjalizacja na 0 gdy brak przypisania

40 Funkcje rekurencyjne w C Funkcja 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łady potęga x n =x * x *...* x (n razy) x 0 =1, x n+1 =x * x n 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 struct nazwa opc { typ 1 składowa 1 ; typ 2 składowa 2 ;... } zmienne opc ; 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ęci unia 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 strukturze struct{ 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 jednobitowe umoż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ład maski 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 nazwa opc : 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 operacje FILE *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 tekstowe char *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ście int *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ście size_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: funkcje do klasyfikacji znaków - wynik jest typu int - różny od 0 gdy argument spełnia dany warunek int isalpha(int c) int isdigit(int c) int isalnum(int c) int islower(int c)int tolower(int c) int isupper(int c)int toupper(int c) int isspace(int c) int isxdigit(int c) int iscntrl(int c)

64 Biblioteka standardowa: funkcje operujące na tekstach - argumenty s i t są typu char*, cs i ct są typu const char*, n jest typu size_t, a c ma typ int przekształcony do char char *strcpy(s,ct) char *strncpy(s,ct,n) char *strcat(s,ct) char *strncat(s,ct,n) int strcmp(cs,ct) int strncmp(cs,ct,n) size_t strlen(cs)

65 - c.d. char *strchr(cs,c) char *strrchr(cs,c) size_t strspn(cs,ct) size_t strcspn(cs,ct) char *strpbrk(cs,ct) char *strstr(cs,ct) char *strtok(s,ct) za pierwszym razem wywołuje się funkcję z argumentem s różnym od NULL kolejne wywołania z s równym NULL ct może być różny za każdym razem na końcu zwraca NULL

66 - c.d. funkcje operujące na obiektach traktowanych jako tablice znakowe - argumenty s i t są typu void*, cs i ct są typu const void*, n jest typu size_t, a c ma typ int przekształcony do unsigned char void *memcpy(s,ct,n) void *memmove(s,ct,n) działa, gdy obiekty "zachodzą" na siebie int memcmp(cs,ct,n) void *memchr(cs,c,n) void *memset(s,c,n)

67 Biblioteka standardowa: funkcje matematyczne - argumenty x i y są typu double, n jest typu int, zwracają wynik typu double sin(x)cos(x)tan(x) asin(x)acos(x)atan(x) exp(x)log(x)log10(x) pow(x,y)sqrt(x) ceil(x)floor(x) fabs(x) fmod(x,y) modf(x, double *ip)

68 Biblioteka standardowa: funkcje narzędziowe - konwersja liczb, przydzielanie pamięci, interakcja z systemem operacyjnym double atof(const char *s) int atoi(const char *s) long atol(const char *s) double strtod(const char *s, char **endp) jeśli endp jest różny od NULL - nieprzetworzona część napisu long strtol(const char *s,char **endp, int b) b - podstawa (2-36)

69 - c.d. int rand(void) wartość pseudolosowa z przedziału od 0 do RAND_MAX (co najmniej 32767) void srand(unsigned int seed) początkowy zarodek jest równy 1

70 - c.d. void *bsearch( const void *key, const void *base, size_t n, size_t size, int (*cmp)(const void *keyval, const void *datum) ) Uwaga: tablica musi być uporzadkowana rosnąco! funkcja cmp musi zwracać -1, 0 lub 1 gdy keyval* poprzedza, jest równy lub następuje po datum* void qsort(void *base, size_t n, size_t size, int (*cmp)(const void *, const void *) ) porządkuje w kolejności rosnącej funkcja porównująca taka sama jak dla bsearch

71 Dynamiczny przydział pamięci void *malloc (size_t size) zwraca wskaźnik do obiektu o rozmiarze size utworzonego dynamicznie zwraca NULL gdy nie może zrealizować polecenia void *calloc(size_t n, size_t size) tworzy tablicę n elementów o rozmiarach size obszar jest inicjalizowany zerami void *realloc(void *p, size_t size) zmienia rozmiar obiektu wskazywanego przez p na size void free(void *p) zwalnia pamięć przydzieloną uprzednio przez malloc, calloc, lub realloc nie robi nic gdy p jest równy NULL

72 Lista jednokierunkowa typedef 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 C Pierwsza 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 preprocesora zastępowanie tzw. sekwencji trzyznakowych sklejanie wierszy wystąpienia \ są zamieniane na pojedyncze odstępy przekształcenie kodu programu na ciąg leksemów oddzielonych odstępami komentarze zamieniane są na pojedynczy odstęp wykonanie dyrektyw (każda w osobnej linii) rozwinięcie makr zastępowanie sekwencji specjalnych w stałych znakowych i napisach oraz łączenie sąsiadujących napisów np. \n, \123 itp. tłumaczenie wyniku i łączenie z innymi programami/bibliotekami zapewnienie powiązania zewnetrznych funkcji i obiektów z ich definicjami

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 przeszukiwanie bieżącej kartoteki lub listy lokalizacji zależnej od implementacji włączanie plików można zagnieżdżać można użyć konstrukcji # include ciąg-leksemów aby wywołać rozwinięcie makra do jednej z postaci j/w

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 specjalne zawsze 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ów przykład z biblioteki standardowej int printf(const char *format,...) plik nagłówkowy typ va_list - reprezentuje wskaźnik na kolejny argument makra void va_start(va_list ap, ostatni_nazwany_parametr) typ va_arg(va_list ap, typ) void va_end(va_list ap) przykład type r myfunc(type 1 par 1,..., type k par k,...) {... va_list ap; va_start(ap, par k );... type k+1 x = va_arg(ap, type k+1 )... va_end(ap);... }

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 jmp_buf - typ do przechowania stanu programu w chwili wywołania funkcji setjmp int setjmp(jmp_buf env) void longjmp(jmp_buf env, int val) przykład if (setjmp(env)==0)... /* kod wykonywany bezpośrednio po wejściu*/ else... /* kod wykonywany po wołaniu longjmp */

88 Interakcja z systemem operacyjnym plik nagłówkowy char *getenv(const char *name) zwraca wartość zmiennej środowiskowej name int system(const char *prog) uruchamia program prog i zwraca jego kod wyjścia void exit (int status) kończy program z kodem status stałe EXIT_SUCCESS, EXIT_FAILURE int atexit(void (*func)(void)) rejestruje funkcję func do wykonania przy wyjściu z programu - powstaje łańcuch funkcji void abort(void) bezwzględne zakończenie programu

89 Obsługa daty i czasu plik nagłówkowy clock_t, time_t - typy arytmetyczne struct tm - składniki czasu kalendarzowego int tm_sec int tm_min int tm_hour int tm_mday int tm_mon int tm_year - lata, które upłyneły od 1900 r. int tm_wday int tm_yday int tm_isdst - znacznik czasu letniego

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 void (*signal(int sig, void (*handler)(int)))(int) SIG_DFL, SIG_IGN - predefiniowane handlery na początku obsługi przywracana jest domyślna wartość handlera - należy ustawić go na nowo wewnątrz handlera int raise(int sig) wybrane sygnały SIGFPE SIGINT SIGSEGV SIGABRT SIGTERM

92 Obsługa diagnostyczna plik nagłówkowy makro assert(int wyrażenie) Assertion failed: wyrażenie, file..., line... _ _FILE_ _ _ _LINE_ _ wywołanie funkcji abort zdefiniowanie NDEBUG przed włączeniem pliku nagłówkowego assert.h sprawia, że makro assert jest ignorowane

93 Microsoft Windows API API (Application Programming Interface) kernel32.dll, user32.dll, gdi32.dll, shell32.dll,... C/C++ #include Dokumentacja:

94 Microsoft Windows API - c.d. WinMain #include int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MessageBox(NULL,"Hello world!", "Note", MB_OK); return 0; }

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ów Co 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, T E X, 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


Pobierz ppt "Podstawy programowania Adam Naumowicz. Sprawy formalne 30 godz. wykładu + 30 godz. ćwiczeń (15 godz. w laboratorium) zaliczenie laboratorium i egzamin."

Podobne prezentacje


Reklamy Google