Proceduralne Języki Programowania Patryk Jasik Katedra Fizyki Teoretycznej i Informatyki Kwantowej Wydział Fizyki Technicznej i Matematyki Stosowanej Politechnika.

1 Proceduralne Języki Programowania Patryk Jasik Katedra ...
Author: Liliana Grzybowska
0 downloads 2 Views

1 Proceduralne Języki Programowania Patryk Jasik Katedra Fizyki Teoretycznej i Informatyki Kwantowej Wydział Fizyki Technicznej i Matematyki Stosowanej Politechnika Gdańska Pokój 415GB E-mail: [email protected]@mif.pg.gda.pl Strona domowa: http://aqualung.mif.pg.gda.plhttp://aqualung.mif.pg.gda.pl Konsultacje: poniedziałek 15-16, środa 16-17

2 Warunki zaliczenia przedmiotu Pisemny sprawdzian wiedzy z wykładu (10 pkt) 3 sprawdziany z programowania podczas zajęć laboratoryjnych (30 pkt) Uzyskanie 50% punktów spośród wszystkich możliwych do zdobycia Termin zaliczenia wykładu: ostatnie zajęcia w semestrze, 10.VI.2009 Terminy sprawdzianów z programowania: -23.III.2009 -11.V.2009 -8.VI.2009

3 Literatura I. Sommerville – „Inżynieria oprogramowania”, WNT, Warszawa 2003 B.W. Kernighan, D.M. Ritchie – „Język ANSI C”, WNT, Warszawa 2003 C.L. Tondo, S.E. Gimpel – „Język ANSI C – ćwiczenia i rozwiązania”, WNT, Warszawa 2004 N. Wirth – „Algorytmy + struktury danych = programy”, WNT 2002 www.moodle.pg.gda.pl – Proceduralne i obiektowe języki programowania S. Prata – „Język C. Szkoła programowania”, Helion S. Oaulline – „Język C. Programowanie”, Helion

4 Historia BCPL, Richards, 1967 – prototyp języka C Język B, Thompson, 1969 – prototyp języka C Simula 67, Dahl, 1970 – pojęcie klasy wraz z klasami pochodnymi i funkcjami wirtualnymi Algol 68, Woodward, 1974 – przeciążanie operatorów i możliwość umieszczania deklaracji wszędzie tam, gdzie są dozwolone instrukcje Język C, Kernighan, Ritchie, 1978 – prototyp języka C++ Język ANSI C, Kernighan, Ritchie, 1988 ADA, Ichbiah, 1979 – obsługa wyjątków CLU, Liskov, 1979 – obsługa wyjątków C z klasami, Stroustrup, 1980 – rozszerzenie języka C C++, Stroustrup, lipiec 1983 – pierwsze zastosowanie poza pracownią badawczą Standard ISO C++, Stroustrup, 1998, poprawki do standardu 2003, nowy standard 2009 Java, Gosling, 1994 C#, Hejlsberg, początek XXI wieku

5 Pierwszy program #include int main() { printf ("Witajcie! To jest wyklad z proceduralnych jezykow programowania."); }

6 Drugi program #include int main() { int x, y, liczba; printf(„Podaj pierwsza liczbe: \n"); scanf(„%i”, &x); printf(„Podaj druga liczbe: \n"); scanf(„%i”, &y); liczba = x+y; printf("To jest nasz wynik: x+y=%i\n", liczba); }

7 Kompilacja http://januszg.hg.pl/teksty/kompilatory_c_cpp.html GCC (GNU Compiler Collection), Cygwin, MinGW, DJGPP, EMX 0.9, RSX tools for GNU C/C++, Borland C++ Compiler 5.5, Borland Kylix 3 Open Edition, Borland C++Builder 6 Personal, Borland C++BuilderX Personal, Microsoft Visual C++ Toolkit 2003, LCC-Win32, lcc 4.1, Digital Mars, Macintosh Programmer's Workshop (MPW), Turbo C 2.01, Turbo C++ 1.01, Pacific C MS- DOS Compiler, Compaq C Version 6.4 for Linux Alpha, Open Watcom 11C, Intel(R) C++ Compiler 6.0 for Linux, ACC, LadSoft CC386 1.90, Small C Compiler 2.2, Tiny C Compiler, Digital Research C for PC-DOS, LSI C-86, Cyclone, Pelles C for Windows

8 Preprocesor To program interpretujący, którego zadaniem jest przetworzenie tekstu wejściowego w sposób określony za pomocą poleceń preprocesora przez programistę na tekst wyjściowy. Dopiero tak przetworzony tekst poddawany jest analizie składniowej i kompilacji. Wynikiem działania preprocesora jest więc tekst wyjściowy po przetworzeniu podlegający następnie kompilacji. Dyrektywy preprocesora mogą występować w ogólności w dowolnym miejscu programu, a rozróżnienie ich od tekstu kodu źródłowego w językach C i C++ dokonywane jest poprzez poprzedzenie dyrektywy znakiem hash #.

9 Preprocesor Do najważniejszych dyrektyw należą: #include … - dyrektywa włączająca tekst innego pliku źródłowego w miejscu jej wystąpienia w pliku podlegającym aktualnie przetwarzaniu, przy czym możliwe jest zagłębione występowanie dyrektywy include, #define … - definiuje stałe i makroinstrukcje (pseudofunkcje) #undef … - usuwa definicje stałej lub makra #if … - dyrektywy kompilacji warunkowej #elif … - działa podobnie jak else if w języku C #endif … - oznacza koniec bloku kompilacji warunkowej #ifdef … - znaczy to samo co #if defined(…) #ifndef … - znaczy to samo co #if !defined(…)

10 Biblioteki podstawowe assert.h - deniuje makro assert, używane do diagnostyki programu. complex.h – zestaw funkcji opisujących działania na liczbach zespolonych. ctype.h - deklaruje funkcje do klasykacji i konwersji znaków (kody ASCII). errno.h - deniuje makra dla warunków błędu, EDOM i ERANGE, oraz zmienną całkowitą errno, poprzez którą funkcje biblioteczne zwracają kod błędu.

11 Biblioteki podstawowe float.h - definiuje zakres wartości, które mogą być zapamiętywane w typach zmiennoprzecinkowych. fenv.h – kontrola środowiska zmiennoprzecinkowego. inttypes.h – funkcje precyzyjnej konwersji między typami całkowitymi (integer). iso646.h – definiuje makra w standardzie iso646 (and = &&, or = ||, not_eq = !=) limits.h - definiuje wartości ograniczające dla wszystkich danych typu całkowitego (_MIN, _MAX). locale.h - deklaruje strukturę lconv i funkcje niezbędne do przystosowania programu w C do poszczególnych środowisk lokalnych. math.h - deklaruje funkcje matematyczne oraz makro HUGE_VAL.

