|
Wyjście Spis treści Wstecz Dalej
Autor artykułu |
©2026 mgr Jerzy Wałaszek
|
Język C posiada wiele pożytecznych bibliotek, które zostały opracowane w celu ułatwienia programowania. Dostęp do funkcji tych bibliotek następuje po dołączeniu odpowiedniego pliku nagłówkowego, w którym znajdują się definicje struktur danych oraz funkcji danej biblioteki. Korzystaliśmy z tej opcji już wcześniej, używając dyrektywy preprocesora #include <stdio.h>. Dzięki niej mieliśmy dostęp do takich funkcji jak printf( ), scanf( ), puts( ), itp. Dlaczego warto korzystać z funkcji bibliotecznych? Odpowiedź jest prosta: bo są dostępne, wiec po co się męczyć i wymyślać koło od nowa. Drugi powód to taki, że funkcje biblioteczne są napisane profesjonalnie i dobrze przebadane. Jeśli używasz ich zgodnie z ich przeznaczeniem, to raczej nie powinieneś wpaść w kłopoty. A z funkcjami własnymi jest różnie. Czasem programiście coś umknie i program staje się niestabilny. Uwierz mi, poszukiwanie błędów w dużych programach jest ciężką, żmudną i niewdzięczną pracą. Jeśli się da, to lepiej jej unikać.
W środowisku kompilatorów C dla mikrokontrolerów AVR (Atmel) oraz PIC (Microchip) dostępny jest plik nagłówkowy string.h, który definiuje funkcje wspomagające przetwarzanie obszarów pamięci. Poniżej opiszemy podstawowe funkcje zdefiniowane w tym pliku i dotyczące pamięci (w rzeczywistości jest ich więcej, lecz nie wszystkie dostępne są w obu środowiskach).
Funkcja memset( ) (ang. memory set), wypełnia zadany obszar wybraną wartością. Składnia jest następująca:
Funkcja zwraca w wyniku adres wypełnionego obszaru.
Uruchom program:
Program tworzy tablicę znakową t o rozmiarze 10 znaków, po czym wypełnia ją liczbami -55. Na końcu zostaje wyświetlona zawartość tablicy.
Funkcję memset( ) wykorzystuje się najczęściej do szybkiego zerowania tablic. Jeśli tablica przechowuje dane innego typu niż char, to należy uwzględnić ich rozmiar:
Funkcja memcpy( ) (ang. memory copy) kopiuje zawartość jednego obszaru pamięci do drugiego. Oba obszary nie powinny się pokrywać. W przeciwnym razie może dojść do nadpisania danych (rozważ, co się stanie, jeśli kopiujesz dane z obszaru a do obszaru b, a obszar b pokrywa częściowo obszar a). Składnia jest następująca:
Funkcja zwraca adres przeznaczenia.
Uruchom program:
Program tworzy dwie tablice znakowe: s[ ] – 5-cio elementową i t[ ] – 9-cio elementową. Tablice są wstępnie wypełnione liczbami. Następnie program kopiuje zawartość tablicy s do tablicy t od pozycji elementu t[2].
Jeśli obszary zawierają elementy o rozmiarze innym niż 1 bajt, to należy to odpowiednio uwzględnić w ilości kopiowanych bajtów. Ten sam przykład dla liczb całkowitych:
Ostrożność należy zachować, jeśli kopiowane obszary pamięci pokrywają się częściowo. W takim przypadku wynik jest nieokreślony, ponieważ zależy od konkretnej implementacji funkcji memcpy( ).
Funkcja memmove( ) (ang. memory move) również kopiuje obszary pamięci, lecz w tym przypadku obszary te mogą na siebie częściowo zachodzić.
Uruchom program:
Program tworzy tablicę t z ustaloną zawartością. Następnie przenosi na początek fragment tej tablicy od komórki t[2] w górę.
Zmodyfikuj ten program, tak aby przenoszony fragment rozpoczynał się na początku tablicy i był przenoszony w obszar rozpoczynający się od komórki t[2]. Zwróć uwagę na rozmiar przenoszonego obszaru, który należy dobrać, tak aby program nie nadpisał danych umieszczonych w pamięci za ostatnią komórką tablicy.
Funkcja memchr( ) (ang. memory character) przeszukuje zadany obszar pamięci, szukając wystąpienia w nim bajtu o podanej wartości. Jeśli taki bajt znajdzie, to jest zwracany jego adres. Jeśli nie, to funkcja zwraca wskaźnik pusty NULL – w języku C adres NULL (czyli 0) nie wskazuje żadnego obiektu w pamięci komputera.
Uruchom program:
Funkcja memcmp( ) (ang. memory compare) porównuje ze sobą dwa obszary pamięci. Funkcja posiada następujące parametry:
Funkcja zwraca w wyniku:
Na przykład:
Uruchom program:
Tekst/łańcuch (ang. string) jest w języku C obszarem pamięci, w którym przechowuje się znaki. Na końcu tekstu wstawiany jest znak NUL o kodzie 0, który pełni funkcję znacznika końca tekstu. Teksty przechowujemy w tablicach znakowych. Tablica powinna posiadać wystarczająco duży rozmiar, aby pomieścić znaki łańcucha oraz kończący go znak NUL.
Stała łańcuchowa to tekst umieszczony w cudzysłowach:
Wartością tej stałej jest wskaźnik do obszaru, w którym umieszczone są znaki:
Ponieważ stała łańcuchowa daje w wyniku wskaźnik, to nie możemy przypisać ją do tablicy znakowej, np. tak:
Zamiarem programisty było tu wprowadzenie do tablicy tekstu podanego w cudzysłowach. Jednak to nie zadziała, ponieważ jest to próba przypisania nowego adresu wskaźnikowi t, a jak pamiętamy z rozdziału o wskaźnikach i tablicach, zmienna tablicy jest stałą, czyli elementem, który nie może zmieniać w programie swojej wartości. Poza tym, nawet gdyby to zadziałało, to tekst nie znalazłby się w tablicy. Jedynie jego adres zostałby przypisany zmiennej t. A nie o to chodziło. Zatem do umieszczenia tekstu w tablicy musimy skorzystać z odpowiedniej funkcji łańcuchowej, która zadanie to wykona jak należy.
Wyjątkiem jest inicjalizacja tablicy w momencie jej tworzenia, wtedy można zastosować konstrukcję:
Tekst zostanie umieszczony w tablicy, która otrzyma taki rozmiar, aby ten tekst pomieścić wraz z kończącym go znakiem NUL.
Funkcja strcpy( ) (ang. string copy) kopiuje łańcuch znakowy do tablicy znakowej. Kopiowane są wszystkie znaki łańcucha wraz z kończącym go znakiem NUL. Tablica powinna być odpowiednio duża, aby pomieścić cały łańcuch tekstowy wraz ze znakiem końca tekstu.
Funkcja zwraca w wyniku adres docelowy.
Funkcja strncpy( ) działa podobnie do poprzednio opisanej funkcji strcpy( ). Różnica jest taka, iż kopiuje co najwyżej zadaną liczbę znaków. Jednak musisz zwrócić uwagę na jedną ważną rzecz: Jeśli w n znakach kopiowanego łańcucha nie znajdzie się znak o kodzie 0, to nie będzie on umieszczony w tablicy docelowej. Musisz sam o to zadbać, przez wpisanie kodu 0 na pozycję za n pierwszymi znakami w tablicy.
Wynikiem funkcji jest adres docelowy.
W tym programie kopiujemy do tablicy t dłuższy łańcuch i nie umieszczamy na końcu znaku NUL. Za ostatnim znakiem na wydruku pojawią się śmieci z pamięci za tablicą.
Ten z kolei program robi to właściwie. Tekst w tablicy to pierwsze 6 znaków łańcucha plus znak NUL.
Funkcja strlen( ) (ang. string length) zwraca liczbę znaków, które zawiera podany łańcuch. Znak NUL nie jest wliczany.
| adres_łańcucha | – | wskaźnik pierwszego znaku łańcucha
tekstowego, którego liczbę znaków funkcja wylicza. |
Uruchom program:
Funkcja strcat( ) (ang. string concatenate) dołącza do końca jednego łańcucha tekstowego drugi. W efekcie powstaje łańcuch tekstowy zawierający tekst obu łańcuchów.
Funkcja zwraca adres docelowy. Obszar docelowy powinien być wystarczająco duży, aby pomieścić tekst obu łańcuchów oraz zamykający znak NUL.
Funkcja strncat( ) działa podobnie do strcat( ). Jednakże posiada dodatkowy parametr, który określa maksymalną liczbę znaków do dołączenia z drugiego łańcucha. Wynikowy łańcuch będzie zakończony znakiem NUL.
Funkcja zwraca adres docelowy.
Funkcja strchr( ) (ang. string character) szuka w podanym łańcuchu tekstowym pierwszego wystąpienia określonego znaku. Jeśli znak zostanie znaleziony, funkcja zwraca jego adres. Jeśli znaku nie ma w łańcuchu zwracany jest adres pusty (NULL).
Poniższy program demonstruje sposób używania funkcji strchr( ) do wyszukania wszystkich wystąpień litery 'e', która zostaje zastąpiona literą 'E':
W programie wykorzystujemy wskaźnik p, który przed pętlą ustawiamy na adres tablicy znakowej t, która przechowuje przeszukiwany łańcuch. Następnie w pętli wykonujemy poszukiwanie pierwszego wystąpienia litery 'e'. Gdy zostanie znaleziona, do wskaźnika p trafi jej adres. Zmieniamy wtedy znak 'e' na 'E', po czym jako nowy adres łańcucha przyjmujemy adres następnego znaku. Jeśli litery 'e' funkcja strchr( ) nie znajdzie w łańcuchu, to zwróci wskaźnik NULL. Instrukcja przypisania w warunku kontynuacji pętli będzie miała wartość 0, zatem pętla przestanie być wykonywana. Zwróć uwagę, że instrukcja ta jest ujęta w nawiasy. Jest to znak dla kompilatora, iż nie pomyliliśmy się i nie jest to test równości typu p == ..., lecz właśnie instrukcja przypisania. Spróbuj te nawiasy usunąć, a zobaczysz reakcję kompilatora. Dzięki takim konstrukcjom program w języku C staje się bardziej zwięzły i krótszy.
Funkcja strrchr( ) (ang. string right character) działa podobnie do strchr( ). Różnica polega na tym, iż znak jest wyszukiwany od końca łańcucha. Jeśli zostanie znaleziony, to funkcja zwraca jego adres. W przeciwnym razie zwraca wskaźnik pusty (NULL).
Poniższy program zamienia w ostatnim wyrazie litery małe na duże – postaraj się odkryć, jak to jest robione:
Funkcja strcmp( ) (ang. string compare) porównuje ze sobą dwa łańcuchy znakowe s1 i s2. Zwraca następujące wartości:
Funkcja posiada następującą składnię:
Uruchom program:
Funkcja strncmp( ) działa identycznie jak strcmp( ). Różnicą jest to, że porównanie dotyczy zadanej liczby początkowych znaków obu łańcuchów.
Uruchom program:
Funkcja strstr( ) (ang. string in string) zwraca adres pierwszego wystąpienia łańcucha s2 w łańcuchu s1. Jeśli łańcuch s2 nie występuje w s1, funkcja zwraca adres pusty (NULL).
Uruchom program:
Program wyszukuje w łańcuchu s1 wszystkie wystąpienia łańcucha s2 i zmienia w nich literki małe na duże. Postaraj się odkryć zasadę jego działania.
Funkcja strpbrk( ) (ang. string pointer break) zwraca adres pierwszego wystąpienia w łańcuchu s1 dowolnego ze znaków umieszczonych w łańcuchu s2. Jeśli żaden ze znaków w s2 nie pojawia się w s1, funkcja zwraca adres pusty.
Uruchom poniższy program, który w łańcuchu s zamienia wszystkie samogłoski małe na duże:
Funkcja strtok( ) (ang. string to keywords) rozbija łańcuch na poszczególne słowa, które mogą być oddzielone od siebie znakami separatorów. Składnia funkcji jest następująca:
Funkcja zwraca adres pierwszego znaku słowa lub NULL, jeśli brak dalszych słów w łańcuchu.
Aby poprawnie użyć tej funkcji, musisz zrozumieć sposób jej działania. W pierwszym wywołaniu podajemy w pierwszym argumencie adres łańcucha s, który chcemy rozbić na słowa. W drugim argumencie podajemy adres łańcucha ze znakami separującymi słowa. Funkcja znajduje pierwsze słowo, a znak separatora za tym słowem zastępuje znakiem NUL i zwraca jako wynik adres pierwszego znaku tego słowa. W kolejnych wywołaniach w pierwszym parametrze podajesz adres pusty NULL. Drugi parametr pozostaje bez zmian. Adres NULL jest informacją dla funkcji, aby w pierwotnym łańcuchu wyszukała następne słowo. Funkcja wyszukuje je i zwraca jego adres, a na końcu słowa jest umieszczany znak NUL, który zastępuje separator. Powtarzamy tę sekwencję aż do momentu, gdy funkcja zwróci adres NULL, co oznacza brak dalszych słów.
Uruchom program:
Nie ma funkcji standardowej, która usuwa z łańcucha znak. Jednak funkcję taką można łatwo napisać. Uruchom poniższy program:
Nie ma również funkcji, która wstawia do łańcucha nowy znak. Napiszemy sobie ją sami. Tablica przechowująca łańcuch musi być dostatecznie duża, aby pomieścić go po wstawieniu nowego znaku.
W ramach ćwiczeń napisz podobne funkcje:
Funkcje konwersji umożliwiają przetwarzanie wartości liczbowej na łańcuch tekstowy i na odwrót. Definicje funkcji znajdują się w pliku nagłówkowym stdlib.h.
Funkcja atoi( ) (ang. ASCII string to integer) oblicza wartość dziesiętną liczby całkowitej zapisanej w postaci znaków ASCII. Początkowe spacje są pomijane. Przed cyframi liczby może się znajdować znak + lub -. Wynik konwersji zwracany jest jako wartość typu int.
Jeśli tekstu nie da się zinterpretować jako liczbę całkowitą, funkcja zwraca wartość 0.
Funkcja atol( ) (ang. ASCII string to long integer) oblicza wartość dziesiętną liczby całkowitej zapisanej w postaci znaków ASCII. Początkowe spacje są pomijane. Przed cyframi liczby może się znajdować znak + lub -. Wynik konwersji zwracany jest jako wartość typu long int.
Jeśli tekstu nie da się zinterpretować jako liczbę całkowitą, funkcja zwraca wartość 0.
W dużym komputerze PC nie ma różnicy pomiędzy typem int a long int, ponieważ oba oznaczają liczbę 32-bitową. Jednak w mikrokontrolerach taka różnica wystąpi:
W dużym komputerze PC dostępna jest zwykle funkcja atoll( ), która zamienia łańcuch w liczbę typu long long int
Funkcja atof( ) (ang. ASCII string to floating point number) oblicza wartość dziesiętną liczby rzeczywistej zapisanej w postaci znaków ASCII. Początkowe spacje są pomijane. Sama liczba może być zapisana jako:
Wynik konwersji zwracany jest jako wartość typu double.
Jeśli tekstu nie da się zinterpretować jako liczbę rzeczywistą, funkcja zwraca wartość 0.
Funkcja itoa( ) (ang. integer to ASCII string) dokonuje konwersji liczby całkowitej na jej reprezentację w wybranym systemie pozycyjnym w postaci ciągu liczb.
Funkcja zwraca adres bufora.
Uwaga: w środowisku mikrokontrolerów PIC argumenty funkcji itoa( ) są w innej kolejności:
W środowiskach programowania mikrokontrolerów dostępne są podobne funkcje, których niestety nie ma w Code::Blocks (nie są one standardowe):
Sprawdź to w instrukcji swojego kompilatora.
Dołączając do swojego programu plik nagłówkowy ctype.h uzyskujesz dostęp do wielu przydatnych funkcji znakowych. Poniżej podajemy ich spis wraz z krótkim opisem działania.
Funkcje znakowe są zrealizowane w postaci tzw. makr (tego tematu nie poruszałem w tym krótkim kursie) preprocesora. Makra są rozwijane w odpowiednie rozkazy języka C. Parametrem każdego z makr jest wartość całkowita c, traktowana jako kod znaku ASCII. Wynikiem jest 0, jeśli test wykonywany przez makro daje rezultat negatywny, lub 1, jeśli test daje wynik pozytywny.
Uruchom program:
Kolejne trzy makra zwracają w wyniku przetworzoną wartość argumentu jako znak ASCII:
Funkcje tolower( ) i touper( ) nie reagują na polskie litery, których kody nie należą do podstawowego zestawu ASCII.
Uruchom program:
Zapraszam do ostatniego rozdziału.
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2026 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.