2. Biblioteka C. Moze na poczatek taka uwaga: w Turbo C mozna ustawic kursor gdzies gdzie nie ma nic znanego kompilatorowi, wcisnac Ctrl-F1, i wtedy zapyta, czy chce sie "keywords", czy "header files". To drugie zawiera informacje o calej bibliotece. Dlatego omowione tu beda dokladniej tylko niektore czesci - reszte mozna doczytac w helpie. 2.1. Standardowe wejscie/wyjscie. Definicje do standardowego wejscia/wyjscia sa zawarte w pliku stdio.h. Z nich byly juz omowione funkcje formatujace wyjscie [v][f|s]printf i deformatujace wejscie [v][f|s]scanf. Uzywaja one - poza [v]sprintf i [v]sscanf, ktore dzialaja na tablicach typu char - zmiennej typu FILE, przekazywanej przez wskaznik (typu FILE*; dostep jest tylko przez wskaznik) opisujacej otwarty plik. Na poczatku program ma zdefiniowane i otwarte: stdin - standardowe wejscie danych, stdout - standardowe wyjscie danych, stderr - standardowe wyjscie do sygnalizacji bledow, stdprn - standardowe wyjscie do drukowania, stdaux - standardowe wejscie/wyjscie szeregowe. Jezeli ktores z nich nie jest potrzebne, mozna zamknac je na poczatku - to moze miec sens, jesli potrzeba otwierac wiele plikow, i moglaby zostac przekroczona maksymalna ich ilosc. Do otwierania plikow sluza funkcje (typ wyniku FILE*): fopen(char *nazwa, char *mod) - normalne otwieranie pliku, mod moze miec wartosci "r" - do czytania, "r+" - do czytania i/lub modyfikacji, "w" - do pisania, "w+" - do pisania z mozliwoscia pozniejszego czytania, "a" - do pisania na koncu pliku, "a+" - z mozliwoscia czytania, mozna na koncu mod dodac b, zeby plik byl binarny, albo t zeby byl tekstowy; freopen(char *nazwa, char *mod, FILE *oldfile) - ta forma zamyka oldfile, i otwiera nowy plik, uzywajac tego samej zmiennej, skutek jest taki ze dalsze odwolania uzywajace niezmienionego wskaznika czytaja badz pisza nowy plik; fdopen(int uchwyt, char *mod) - otwiera plik do uchwytu - taki uchwyt opisuje otwarty plik na nizszym poziomie, i musi miec dostep zgodny z podamym modem, otrzymuje sie go zwykle przez funkcje z systemowego wejscia/wyjscia (opisane w io.h). tmpfile(void) - otwiera plik tymczasowy, do skasowania przy zamykaniu, zawsze binarny (mod="w+b"); a do zamykania: fclose(FILE *file) i fcloseall(void) - ta druga zamyka wszystkie otwarte pliki opisane strukturami FILE. Uchwyt dla pliku mozna otrzymac z funkcji: int fileno(FILE *file). Opisane ponizej operacje zwykle uzywaja bufora (jest to bufor przypisany do pliku, nie mylic z buforem do ktorego czyta sie dane). Jego dlugosc jest zwykle 512 bajtow (stala BUFSIZ), mozna zazadac uzywania podanej tablicy jako bufora funkcja void setbuf(FILE *file, char *buf) jesli jako buf przekaze sie NULL operacje beda niebuforowane, mozna tez ustawic wiekszy bufor funkcja int setvbuf(FILE *file, char *buf, int rozm_elem, int ile_elem) (wynik niezerowy sygnalizuje blad). Nieformatowane operacje wejscia: int [f]getc(FILE *file) - czyta znak z pliku; int [f]getchar(void) - czyta znak z stdin (dla obu powyzej wersja z f wola funkcje, bez f makro); int getw(FILE *file) - czyta 2 znaki z file; char *gets(char *bufor) - czyta linie z stdin do bufora, konczy na \n (tego juz nie), bez limitu dlugosci, wynik=bufor (jesli jest blad, lub EOF, to wynik jest NULL = (char*)0); char *fgets(char *bufor, int dlugosc, FILE *file) - czyta linie z file do \n (z nim) lub dlugosc-1 znakow (1 znak na 0); int ungetc(int c,FILE *file) - cofa czytanie o 1 znak (wynik= przekazany znak) - nastepny getc zwroci ten znak; int fread(void *bufor, rozmiar_elem, ile_elementow, FILE *file) - wynik=ilosc elementow przeczytanych, -1 jezeli jest blad. Nieformatowane operacje wyjscia: int [f]putc(int c, FILE *file) - wypisuje znak, wynikiem jest wypisany znak (EOF w razie bledu); int [f]putchar(int c) - pisze znak na stdout; (dla obu powyzej wersja z f wola funkcje, bez f makro); int putw(int w, FILE *file) - wypisuje dwa znaki, wynik=w; puts(char *bufor) - wypisuje linie na stdout, wynik=ostatni wypisany znak, EOF w razie bledu, dodaje \n na koncu linii; fputs(char *bufor, FILE *file) - wypisuje linie na file, nie dodaje \n, wynik jak dla puts(); int fwrite(void *bufor, rozmiar_elem, ile_elementow, FILE *file) - wynik=ilosc elementow zapisanych, -1 jezeli jest blad. Operacje ustawiania i odczytywania pozycji pliku: int rewind(FILE *file) - ustawianie na poczatek pliku int fgetpos(FILE *file, fpos_t *pos) - odczytywanie int fsetpos(FILE *file, fpos_t *pos) - ustawianie int fseek(FILE *file, long zmiana, int pozycja) - ustawianie, jako pozycja moze byc SEEK_SET (poczatek), SEEK_END (koniec), SEEK_CUR (aktualna), i zmiana dodaje sie do tej pozycji; (dla powyzszych wynik jest 0 jesli nie ma bledu) long ftell(FILE *file) - podaje aktualna pozycje, -1L jak blad. Inne operacje: int feof(FILE *file) - niezero jesli probowano przeczytac EOF; int ferror(FILE *file) - niezero jesli blad (EOF to nie blad); void clearerr(FILE *file) - kasuje stany blad i EOF; int fflush((FILE *file) - czysci bufor pliku (wypisuje na dysk); int flushall(void) - czysci bufory wszystkich plikow, zwraca ilosc otwartych plikow; void perror(char *napis) - pisze na stderr napis: opis bledu\n; int remove/unlink(char *nazwa_pliku) - kasuje ten plik int rename(char *s_nazwa,char *n_nazwa) - zmienia nazwe pliku; char *strerror(int errnum) - opis bledu numer errnum; char *tmpnam(char *bufor) - tworzy nazwe pliku tymczasowego, jako bufor mozna podac NULL - wtedy uzyje wlasnego bufora. 2.1. Wejscie/wyjscie "ekranowe" - wybrane funkcje. Definicje sa zawarte w conio.h, i jest to pakiet dostepny tylko w DOS-ie na PC. Mozna w nim ustawic parametry "okna" (fragmentu ekranu), i wtedy wszystkie operacje beda dotyczyc tylko tego okna (np. przewijanie tekstu, czyszczenie ekranu), i polozenie na ekranie bedzie liczone wzgledem okna. To okno definiuje sie funkcja window(x0,y0,x1,y1), ale zeby zaczelo dzialac trzeba jeszcze potem wejsc do niego przez gotoxy(x,y), wspolrzedne juz wedlug nowego okna. Aktualne wartosci wspolrzednych zwracaja funkcje wherex() i wherey(). Czyszczenie ekranu clrscr(), linii (do konca) clreol(). Mozna zapisac kawalek ekranu do pamieci funkcja gettext(x0,y0,x1,y1,char *buf), rozmiar buf ma byc 2*(x1-x0+1)*(y1-y0+1) (2 bajty na znak ekranu), i potem wypisac go z powrotem na ekran funkcja puttext (takie same parametry). I sa delline() i insline() do kasowania i wstawianie linii. Przy pisaniu na ekran trzeba zwrocic uwage na to, ze \n nie jest zamieniany na \r\n - przesuwa kursor do nastepnej linii, ale nie na poczatek, a po prostu pionowo w dol. Do pisania sluza funkcje putch(c), cputs(char *s), cprintf(char *format...), dzialajace analogicznie jak putchar, puts, printf - tylko znacznie szybciej, zwlaszcza jezeli nie wyzeruje sie zmiennej directvideo. Za to z czytaniem sporo klopotow. Do czytania znaku sa getch() i getche() - ta druga funkcja daje echo, pierwsza nie. Czasem chce sie wiedziec, czy mozna czytac z klawiatury, czy tez bedzie sie czekac - kbhit() zwraca niezero jesli mozna cos przeczytac. Jesli wartoscia przeczytana jest zero, to zostal wcisniety jakis klawisz specjalny (np. F1-F12), albo z Alt, i trzeba przeczytac nastepny znak uzywajac getch() - wartosc podaje kod skanowania tego klawisza. Funkcji cscanf() i cgets() lepiej nie uzywac. Do czytania napisu bez echa jest getpass(char *prompt) - po to, zeby wczytywac haslo nie pokazujac go na ekranie. Mozna "cofnac" czytanie o 1 znak przez ungetch(c), tylko (char)c nie moze byc 0. Znaki na ekranie moga miec atrybuty (kolor znaku i tla), mozna to ustawiac funkcjami lowvideo(), normvideo(), highvideo() - jasnosc, lub textcolor(c), textbackground(c) - kolory tekstu i tla, kazdy z osobna - lub textattr(c) - oba razem. Do ustawiania pozycji na ekranie jest juz wspomniana gotoxy(x,y). Szczegolowe informacje o aktualnych ustawieniach mozna uzyskac przez gettextinfo(...). A z uzywaniem textmode(mod) lepiej zachowac ostroznosc. 2.3. Podstawowe operacje na napisach (i pamieci). Definicje sa zawarte w string.h. Do kopiowania sa funkcje char *str[n]cpy(char *dokad, char *skad [, int ilosc]); ilosc znakow podaje sie w wersji z n w nazwie; kopiowanie konczy sie na znaku \0 lub po osiagnieciu podanej ilosci - i wtedy nie dopisuje \0 na koncu; nie ma zabezpieczenia przed skopiowaniem do zbyt krotkiej tablicy wynikowej; jako wartosc zwraca adres dokad; jest tez stpcpy, ktory dziala tak samo, ale zwraca adres konca. Do porownywania sa: int str[n][i]cmp, takie same parametry (ilosc tylko jesli n w nazwie); i w nazwie powoduje ignorowanie roznicy miedzy malymi i duzymi literami; wartosc 0 oznacza "identyczne", <0 pierwszy mniejszy, >0 pierwszy wiekszy (jako signed char). Mozna dopisac do konca napisu przez str[n]cat - znow parametry takie same, ilosc podaje maksymalna dlugosc tego, co ma sie dopisac, nie calkowity rozmiar tego, co ma wyjsc. Dlugosc mozna otrzymac przez strlen(char *napis) - podaje gdzie jest to konczace zero; znalezc zadany znak w napisie mozna przez char *strchr(char *napis, int znak) - zwroci jego adres, lub NULL jesli tego znaku nie bedzie; podobny strrchr szuka od konca. Do szukania napisu jest char *strstr(char *w_czym, char czego). Mozna skopiowac przydzielajac na to pamiec - robi to funkcja char *strdup(char *napis) - tyle, ze po pierwsze trzeba ja zwracac jak kopia przestaje byc potrzebna, po drugie dostaje sie jej tylko tyle, ile zajmie kopia - nie mozna nic dopisac. Mozna zamienic wszystkie litery w napisie na male lub na duze - do tego sa strlwr(char *napis) i strupr, ich wynik=parametr. Sa jeszcze bardziej skomplikowane operacje: znajdowanie dlugosci kawalka zawierajacego wylacznie podane znaki, lub wylacznie znaki spoza podanych (strspn,strcspn), znajdowanie pierwszego znaku z podanego zestawu (strpbrk), i pare innych mniej uzytecznych. Oprocz zestawu "str" jest zestaw funkcji "mem", ktore roznia sie tym, ze nie uznaja \0 ani niczego innego za koniec, uzywaja wskaznikow void * (jest im wszystko jedno na co one pokazuja), i zawsze specyfikuja ilosc bajtow, poza tym sa analogiczne: memcpy (ma tez nazwe memmove), memchr, mem[i]cmp; memset(void *gdzie, int na_co, int ilosc) - zapisuje podana ilosc bajtow podana wartoscia (ma odpowiedniki str[n]set). Funkcje movmem i setmem roznia sie od memcpy i memset tylko kolejnoscia parametrow. Jest jeszcze memccpy, ktora kopiuje do podanego znaku, i jako wynik zwraca jego adres (NULL jak nie ma), i movedata, ktora ze wzgledu na sposob adresowania bedzie omowiona osobno. Caly ten zestaw ("mem") jest rowniez w mem.h. 2.4 O kilku innych pakietach. alloc.h - wszystkie funkcje zwiazane z przydzielaniem pamieci do zmiennych wskaznikowych i zwalnianiem jej; assert.h - zawiera jedna funkcje: void assert(int test); bios.h - funkcje odwolujace sie do BIOS-u PC; conio.h - we/wy klawiatura/ekran (*); ctype.h - zawiera definicje do klasyfikowania znakow (cyfra, cyfra hex, litera dowolna/mala/duza, sterujacy,...) i konwersji malych liter na duze lub duzych na male; dir.h - wszystko co laczy sie ze struktura katalogow na dysku i nazwami plikow (np. szukanie plikow w katalogu); dos.h - operacje i definicje specyficzne dla DOS-u na PC; float.h - funkcje do sterowania koprocesorem numerycznym; graphics.h - funkcje i definicje do modu graficznego na ekranie; io.h - funkcje do operacji we/wy uzywajacych uchwytow; math.h - funkcje matematyczne; mem.h - operacje na pamieci (kopiowanie, porownywanie) (*); process.h - wywolywanie i konczenie programow; setjmp.h - pozwala zapisac stan programu i do niego wrocic, mozna uzyc przy obsludze bledow, do multitaskingu; signal.h - podlaczanie procedur pod sygnaly o bledzie, i generowanie takich sygnalow; stdarg.h - definicje do obslugi zmiennych list parametrow; stdio.h - standardowe funkcje we/wy (*); stdlib.h - rozne funkcje (wiele jest gdzie indziej); string.h - operacje na tablicach znakow + mem.h (*); sys\stat.h - funkcje do informacji systemowych o otwartym pliku; time.h - wszystko co laczy sie z czasem i data; (*) oznacza, ze pakiet zostal juz omowiony.