12 Biblioteki podstawowe setjmp.h - definiuje funkcje setjmp oraz longjmp, które mogą przekazywać kontrole z jednej funkcji do drugiej bez opierania się na wywołaniach i powrotach z funkcji. Definiuje również typ danych jmp_buf używany przez setjmp i longjmp. signal.h - definiuje symbole i procedury niezbędne dla obsługi zdarzeń wyjątkowych. stdarg.h - definiuje makra, które umożliwiają dostęp do nienazwanych argumentów w funkcji, która akceptuje zmienną liczbę argumentów. stdbool.h – obsługa typów logicznych. stdint.h – obsługa różnych typów w zakresie liczb całkowitym. stddef.h - deniuje standardowe typy danych ptrdi_t, size_t, wchar_t oraz symbol NULL.

13 Biblioteki podstawowe stdio.h - deklaruje funkcje i typy danych niezbędne do obsługi operacji we/wy (operacje na plikach, formatowane wyjście/wejście, f. realizujące we/wy znakowe, f. wyznaczające pozycję w pliku, obsługa błędów). stdlib.h - deklaruje wiele funkcji użyteczności takich, jak procedury konwersji łańcuchów, generator liczb losowych, procedury alokacji pamięci i procedury kontroli procesów (takie, jak abort, exit i system), wyszukiwanie, sortowanie. string.h - deklaruje funkcje do manipulowania łańcuchami takie, jak strcmp i strcpy. time.h - deklaruje typy daty i definiuje funkcje do manipulowania czasem. Definiuje typy clock_t i time_t oraz strukturę danych tm. wchar.h – manipulacje znakami regionalnymi (różne języki) wctype.h – klasyfikacja znaków regionalnych.

14 Słowa kluczowe auto, break, case, char, const, continue, default, do, double, else, enum, extern, float, for, goto, if, int, long, register, return, short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, volatile, while

15 Stałe znakowe nowy wiersz tabulacja pozioma tabulacja pionowa cofanie powrót karetki nowa strona alarm kreska ukośna w lewo znak zapytania apostrof cudzysłów liczba ósemkowa liczba szesnastkowa \n \t \v \b \r \f \a \\ \? \’ \” \ooo \xhh

16 Przekształcenia funkcji printf/scanf ZnakTyp argumentuPrzekształcany do postaci d, iintliczby dziesiętnej ze znakiem. ointliczby ósemkowej bez znaku (bez wiodącego zera) x, Xintliczby szesnastkowej bez znaku (bez wiodącego 0x) z użyciem liter abcdef dla 0x i ABCDEF dla 0X. uintliczby dziesiętnej bez znaku. cintpojedynczego znaku po przekształceniu do typu unsigned char. schar *Znaki tekstu są wypisywane aż do napotkania znaku ‘\0’ lub liczba wypisanych znaków osiągnie wskazaną precyzję. fdoubleliczby dziesiętnej [-]mmm.ddd, gdzie liczbę cyfr d określa precyzja. Domyślną precyzją jest 6; przy precyzji 0 opuszcza się kropkę dziesiętną. e, Edoubleliczby dziesiętnej [-]m.dddddde±xx lub [-]m.ddddddE±xx, gdzie liczbę cyfr d określa precyzja. g, GdoubleJeśli wykładnik potęgi jest mniejszy niż -4, większy lub równy precyzji, to stosuje się specyfikację %e lub %E; w przeciwnym przypadku %f. Nie wypisuje się nie znaczących zer i zbędnej kropki dziesiętnej. pvoid *wskaźnika (reprezentacja zalży od reprezentacji). nint *Liczbę dotychczas wypisanych znaków zapisuje się do odpowiedniego argumentu. Nie ma żadnego przekształcenia argumentu. %Nie ma żadnego przekształcenia argumentu-zostanie wypisany znak %.

17 Specyfikatory typu void char – jeden bajt, zdolny pomieścić jeden znak z lokalnego zbioru znaków (u 0-255, s -128 +127); short – 16 bitów (-32768 +32767) int – typ całkowity (16 lub 32 bity), odzwierciedla naturalny rozmiar liczb całkowitych komputera (-32768 +32767 lub -2 147 483 648 to 2 147 483 647) long – 32 bity − (-2 147 483 648 to 2 147 483 647) float – typ zmiennopozycyjny pojedynczej precyzji (10 -38 10 +38 ) double – typ zmiennopozycyjny pojedynczej precyzji signed – typ ze znakiem unsigned – typ bez znaku

18 Rodzina operatorów Operatory arytmetyczne +-*/% Relacje i operatory logiczne >>=

19 Rodzina operatorów Przykład if((year % 4 ==0 && year % 100 != 0) || year % 400 == 0) printf(„%d jest rokiem przestępnym \n”, year); else printf(„%d nie jest rokiem przestępnym \n”, year);

20 Bloki sterujące if else else if switch case for while do while break continue goto

21 if else Przykład if (wyrażenie) { instrukcja1; instrukcja2; … } else { instrukcja3; instrukcja4; … }

22 else if Przykład if (wyrażenie) { instrukcja1; instrukcja2; … } else if (wyrażenie) { instrukcja3; instrukcja4; … } … else { instrukcja5; instrukcja6; … }

23 switch case Przykład switch (wyrażenie) { case wyrażenie-stałe1: instrukcje break; case wyrażenie-stałe2: instrukcje break; … default: instrukcje break; }

24 for Przykład for(wyr1; wyr2; wyr3) { instrukcja1; instrukcja2; … } for(i = 0; i < n; i++) { … }

25 while Przykład while(wyrażenie) { instrukcja1; instrukcja2; … }

26 do while Przykład do { instrukcja1; instrukcja2; … } while(wyrażenie)

27 Break i continue Przykład /* trim: usuń z s końcowe znaki odstępu, tabulacji, nowego wiersza */ int trim(char s[]) { int n; for(n = strlen(s)-1; n>=0; n--) if(s[n] != ‘ ’ && s[n] != ‘\t’ && s[n] != ‘\n’) break; s[n+1] = ‘\0’; return n; }

28 Break i continue Przykład for(i =0; i < n; i++) { if(a[i] < 0) /*pomiń element ujemny*/ continue; … /*przetwarzaj element nieujemny*/ }

29 Goto Przykład for (…) for (…) { … if (niepowodzenie) goto error; /*skocz do obsługi błedów*/ } … error: /*napraw sytuację lub wypisz komunikat*/

30 funkcje = moduły Przykład nazwa_funkcji(typ_argumentu argument1, typ_argumentu argument2, …) Typy zmiennych przekazywane do funkcji muszą być zgodne z typami argumentów funkcji. Typ funkcji również powinien być określony. funkcja = moduł Plik, w którym została zapisana funkcja powinien być dołączony do programu głównego w preprocesorze #include „nazwa_funkcji.h”

31 wskaźniki Wskaźnik jest zmienną, która zawiera adres innej zmiennej. ……… p:c: Wskaźnik jest grupą komórek, które mogą pomieścić adres. Jeśli c jest obiektem typu char, a p jest wskaźnikiem, który wskazuje na c, to taką sytuację zilustrowano na obrazku. Jednoargumentowy operator & podaje adres obiektu p = &c; powyższa instrukcja przypisuje zmiennej p adres zmiennej c, zmienna p wskazuje na zmienną c

32 wskaźniki Jednoargumentowy operator * oznacza adresowanie pośrednie lub odwołanie pośrednie, a zastosowany do wskaźnika daje zawartość obiektu wskazywanego przez ten wskaźnik 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] Od wskaźnika wymaga się wskazywania obiektów określonego rodzaju. (Z jednym wyjątkiem – wskaźnik do void, czyli „wskaźnik do niczego”, może przechowywać wskaźnik do obiektów dowolnego typu, ale nie można go stosować do adresowania pośredniego.)

33 wskaźniki Jeżeli wskaźnik ip wskazuje na zmienną całkowitą x, to *ip może wystąpić wszędzie tam, gdzie może wystąpić x y = *ip + 5 *ip = *ip + 10 *ip += 1 ++*ip (*ip)++ iq = ip

34 wskaźniki źródło: http://pl.wikibooks.org/wiki/C/Wskaźniki http://pl.wikibooks.org/wiki/C/Wskaźniki Wskaźnik (ang. pointer) to specjalny rodzaj zmiennej, w której zapisany jest adres w pamięci komputera, tzn. wskaźnik wskazuje miejsce, gdzie zapisana jest jakaś informacja. Oczywiście nic nie stoi na przeszkodzie aby wskazywaną daną był inny wskaźnik do kolejnego miejsca w pamięci. Obrazowo możemy wyobrazić sobie pamięć komputera jako bibliotekę a zmienne jako książki. Zamiast brać książkę z półki samemu (analogicznie do korzystania wprost ze zwykłych zmiennych) możemy podać bibliotekarzowi wypisany rewers z numerem katalogowym książki a on znajdzie ją za nas. Analogia ta nie jest doskonała, ale pozwala wyobrazić sobie niektóre cechy wskaźników: kilka rewersów może dotyczyć tej samej książki, numer w rewersie możemy skreślić i użyć go do zamówienia innej książki, jeśli wpiszemy nieprawidłowy numer katalogowy to możemy dostać nie tą książkę, którą chcemy, albo też nie dostać nic. Warto też poznać w tym miejscu definicję adresu pamięci. Możemy powiedzieć, że adres to pewna liczba całkowita, jednoznacznie definiująca położenie pewnego obiektu (czyli np. znaku czy liczby) w pamięci komputera.

35 wskaźniki Wskaźnik a wskazujący na zmienną b. Zauważmy, że b przechowuje liczbę, podczas gdy a przechowuje adres b w pamięci (1462)

36 wskaźniki Przykład #include int main() { int liczba = 80; printf("Zmienna znajduje sie pod adresem: %p, i przechowuje wartosc: %d\n", &liczba, liczba); }

37 wskaźniki Przykład #include int main() { int liczba = 80; int *wskaznik = &liczba; printf("Wartosc zmiennej: %d; jej adres: %p.\n", liczba, &liczba); printf("Adres zapisany we wskazniku: %p, wskazywana wartosc: %d.\n", wskaznik, *wskaznik); *wskaznik = 42; printf("Wartosc zmiennej: %d, wartosc wskazywana przez wskaznik: %d\n", liczba, *wskaznik); liczba = 55; printf("Wartosc zmiennej: %d, wartosc wskazywana przez wskaznik: %d\n", liczba, *wskaznik); }

38 wskaźniki a tablice W języku C występuje ścisła zależność między wskaźnikami i tablicami. Każdą operację, którą można przeprowadzić za pomocą indeksowania tablicy, można również wykonać za pomocą wskaźników. Wersja wskaźnikowa będzie na ogół szybsza. Przykład: int a[10]; - a[0], a[1], a[2], …, a[9] a[i] oznacza i-ty element tablicy a int *pa; - wskaźnik do obiektów całkowitych pa = &a[0]; - przypisanie ustawi pa tak, aby wskazywał na 0 element tablicy, wskaźnik pa zawiera adres elementu a[0] x = *pa – przypisanie skopiuje zawartość a[0] do x Jeśli pa wskazuje na pewien element tablicy, to pa+1 wskazuje na element następny, pa+i odnosi się do i-tego elementu po pa, pa-i do i- tego elementu przed pa. Jeśli pa wskazuje na a[0], to *(pa+1) – odnosi się do zawartości a[1]; pa+i jest adresem a[i], a *(pa+i) jest zawartością a[i].

39 wskaźniki a funkcje Czasami zdarza się, że argumentem (lub argumentami) funkcji są wskaźniki. W przypadku "normalnych" zmiennych nasza funkcja działa tylko na lokalnych kopiach tychże argumentów, natomiast nie zmienia zmiennych, które zostały podane jako argument. Natomiast w przypadku wskaźnika, każda operacja na wartości wskazywanej powoduje zmianę wartości zmiennej zewnętrznej. Przykład: #include void func (int *zmienna) { *zmienna = 5; } int main() { int z=3; printf ("z=%d\n", z); // wypisze 3 func(&z); printf ("z=%d\n", z); // wypisze 5 } Funkcje w języku C nie tylko potrafią zwracać określoną wartość, lecz także zmieniać dane, podane im jako argumenty. Ten sposób przekazywania argumentów do funkcji jest nazywany przekazywaniem przez wskaźnik (w przeciwieństwie do normalnego przekazywania przez wartość).

40 Argumenty wywołania programu Działania każdego programu rozpoczyna się wywołaniem funkcji main z dwoma argumentami. Pierwszy, umownie nazywany argc (ang. argument count), jest liczbą argumentów, z jakimi program został wywołany; drugi argv (ang. argument vector), jest wskaźnikiem do tablicy zawierającej argumenty, każdy argument jako osobny tekst. Zgodnie z przyjętą konwencją: argv[0] – jest nazwą z jaką program został wywołany, licznik argc jest więc co najmniej równy 1. Wartość argc równa 1 oznacza, że w wierszu polecenia po nazwie programu nie było argumentów. Przykład:./nazwa_programu aaa bbb argc = 3, argv[0] = nazwa_programu, argv[1] = aaa, argv[2] = bbb Dodatkowo standard wymaga, aby element argv[argc] = argv[3] był wskaźnikiem pustym, czyli równym NULL.

41 Argumenty wywołania programu Przykład: #include main(int argc, char* argv[]) { int i; printf("argc = %d\n", argc); for (i = 0; i < argc; i++) printf("argv[%d] = \"%s\"\n", i, argv[i]); }

42 #include #include int main(int argc, char** argv) { /* Set defaults for all parameters: */ int a_value = 0; float b_value = 0.0; char* c_value = NULL; int d1_value = 0, d2_value = 0;int i; /* Start at i = 1 to skip the command name. */ for (i = 1; i < argc; i++) { /* Check for a switch (leading "-"). */ if (argv[i][0] == '-') { /* Use the next character to decide what to do. */ switch (argv[i][1]) { case 'a': a_value = atoi(argv[++i]); break; case 'b': b_value = atof(argv[++i]); break; case 'c': c_value = argv[++i]; break; case 'd': d1_value = atoi(argv[++i]); d2_value = atoi(argv[++i]); break; } printf("a = %d\n", a_value); printf("b = %f\n", b_value); if (c_value != NULL) printf("c = \"%s\"\n", c_value); printf("d1 = %d, d2 = %d\n", d1_value, d2_value); }

43 Operacje na plikach Istnieją dwie metody obsługi czytania i pisania do plików: wysokopoziomowa i niskopoziomowa. Nazwy funkcji z pierwszej grupy zaczynają się od litery "f" (np. fopen(), fread(), fclose()), a identyfikatorem pliku jest wskaźnik na strukturę typu FILE. Owa struktura to pewna grupa zmiennych, która przechowuje dane o danym pliku - jak na przykład aktualną pozycję w nim. Szczegółami nie należy się przejmować, funkcje biblioteki standardowej same zajmują się wykorzystaniem struktury FILE, programista może więc zapomnieć, czym tak naprawdę jest struktura FILE i traktować taką zmienną jako "uchwyt", identyfikator pliku. Druga grupa to funkcje typu read(), open(), write() i close(). Podstawowym identyfikatorem pliku jest liczba całkowita, która jednoznacznie identyfikuje dany plik w systemie operacyjnym. Liczba ta w systemach typu UNIX jest nazywana deskryptorem pliku. Należy pamiętać, że nie wolno nam używać funkcji z obu tych grup jednocześnie w stosunku do jednego, otwartego pliku, tzn. nie można najpierw otworzyć pliku za pomocą fopen(), a następnie odczytywać danych z tego samego pliku za pomocą read(). Czym różnią się oba podejścia do obsługi plików? Otóż metoda wysokopoziomowa ma swój własny bufor, w którym znajdują się dane po odczytaniu z dysku a przed wysłaniem ich do programu użytkownika. W przypadku funkcji niskopoziomowych dane kopiowane są bezpośrednio z pliku do pamięci programu. W praktyce używanie funkcji wysokopoziomowych jest prostsze a przy czytaniu danych małymi porcjami również często szybsze.

44 Operacje na plikach Można zauważyć, że do zapisu do pliku używamy funkcji fprintf, która wygląda bardzo podobnie do printf - jedyną różnicą jest to, że w fprintf musimy jako pierwszy argument podać identyfikator pliku. Nie jest to przypadek - obie funkcje tak naprawdę robią tak samo. Używana do wczytywania danych z klawiatury funkcja scanf też ma swój odpowiednik wśród funkcji operujących na plikach - jak nietrudno zgadnąć, nosi ona nazwę fscanf. W rzeczywistości język C traktuje tak samo klawiaturę i plik - są to źródła danych, podobnie jak ekran i plik, do których można dane kierować. Jest to myślenie typowe dla systemów typu UNIX, jednak dla użytkowników przyzwyczajonych do systemu Windows albo języków typu Pascal może być to co najmniej dziwne. Nie da się ukryć, że między klawiaturą i plikiem na dysku zachodzą podstawowe różnice i dostęp do nich odbywa się inaczej - jednak funkcje języka C pozwalają nam o tym zapomnieć i same zajmują się szczegółami technicznymi. Z punktu widzenia programisty, urządzenia te sprowadzają się do nadanego im identyfikatora. Uogólnione pliki nazywa się w C strumieniami. Każdy program w momencie uruchomienia "otrzymuje" od razu trzy otwarte strumienie (aby z nich korzystać należy dołączyć plik nagłówkowy stdio.h): stdin (wejście) stdout (wyjście) stderr (wyjście błędów) Pierwszy z tych plików umożliwia odczytywanie danych wpisywanych przez użytkownika, natomiast pozostałe dwa służą do wyprowadzania informacji dla użytkownika oraz powiadamiania o błędach.

45 Operacje na plikach Przykład: #include int main() { FILE *fp; /* używamy metody wysokopoziomowej - musimy mieć zatem identyfikator pliku, uwaga na gwiazdkę! */ char tekst[] = "Hello world"; if ((fp=fopen("test.txt", "w"))==NULL) { printf ("Nie mogę otworzyć pliku test.txt do zapisu!\n"); exit(1); } fprintf (fp, "%s", tekst); /* zapisz nasz łańcuch w pliku */ fclose (fp); /* zamknij plik */ return 0; }

46 Operacje na plikach FILE *fopen(const char *filename, const char *mode); Funkcja fopen() otwiera plik, którego nazwa podana jest w pierwszym argumencie. Drugim jest łańcuch znaków zwierający litery oznaczające sposób otwarcia pliku: "r" - otwiera plik do czytania "w" - otwiera plik do nadpisywania (zamazuje starą treść) "a" - otwiera plik do dopisywania (jeśli plik nie istnieje, to jest tworzony) "t" - otwiera plik w trybie tekstowym "b" - otwiera plik w trybie binarnym Litery można ze sobą łączyć, np. "rwb" albo "wt".

47 Operacje na plikach #include int main(int argc, char *argv[]) { FILE *fp; int c; if (argc < 2) { fprintf (stderr, "Uzycie: %s nazwa_pliku\n", argv[0]); exit (-1); } fp = fopen (argv[1], "w"); if (!fp) { fprintf (stderr, "Nie moge otworzyc pliku %s\n", argv[1]); exit (-1); } printf("Wcisnij Ctrl+D lub Ctrl+Z aby zakonczyc\n"); while ( (c = fgetc(stdin)) != EOF) { fputc(c, stdout); fputc(c, fp); } fclose(fp); return 0; }

48 Operacje na plikach Dzięki standardowym funkcjom języka C możemy m.in. określić długość pliku. Do tego celu służą funkcje fsetpos, fgetpos oraz fseek. Przy każdym odczycie/zapisie z/do pliku wskaźnik niejako "przesuwa" się o liczbę przeczytanych/zapisanych bajtów. Możemy jednak ustawić wskaźnik w dowolnie wybranym miejscu. Do tego właśnie służą wyżej wymienione funkcje. Aby odczytać rozmiar pliku powinniśmy ustawić nasz wskaźnik na koniec pliku, po czym odczytać ile bajtów od początku pliku się znajdujemy. Procedura ta działa wyjątkowo prosto i skutecznie. Użyjemy do tego tylko dwóch funkcji: fseek oraz fgetpos. Pierwsza służy do ustawiania wskaźnika na odpowiedniej pozycji w pliku, a druga do odczytywania na którym bajcie pliku znajduje się wskaźnik.

49 Operacje na plikach #include int main (int argc, char **argv) { FILE *fp = NULL; fpos_t dlugosc; if (argc != 2) { printf ("Użycie: %s \n", argv[0]); return 1; } if ((fp=fopen(argv[1], "rb"))==NULL) { printf ("Błąd otwarcia pliku: %s!\n", argv[1]); return 1; } fseek (fp, 0, SEEK_END); /* ustawiamy wskaźnik na koniec pliku fgetpos (fp, &dlugosc); printf ("Rozmiar pliku: %d\n", dlugosc); fclose (fp); return 0; }

50 Struktury danych Struktura danych jest to najogólniej mówiąc sposób reprezentacji oraz organizacji informacji. Można powiedzieć, że najprostszą strukturą danych w języku ANSI C (jak i w wielu innych) jest zmienna wybranego przez programistę typu. Dla przykładu, zmienna o nazwie x typu float może nam posłużyć do przechowania rozwiązania równania. Jednak gdybyśmy chcieli np. stworzyć pewien ciąg, który zawiera np. 10 elementów musielibyśmy stworzyć 10 zmiennych – a1, a2,..., a10. Zamiast tego możemy skorzystać z innej struktury, czyli z tablicy np. int tab[10] co nam da 10 elementową tablicę przechowującą liczby całkowite.

51 Struktury danych Język ANSI C umożliwia nam tworzenie własnych struktur. Taka struktura jest typem zawierającym w sobie zmienne dowolnego typu (tzw. pola). Struktura umożliwia zapakowanie powiązanych ze sobą logicznie danych w jednym obszarze pamięci, który może być przesyłany jako jeden argument. struct nazwa_struktury {.... //

52 Struktury danych Definicja struktury: struct Struktura{ int pole1; int pole2; char pole3; } zmiennaS = {1, 2, 'c'} ; Gdzie "Struktura" to nazwa tworzonej struktury. Nazewnictwo, ilość i typ pól definiuje programista według własnego uznania. Zmienną posiadającą strukturę tworzy się podając jako jej typ nazwę struktury. struct Struktura zmiennaS;

53 Struktury danych Dostęp do poszczególnych pól, tak samo jak w przypadku unii, uzyskuje się przy pomocy operatora kropki zmiennaS.pole1 = 60; /*przypisanie liczb do pól*/ zmiennaS.pole2 = 2; zmiennaS.pole3 = 'a'; /*a teraz znaku */ lub za pomocą wskaźnika wsk->pole1; wsk->pole2;

54 #include /* deklarujemy prosta strukture */ struct point { float x; float y; }; int main(){ /* zmienna typu strukturalnego: */ struct point p; /* odwolujemy sie do pierwszego pola struktury: */ scanf("%f", &p.x); /*... i do drugiego pola: */ p.y=4.5; /* na koniec wypiszmy zawartosc struktury point: */ printf("x=%f\n",p.x); printf("y=%f\n",p.y); return 0; }

55 #include int main(){ struct Adres{ char Ulica[30]; int Nr_Domu; int Nr_Mieszk; }; struct SCzlowiek{ char Imie[20]; int Wiek; struct Adres Mieszkanie; }; struct SCzlowiek LISTA[50]; LISTA[1].Wiek=34; LISTA[1].Mieszkanie.Nr_Domu=29; printf("%d %d\n", LISTA[1].Wiek, LISTA[1].Mieszkanie.Nr_Domu); return 0; }

56 Unie Unie to kolejny sposób prezentacji danych w pamięci. Na pierwszy rzut oka wyglądają bardzo podobnie do struktur union Nazwa{ typ1 nazwa1; typ2 nazwa2; /*... */ }; Przykład: union LiczbaLubZnak{ int calkowita; char znak; double rzeczywista; };

57 Unie Pola w unii nakładają się na siebie w ten sposób, że w danej chwili można w niej przechowywać wartość tylko jednego typu. Unia zajmuje w pamięci tyle miejsca, ile zajmuje największa z jej składowych. W powyższym przypadku unia będzie miała prawdopodobnie rozmiar typu double czyli często 64 bity, a liczba całkowita i znak będą wskazywały odpowiednio na pierwsze cztery bajty lub na pierwszy bajt unii (choć nie musi tak być zawsze). Dlaczego tak? Taka forma często przydaje się np. do konwersji pomiędzy różnymi typami danych. Możemy dzięki unii podzielić zmienną 32-bitową na cztery składowe zmienne o długości 8 bitów każda. Do konkretnych wartości pól unii odwołujemy się przy pomocy operatora wyboru składnika – kropki. Zazwyczaj użycie unii ma na celu zmniejszenie zapotrzebowania na pamięć, gdy naraz będzie wykorzystywane tylko jedno pole i jest często łączone z użyciem struktur.

58 #include /*Deklaracja zmiennej przechowujacej liczbe calkowita lub rzeczywista (ale nie obydwie)*/ union value { long int i_value; /* Liczba rzeczywista */ float f_value; /* Liczba zmiennoprzecinkowa */ } data; int i; /* Losowa liczba calkowita */ float f; /* Losowa liczba zmiennoprzecinkowa */ int main() { data.f_value = 5.0; data.i_value = 3; /* nadpisana wartosc data.f_value */ printf("%li \t %f \n", data.i_value, data.f_value); i = data.i_value; /* prawidlowo */ f = data.f_value; /* nieprawidlowo, wywola nieprzewidywalne wyniki */ printf("%li \t %f \n", i, f); data.f_value = 5.5; /* przypisanie jakiejs wartosci f-value/i-value */ f = data.f_value; i = data.i_value; /* nieprawidlowo, wywola nieprzewidywalne wyniki */ printf("%li \t %f \n", i, f); return(0);}

59 Pola bitowe Struktury mają pewne dodatkowe możliwości w stosunku do zmiennych. Mowa tutaj o rozmiarze elementu struktury. W przeciwieństwie do zmiennej może on mieć nawet 1 bit!. Aby móc zdefiniować taką zmienną musimy użyć tzw. pola bitowego. struct moja{ unsigned inta1:4, /* 4 bity * (0-15)/ a2:8, /* 8 bitów (często 1 bajt) * (0-255)/ a3:1, /* 1 bit * 0 lub 1/ a4:3; /* 3 bity * (0-7)/ }; Wszystkie pola tej struktury mają w sumie rozmiar 16 bitów, jednak możemy odwoływać się do nich w taki sam sposób, jak do innych elementów struktury. W ten sposób efektywniej wykorzystujemy pamięć, jednak istnieją pewne zjawiska, których musimy być świadomi przy stosowaniu pól bitowych. Pola bitowe znalazły zastosowanie głównie w implementacjach protokołów sieciowych.

60 #include int main() { struct USC { int Sex : 1; unsigned Wiek : 8; unsigned Dzieci : 4; unsigned Ktora : 3; } Facet; int bufor; system("clear"); Facet.Sex = 0; printf("\n Ile ma lat ? : "); scanf("%d", &bufor); Facet.Wiek = bufor; printf("\n Ktore malzenstwo ? : "); scanf("%d", &bufor); Facet.Ktora = bufor; printf("\n Ile dzieci ? : "); scanf("%d", &bufor); Facet.Dzieci = bufor; printf("\n\n"); if (Facet.Ktora) printf("Facet ma %d zone", Facet.Ktora); printf("\nPlec: Dzieci: Wiek (lat): \n\n"); printf("%d\t%d\t%d\n", Facet.Sex, Facet.Dzieci, Facet.Wiek); return 0; }

61 stdio.h fclose() – funkcja zamyka otwarty funkcją fopen() plik. Jeśli plik nie zostanie zamknięty, a program zakończy działanie, zmiany nie zostaną zapisane. Funkcja zwraca 0, a w przypadku błędu EOF. int fclose (FILE *plik); feof() – funkcja zwraca wartość niezerową jeżeli napotka koniec pliku tekstowego. int feof(FILE *stream); fflush() – funkcja zapisuje dane znajdujące się w buforach obsługi podanego pliku. Plik pozostaje nadal otwarty. Funkcja fflush zwraca wartość 0 w przypadku wywołania zakończonego sukcesem lub wartość EOF, jeśli wystąpił błąd. int fflush(FILE * stream); fgetpos() – funkcja umieszcza w pos aktualną pozycję wskaźnika do pliku file. Zero gdy funkcja wykonała się pomyślnie, EOF w przypadku wystąpienia błędu, kod błędu umieszczany jest w zmiennej globalnej errno. int fgetpos (FILE* file, fpos_t* pos);

62 stdio.h fgets() – funkcja czyta kolejne znaki ze strumienia stream (usuwa je stamtąd) i umieszcza je w tablicy znakowej wskazywanej przez str. Czytanie przerywa, gdy przeczyta size - 1 znaków, natrafi na koniec pliku lub znak końca linii (znak ten jest zapisywany do str). Na końcu fgets() dopisuje znak '\0'. Wartością funkcji fgets(str, size, stream) jest str w przypadku sukcesu. W przypadku błędu lub natrafienia na koniec pliku przed przeczytaniem jakiegokolwiek znaku wartością funkcji jest NULL. Funkcja fgets() nie odróżnia sytuacji osiągnięcia końca pliku od błędu odczytu pliku. Jeśli potrzebne jest ich rozróżnienie użyj funkcji feof() lub ferror(). char *fgets(char *str, int size, FILE *stream); fread() – funkcja kopiuje nitems elementów z podanego pliku do tablicy. Kopiowanie kończy się w przypadku wystąpienia błędu, końca pliku lub po skopiowaniu podanej liczby elementów. Wskaźnik pliku jest przesuwany, tak by wskazywał pierwszy nieodczytany element. Wartość zwracana to liczba faktycznie wczytanych elementów. ptr – wskaźnik na tablicę, size - rozmiar elementu tablicy, nitems - liczba elementów do odczytania, stream - plik, na którym wykonywana jest operacja size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

63 stdio.h fseek() - funkcja ustawia pozycję w pliku file na offset w zależnośći od wartości argumentu mode. Jeśli mode jest równy zero, to offset liczony jest od początku. Jeśli 1, to offset przesuwany od aktualnej pozycji, a 2 przesuwany o offset od końca pliku (wskaźnik pliku jest przesuwany do pozycji będącej sumą rozmiaru pliku i parametru offset). Zwraca zero, a w przypadku błędu wartość niezerową. int fseek(FILE *file, long offset, int mode); fsetpos() - funkcja zmienia aktualną pozycję wskaźnika do pliku file na pos. Zwraca zero gdy funkcja wykonała się pomyślnie, EOF w przypadku wystąpienia błędu, kod błędu umieszczany jest w zmiennej globalnej errno. int fsetpos (FILE* file, fpos_t* pos); ftell() - funkcja zwraca aktualną pozycję wskaźnika pliku. long ftell(FILE *file);

64 stdio.h fwrite() - funkcja kopiuje nitems elementów z poddanej tablicy do pliku. Kopiowanie kończy się w przypadku wystąpienia błędu lub po skopiowaniu podanej liczby elementów. Wskaźnik pliku jest przesuwany, tak by wskazywał pierwszy element po ostatnim zapisanym. Zwraca jest liczba faktycznie zapisanych elementów. ptr – wskaźnik na tablicę, size - rozmiar elementu tablicy, nitems - liczba elementów do odczytania, stream - plik, na którym wykonywana jest operacja size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream); getchar() - funkcja czyta znak ze standardowego wejścia i go stamtąd usuwa. Wywołanie getchar() jest równoważne wywołaniu getc(stdin). Funkcja getchar() zwraca kod pierwszego znaku ze standardowego wejścia traktowany jako unsigned char przekształcony do typu int. W przypadku końca pliku lub błędu funkcja zwraca wartość EOF. int getchar(void); gets() - Funkcja gets() czyta linię ze standardowego wejścia (usuwa ją stamtąd) i umieszcza ją w tablicy znakowej wskazywanej przez str. Ostatni znak linii (znak nowego wiersza - '\n') zastępuje zerem (znakiem '\0'). Wartością funkcji jest str w przypadku sukcesu lub NULL w przypadku błędu lub natrafienia na koniec pliku. Funkcja nie sprawdza, czy jest miejsce do zapisu w tablicy str. char *gets(char *str);

65 stdio.h perror() - Wypisuje zrozumiały komunikat o błędzie. Jeśli argumentem jest NULL, wypisuje na stderr tekstowy opis błędu, opierajac się na wartości zmiennej errno. Jeśli argumentem jest niepusty napis, napisze go najpierw, dodając dwukropek. Po wypisaniu komunikatu perror przechodzi do następnej linii. void perror(const char *string); putchar() - funkcja wysyła znak na standardowe wyjście. Wywołanie putchar (c) jest równoważne wywołaniu putc(c, stdout). Funkcja putchar() zwraca kod znaku traktowany jako unsigned char przekształcony do typu int. W przypadku błędu funkcja zwraca wartość EOF. int putchar(int c); puts() - funkcja wysyła na standardowe wyjście napis s, a następnie znak nowej linii. Funkcja zwraca liczbę nieujemną w przypadku sukcesu. W przypadku błędu zwraca wartość EOF. int puts(const char *s);

66 stdio.h remove() - funkcja usuwa podaną nazwę z systemu plików. Przy usuwaniu plików wywołuje funkcję unlink, natomiast przy usuwaniu katalogu używa funkcję rmdir. Zwraca 0 gdy funkcja zakończyła się poprawnie lub -1 w przypadku błędu. int remove (const char *name); rewind() - funkcja 'przewija' plik do początku. Jest równoważna wywołaniu funkcji fseek(file, 0, 0). void rewind(FILE *file); ungetc() - funkcja zwraca znak c z powrotem do strumienia stream. Przy najbliższej operacji czytania z tego strumienia znak pojawi się ponownie, jako pierwszy. Zwracany znak jest przekształcany do typu unsigned char; nie można zwrócić w ten sposób znacznika końca pliku (EOF). Dla każdego strumienia dopuszczalne jest zwrócenie z powrotem tylko jednego znaku. Wartość zwracana przez funkcję to wycofany znak w razie powodzenia lub EOF w razie błędu. int ungetc( int c, FILE *stream );

67 stdlib.h abort() - powoduje zamknięcie programu z powodu poważnego błędu. W systemach UNIX wywoływana jest funkcja raise(SIGABRT), co powoduje wyjście z programu z kodem -1 i wypisanie stanu rejestrów procesora. void abort(void); abs() - zwraca wartość bezwzględną liczby całkowitej. int abs(int); atexit() - sprawia, że podana jako parametr funkcja będzie wywołana w chwili, gdy program zakończy działanie. Zwraca wartość 0, gdy wywołanie funkcji zakończy sie pomyślnie, w innym przypadku zwraca wartość niezerową. Funkcja nie ustawia wartości errno. int atexit(void (*funkcja)(void)); div() - funkcja zwraca w strukturze div_t wynik dzielenia zmiennej numer przez zmienną denom. Struktura div_t składa się z dwóch pól typu int: quot i rem. Zwracana jest struktura div_t. div_t div (int numer, int denom);

68 stdlib.h atof(), atol() - funkcja jako argument pobiera liczbę w postaci ciągu znaków ASCII, a następnie zwraca jej wartość w formacie double. Liczbę może poprzedzać dowolna ilość białych znaków (spacje, tabulatory, itp.), oraz jej znak (plus (+) lub minus (-)). Funkcja atof() kończy wczytywać znaki w momencie napotkania jakiegokolwiek znaku który nie jest cyfrą, bądź znakiem e, lub E. Zwracana jest przekształcona liczba, a w przypadku gdy ciąg nie zawiera cyfr zwracana jest wartość 0. Znak musi bezpośrednio poprzedzać liczbę, czyli możliwy jest zapis "-2.333", natomiast próba potraktowania funkcją atof ciągu "- 2.333" skutkuje zwracaną wartością 0. double atof ( const char* string ); long atol(const char* string); atoi() - funkcja jako argument pobiera liczbę w postaci ciągu znaków ASCII, a następnie zwraca jej wartość w formacie int. Liczbę może poprzedzać dowolona ilość białych znaków (spacje, tabulatory, itp.), oraz jej znak (plus (+) lub minus (-)). Funkcja atoi() kończy wczytywać znaki w momencie napotkania jakiegokowiek znaku który nie jest cyfrą. W przypadku gdy ciąg nie zawiera cyfr zwracana jest wartość 0. Znak musi bezpośrednio poprzedzać liczbę, czyli możliwy jest zapis "-2", natomiast próba potraktowania funkcją atoi ciągu "- 2" skutkuje zwracaną wartością 0. int atoi ( const char * string );

69 stdlib.h exit() - kończy działanie programu i zwraca kod wyjścia. Wcześniej wypisywana jest zawartość strumieni wyjściowych i zamykane są wszelkie zasoby z jakich korzystał program (np. pamięć). status - kod wyjścia z programu, argument ten może posiadać wartość 0 lub EXIT_SUCCESS w przypadku pozytywnego zakończenia działania programu, w przeciwnym wypadku może zwracać EXIT_FAILURE lub dowolną wartość, z tym że liczy się ostatnie 8 najmniej znaczących bitów. void exit(int status); system() - powoduje wywołanie w powłoce polecenia command. int system (const char* command);

70 stdlib.h calloc() - funkcja przydziela pamięć dla nmeb elementów o rozmiarze size każdy i zeruje przydzieloną pamięć. malloc() - funkcja przydziela pamięć o wielkości size bajtów. realloc() - funkcja zmienia rozmiar przydzielonego wcześniej bloku pamięci wskazywanego przez ptr do size bajtów. Pierwsze n bajtów bloku nie ulegnie zmianie gdzie n jest minimum z rozmiaru starego bloku i size. Jeżeli ptr jest równy zero (tj. NULL), funkcja zachowuje się tak samo jako malloc. free() - funkcja zwalnia blok pamięci wskazywany przez ptr wcześniej przydzielony przez jedną z funkcji malloc, calloc lub realloc. Jeżeli ptr ma wartość NULL funkcja nie robi nic. nmeb - liczba elementów, dla których ma być przydzielona pamięć, size - rozmiar (w bajtach) pamięci do zarezerwowania bądź rozmiar pojedynczego elementu, ptr - wskaźnik zwrócony przez poprzednie wywołanie jednej z funkcji lub NULL void *calloc(size_t nmeb, size_t size); void *malloc(size_t size); void free(void *ptr); void *realloc(void *ptr, size_t size);

71 stdlib.h Jeżeli przydzielanie pamięci się powiodło, funkcje calloc, malloc i realloc zwracają wskaźnik do nowo przydzielonego bloku pamięci. W przypadku funkcji realloc może to być wartość inna niż ptr. Jeśli jako size, nmeb podano zero, zwracany jest albo wskaźnik NULL albo prawidłowy wskaźnik, który można podać do funkcji free (zauważmy, że NULL jest też prawidłowym argumentem free). Jeśli działanie funkcji nie powiedzie się, zwracany jest NULL i odpowiedni kod błędu jest wpisywany do zmiennej errno. Dzieje się tak zazwyczaj, gdy nie ma wystarczająco dużo miejsca w pamięci.

72 stdlib.h rand() - funkcja zwraca kolejną liczbę pseudolosową. Aby ustawić zarodek ciągu liczb pseudolosowych, należy posłużyć się funkcją srand. Aby otrzymać liczbę z mniejszego przedziału, należy posłużyć się operatorem modulo (%) lub operacjami na liczbach rzeczywistych. Liczba pseudolosowa z przedziału od 0 do RAND_MAX (które ma wartość co najmniej 32767). int rand(void); Użycie operacji na liczbach rzeczywistych jest często sugerowane, gdyż w przeciwieństwie do operacji modulo bierze pod uwagę bardziej znaczące bity wygenerowanej liczby, które teoretycznie są bardziej losowe od bitów mniej znaczących. Istotnie może to być prawdą, jednak nie ma to i tak większego znaczenia, gdyż jeżeli zależy nam na dużej losowości generatora powinniśmy w programie użyć innej implementacji generatora. Generalnie generator z biblioteki standardowej nie nadaje się do bardzo poważnych zastosowań. Należy pamiętać, że jeżeli górny zakres do którego losujemy jest bliski wartości RAND_MAX to liczby nie będą miały równomiernego rozkładu prawdopodobieństwa. Jest to prawdą dla każdej granicy, która nie jest dzielnikiem RAND_MAX+1, jednak przy małych wartościach niedokładność jest pomijalna.

73 stdlib.h srand() - funkcja inicjuje generator liczb pseudolosowych podanym w argumencie zarodkiem (ang. seed). Aby sprawić, by za każdym uruchomieniem programu zarodek liczb pseudolosowych był inny, można funkcję srand wywołać z argumentem time(0). void srand(int zarodek); Przykład: #include int main() { srand(0); printf("Pierwsza liczba pseudolosowa dla zarodka równego zero to: %d", rand()); return 0; }

74 stdlib.h Przykład: #include int main() { int i; srand(time(0)); for(i=0; i

75 string.h memchr(), memrchr() - funkcja memchr() skanuje pierwsze n bajtów obszaru pamięci wskazywanego przez s w poszukiwaniu znaku c. Pierwszy bajt pasujący do c (interpretowany jako typ unsigned char) przerywa szukanie. Funkcja memrchr() jest podobna do funkcji memchr(), z tym wyjątkiem, że poszukuje wstecz od końca n bajtów wskazywanych przez s, zamiast do przodu, od początku. Funkcje memchr() i memrchr() zwracają wskaźnik do pasującego bajtu lub NULL jeżeli znak nie został znaleziony w podanym obszarze pamięci. void *memchr(const void *s, int c, size_t n); void *memrchr(const void *s, int c, size_t n); memcmp() - porównuje obszary pamięci. Funkcja porównuje pierwsze n bajtów obszarów pamięci s1 i s2. Zwraca liczbę całkowitą mniejszą od, równą, lub większą od zera jeżeli s1 jest odpowiednio mniejszy niż, równy, lub większy niż s2. int memcmp(const void *s1, const void *s2, size_t n);

76 string.h memcpy() - funkcja kopiuje size (liczba bajtów do skopiowania) bajtów z obiektu source (wskaźnik do obiektu źródłowego) do obiektu dest (wskaźnik do obiektu docelowego). Funkcja zwraca wskaźnik na dest. Obiekt dest powinien mieć zaalokowane dostatecznie dużo pamięci, aby móc pomieścić obiekt source, ponieważ może dojść do przepełnienia bufora. void *memcpy (void* dest, const void* src, size_t size); Przykład: #include int main (void) { char strTo[30]; char *strFrom = "Ala ma kota"; memcpy (strTo, strFrom, 12); printf("%s", strTo); }

77 string.h memset() - wypełnia kolejne bajty w pamięci ustaloną wartością. buffer - adres początkowy, c - wpisywana wartość (dla napisu - numer znaku), num - ile bajtów zapisać. void * memset ( void * buffer, int c, size_t num ); Przykład: #include int main() { char napis[] = "zamazujemy napis"; memset(napis, '*', 10); printf("%s\n", napis); return 0;}

78 string.h strcat(), strncat() - funkcja dopisuje tekst z tablicy strFrom (wskaźnik do źródłowej tablicy znaków) na koniec tekstu w tablicy strTo (wskaźnik do docelowej tablicy znaków) lub tylko n znaków. Funkcja zwraca wskaźnik na strTo. Tablica strTo powinna być dostatecznie duża, aby pomieścić dodany tekst z strFrom, ponieważ może dojść do przepełnienia bufora. char *strcat (char* strTo, const char* strFrom); Przykład: #include int main (void) { char strTo[30] = "Ala "; char *strFrom = "ma kota"; strcat (strTo, strFrom); printf("%s", strTo); }

79 string.h strchr(), strrchr() - lokalizuje znak w ciągu znaków. Funkcja strchr() zwraca wskaźnik do pierwszego wystąpienia znaku c (poszukiwany znak) w łańcuchu znaków s (przeszukiwany łańcuch). Funkcja strrchr() zwraca wskaźnik do ostatniego wystąpienia znaku c w łańcuchu znaków s. "Znak" oznacza tutaj "bajt" - funkcje te nie działają ze znakami wielobajtowymi. Funkcje strchr() i strrchr() zwracają wskaźnik do pasującego znaku lub NULL jeśli znaku nie znaleziono. char *strchr(const char *s, int c); char *strrchr(const char *s, int c); strcmp(), strncmp() - funkcja porównuje napisy s1 i s2 lub pierwsze n znaków napisów. Funkcja zwraca liczbę mniejszą od zera, gdy s1 s2. int strcmp(const char *s1, const char *s2);

80 string.h strcpy(), strncpy() - funkcja kopiuje tekst z tablicy strFrom (wskaźnik do źródłowej tablicy znaków) do tablicy strTo (wskaźnik do docelowej tablicy znaków) lub tylko n znaków. Funkcja kopiuje znak po znaku od początku, aż do końca tablicy lub znaku '\0', który też kopiuje. Funkcja zwraca wskaźnik na strTo. Tablica strTo powinna być dostatecznie duża, aby pomieścić tekst z strFrom, ponieważ może dojść do przepełnienia bufora. char *strcpy (char* strTo, const char* strFrom); Przykład: #include int main (void) { char strTo[30]; char *strFrom = "Ala ma kota"; /* tekst krótszy niż 30 znaków */ strcpy (strTo, strFrom); printf("%s", strTo); }

81 string.h strcspn() - funkcja zlicza od początku ilość znaków w łańcuchu s (łańcuch znaków) które nie należą do niepasujace (tablica znaków które zliczamy) i zatrzymuje się na pierwszym pasującym którego nie liczy. Ilość zliczonych znaków jest zwracana. size_t strcspn(const char *s, const char *niepasujace); strerror() - funkcja interpretuje wartość errnum (numer błędu) i zwraca wskaźnik do tablicy zawierającej słowny opis tego błędu. char * strerror(int errnum); strlen() - funkcja oblicza długość łańcucha str nie wliczając znaku '\0'. Zwracana jest długość łańcucha str. int strlen (char *str); Przykład: #include int main(){char tab[80]; int dl; printf("Podaj swoje imie: "); scanf("%s", tab); dl=strlen(tab); printf("Twoje imie sklada sie z %d znakow\n", dl); return 0; }

82 string.h strspn() - funkcja zlicza od początku ilość znaków w łańcuchu s które należą do pasujace (tablica znaków które zliczamy) i zatrzymuje się na pierwszym nie pasującym którego nie liczy. Ilość zliczonych znaków jest zwracana. size_t strspn(const char *s, const char *pasujace); strtok() - "Słowo" jest to niepusty ciąg znaków, które nie występują w łańcuchu delim, poprzedzony znakiem \0 lub znakiem występującym w delim. Funkcja strtok() służy do rozkładania ciągu znaków s na słowa. Pierwsze odwołanie do strtok() powinno posiadać s jako pierwszy argument. Następne wywołania powinny mieć jako pierwszy argument NULL. Każde wywołanie zwraca wskaźnik do następnego słowa lub NULL, gdy nie ma już więcej słów. Jeśli słowo kończy się separatorem (delim), to ten kończący znak jest nadpisywany przez \0 i zapamiętywany jest wskaźnik do następnego znaku dla następnego wywołania strtok. Ciąg separatorów delim może być inny dla każdego wywołania. Funkcja strtok_r() działa tak samo, jak strtok(), ale zamiast korzystać ze statycznego bufora, korzysta ze wskaźnika do przydzielonego przez użytkownika wskaźnika char*. Wskaźnik ten, parametr ptrptr, nie może zostać zmieniony podczas rozkładania jednego łańcucha. char *strtok(char *s, const char *delim); char *strtok_r(char *s, const char *delim, char **ptrptr);

83 math.h acosh(), acos(), asinh(), asin(), atan2(), atanh(), atan(), cbrt(), ceil(), copysign() cosh(), cos(), double_t(), erfc(), erf(), exp2(), expm1(), exp(), fabs(), fdim(), float_t(), floor(), fmax(), fma(), fmin(), fmod(), fpclassify(), frexp(), hypot(), ilogb(), isfinite(), isgreaterequal(), isgreater(), isinf(), islessequal(), islessgreater(), isless(), isnan(), isnormal(), isunordered(), ldexp(), lgamma(), llrint(), llround(), log1p(), log2(), logb(), log10(), log(), lrint(), lround(), modf(), nan(), nearbyint(), nextafter(), nexttoward(), pow(), remainder(), remquo(), rint(), round(), scalbln(), scalbn(), signbit(), sinh(), sin(), sqrt(), tanh(), tan(), tgamma(), trunc()