|
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
W środowisku kompilatorów C dla mikrokontrolerów AVR (Atmel) oraz PIC (Microchip) dostępny
jest plik nagłówkowy
Funkcja memset( ) (ang. memory set), wypełnia zadany obszar wybraną wartością. Składnia jest następująca:
memset(adres_obszaru, wartość, liczba_bajtów); |
| adres_obszaru | – | wskaźnik pierwszego bajtu obszaru, który ma zostać wypełniony |
| wartość | – | obszar zostanie wypełniony bajtami o tej wartości |
| liczba_bajtów | – | tyle bajtów obszaru zostanie wypełnione podaną wartością |
Funkcja zwraca w wyniku adres wypełnionego obszaru.
Uruchom program:
/*
Pamięć
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 29.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
signed char t[10];
int i;
setlocale(LC_ALL,"");
memset(t, -55, 10); // wypełniamy t liczbą -55
for(i = 0; i < 10; i++)
printf("t[%d] = %d\n", i, t[i]);
return 0;
}
|
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:
/*
Pamięć
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 29.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
float t[10];
int i;
setlocale(LC_ALL,"");
memset(t, 0, 10 * sizeof(float)); // zerujemy t
for(i = 0; i < 10; i++)
printf("t[%d] = %f\n", i, t[i]);
return 0;
}
|
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:
memcpy(adres_przeznaczenia, adres_źródła, liczba_bajtów); |
| adres_przeznaczenia | – | wskaźnik pierwszego bajtu obszaru
pamięci, do którego odbędzie się kopiowanie |
| adres_źródła | – | wskaźnik pierwszego bajtu obszaru,
który będzie kopiowany |
| liczba_bajtów | – | tyle bajtów zostanie skopiowane |
Funkcja zwraca adres przeznaczenia.
Uruchom program:
/*
Pamięć
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 29.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
// Wypisuje zawartość tablicy znakowej jako liczby
//------------------------------------------------
void pc(char c, char * x, int n)
{
int i;
printf("%c[] = ", c);
for(i = 0; i < n; i++) printf("%3d", x[i]);
printf("\n");
}
int main()
{
char s[] = {81,82,83,84,85};
char t[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
setlocale(LC_ALL,"");
pc('s', s, 5);
printf("\nPrzed:\n");
pc('t', t, 9);
memcpy(&t[2], s, 5);
printf("\nPo:\n");
pc('t', t, 9);
return 0;
}
|
Program tworzy dwie tablice znakowe:
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:
/*
Pamięć
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 29.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
// Wypisuje zawartość tablicy
//---------------------------
void pi(char c, int * x, int n)
{
int i;
printf("%c[] = ",c);
for(i = 0; i < n; i++) printf("%3d",x[i]);
printf("\n");
}
int main()
{
int s[] = {81,82,83,84,85};
int t[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
setlocale(LC_ALL,"");
pi('s', s, 5);
printf("\nPrzed:\n");
pi('t', t, 9);
memcpy(&t[2], s, 5 * sizeof(int));
printf("\nPo:\n");
pi('t', t, 9);
return 0;
}
|
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ć.
memmove(adres_przeznaczenia, adres_źródła, liczba_bajtów); |
| adres_przeznaczenia | – | wskaźnik pierwszego bajtu obszaru
pamięci, do którego odbędzie się kopiowanie |
| adres_źródła | – | wskaźnik pierwszego bajtu obszaru,
który będzie kopiowany |
| liczba_bajtów | – | tyle bajtów zostanie skopiowane |
Uruchom program:
/*
Pamięć
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 29.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
// Wypisuje zawartość tablicy
//---------------------------
void pi(char c, int * x, int n)
{
int i;
printf("%c[] = ",c);
for(i = 0; i < n; i++) printf("%3d",x[i]);
printf("\n");
}
int main()
{
int t[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
setlocale(LC_ALL,"");
printf("\nPrzed:\n");
pi('t', t, 9);
memmove(t, &t[2], 7 * sizeof(int));
printf("\nPo:\n");
pi('t', t, 9);
return 0;
}
|
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.
memchr(adres_obszaru, wartość, liczba_bajtów); |
| adres_obszaru | – | wskaźnik pierwszego bajtu obszaru
pamięci, w którym będzie poszukiwana zadana wartość |
| wartość | – | wartość do wyszukania |
| liczba_bajtów | – | tyle bajtów zostanie przeszukane |
Uruchom program:
/*
Pamięć
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 29.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char t[] = {12,76,33,11,55,97,48,62,81};
char v = 48; // szukana wartość;
char * p;
int i;
setlocale(LC_ALL,"");
p = memchr(t,v,9);
printf("Szukane %d: ", v);
if(p)
{
printf("na pozycji %d w t[]\n\n"
"t[] = ", p - t);
for(i = 0; i < 9; i++)
if(p == &t[i]) printf("{%d} ", t[i]);
else printf(" %d ", t[i]);
}
else printf("BRAK W t[]");
printf("\n\n");
return 0;
}
|
Funkcja memcmp( ) (ang. memory compare) porównuje ze sobą dwa obszary pamięci. Funkcja posiada następujące parametry:
memcmp(adres_obszaru_1, adres_obszaru_2, liczba_bajtów); |
| adres_obszaru | – | wskaźnik pierwszego bajtu porównywanego obszaru |
| liczba_bajtów | – | tyle bajtów zostanie porównane |
Funkcja zwraca w wyniku:
Na przykład:
| obszar_1: | 2,3,5,5,7,2,8,1,9 | : wynik 0, : obszar_1 = obszar_2 |
| obszar_2: | 2,3,5,5,7,2,8,1,9 |
| obszar_1: | 2,3,5,5,7,2,8,1,9 | : wynik 1, : obszar_1 > obszar_2 |
| obszar_2: | 2,3,5,5,7,0,8,1,9 |
| obszar_1: | 2,3,5,5,7,2,8,1,9 | : wynik -1, : obszar_1 < obszar_2 |
| obszar_2: | 2,3,5,5,7,2,9,1,9 |
Uruchom program:
/*
Pamięć
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 30.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char a[] = {2,3,5,5,7,2,8,1,9};
char b[] = {2,3,5,5,7,2,8,1,9};
char c[] = {2,3,5,5,7,0,8,1,9};
char d[] = {2,3,5,5,7,2,9,1,9};
setlocale(LC_ALL,"");
printf("a i b -> %2d\n", memcmp(a,b,9));
printf("a i c -> %2d\n", memcmp(a,c,9));
printf("a i d -> %2d\n", memcmp(a,d,9));
return 0;
}
|
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:
| "ABC", "domek", "Bartek i Agatka", itp. |
Wartością tej stałej jest wskaźnik do obszaru, w którym umieszczone są znaki:
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 31.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
char *p = "Hulaj dusza ile wola!";
setlocale(LC_ALL,"");
while(*p) printf("znak tekstu: %c\n",*p++);
return 0;
}
|
Ponieważ stała łańcuchowa daje w wyniku wskaźnik, to nie możemy przypisać ją do tablicy znakowej, np. tak:
char t[12]; t = "Abracadabra"; // Źle!! |
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ę:
char tablica[] = "dowolny tekst"; |
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.
strcpy(adres_docelowy, adres_łańcucha); |
| adres_docelowy | – | wskaźnik pierwszego bajtu obszaru, w którym zostanie umieszczony kopiowany łańcuch tekstowy |
| adres_łańcucha | – | wskaźnik pierwszego
znaku kopiowanego łańcucha tekstowego. |
Funkcja zwraca w wyniku adres docelowy.
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 31.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char t[12];
setlocale(LC_ALL,"");
strcpy(t,"Abracadabra");
printf("%s\n",t);
return 0;
}
|
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.
strncpy(adres_docelowy, adres_łańcucha, liczba_znaków); |
| adres_docelowy | – | wskaźnik pierwszego bajtu obszaru, w którym zostanie umieszczony kopiowany łańcuch tekstowy |
| adres_łańcucha | – | wskaźnik pierwszego znaku kopiowanego łańcucha tekstowego. |
| liczba_znaków | – | tyle maksymalnie znaków zostanie przesłanych z łańcucha do obszaru docelowego. Jeśli łańcuch jest krótszy, to na końcu łańcucha będzie umieszczony znak NUL. Jeśli łańcuch jest dłuższy, to znak NUL nie będzie umieszczony w obszarze docelowym. |
Wynikiem funkcji jest adres docelowy.
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 31.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char t[6];
setlocale(LC_ALL,"");
strncpy(t,"Abracadabra",6);
printf("%s\n",t);
return 0;
}
|
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ą.
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 31.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char t[7];
setlocale(LC_ALL,"");
strncpy(t,"Abracadabra",6);
t[6] = 0; // Znak NUL na koniec
printf("%s\n",t);
return 0;
}
|
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.
strlen(adres_łańcucha); |
| adres_łańcucha | – | wskaźnik pierwszego znaku łańcucha
tekstowego, którego liczbę znaków funkcja wylicza. |
Uruchom program:
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 31.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char t[20];
setlocale(LC_ALL,"");
strcpy(t,"Kajko i Kokosz");
printf("Tekst >%s< ma znakow %d\n",
t,strlen(t));
return 0;
}
|
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.
strcat(adres_docelowy, adres_łańcucha); |
| adres_docelowy | – | wskaźnik pierwszego znaku obszaru
zawierającego łańcuch, do którego końca zostanie dołączony drugi łańcuch. |
| adres_łańcucha | – | wskaźnik pierwszego znaku dołączanego łańcucha tekstowego. |
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.
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 31.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char t[100];
setlocale(LC_ALL,"");
strcpy(t,"Kajko i Kokosz"); printf("%s\n",t);
strcat(t," to dwaj"); printf("%s\n",t);
strcat(t," dobrzy"); printf("%s\n",t);
strcat(t," przyjaciele."); printf("%s\n",t);
return 0;
}
|
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.
strncat(adres_docelowy, adres_łańcucha, liczba_znaków); |
| adres_docelowy | – | wskaźnik pierwszego znaku obszaru
zawierającego łańcuch, do którego końca zostanie dołączony drugi łańcuch. |
| adres_łańcucha | – | wskaźnik pierwszego znaku dołączanego łańcucha tekstowego. |
| liczba_znaków | – | tyle maksymalnie znaków będzie dołączone z łańcucha. |
Funkcja zwraca adres docelowy.
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 31.10.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#define MAXC 78
int main()
{
char t[MAXC + 1];
setlocale(LC_ALL,"");
t[0] = 0; // pusty łańcuch tekstowy
while(strlen(t) < MAXC)
printf("%s\n",
strncat(t,"Ala ma rudego kocura gbura ",
MAXC - strlen(t)));
return 0;
}
|
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).
strchr(adres_łańcucha, znak_do_wyszukania); |
| adres_łańcucha | – | wskaźnik pierwszego znaku przeszukiwanego łańcucha tekstowego. |
| znak_do_wyszukania | – | kod ASCII znaku, który będzie poszukiwany w łańcuchu. |
Poniższy program demonstruje sposób używania funkcji strchr( ) do wyszukania wszystkich wystąpień litery 'e', która zostaje zastąpiona literą 'E':
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 1.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char t[] = "Dzisiaj misiaczek wypije kubeczek pysznego miodku.";
char *p;
setlocale(LC_ALL,"");
printf("Przed: %s\n",t);
for(p = t;(p = strchr(p,'e')); p++) *p = 'E';
printf("Po : %s\n",t);
return 0;
}
|
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).
strrchr(adres_łańcucha, znak_do_wyszukania); |
| adres_łańcucha | – | wskaźnik pierwszego znaku przeszukiwanego łańcucha tekstowego. |
| znak_do_wyszukania | – | kod ASCII znaku, który będzie poszukiwany w łańcuchu. |
Poniższy program zamienia w ostatnim wyrazie litery małe na duże – postaraj się odkryć, jak to jest robione:
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 2.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char t[] = "Dzisiaj misiaczek wypije kubeczek pysznego miodku.";
char *p;
setlocale(LC_ALL,"");
printf("Przed: %s\n",t);
if((p = strrchr(t,' ')))
while(*++p) if(*p >= 'a' && *p <= 'z') *p -= 32;
printf("Po : %s\n",t);
return 0;
}
|
Funkcja strcmp( ) (ang. string compare) porównuje ze sobą dwa łańcuchy znakowe s1 i s2. Zwraca następujące wartości:
| 0 | – | s1 jest równy
s2, tzn. zawiera
dokładnie ten sam tekst. |
| -1 | – | Łańcuch s1 jest leksykograficznie
mniejszy od s2. Oznacza to jedną z dwóch możliwości:
|
| 1 | – | Łańcuch s1 jest leksykograficznie
większy od łańcucha s2. Oznacza to jedną z dwóch możliwości:
|
Funkcja posiada następującą składnię:
strcmp(adres_łańcucha_s1, adres_łańcucha_s2); |
| adres_łańcucha | – | wskaźnik pierwszego znaku łańcucha uczestniczącego w porównaniu. |
Uruchom program:
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 2.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char s1[100], s2[100], c;
setlocale(LC_ALL,"");
printf("Wpisz dwa wyrazy:\n\n");
scanf("%s %s", s1, s2);
switch(strcmp(s1, s2))
{
case -1: c = '<'; break;
case 0: c = '='; break;
case 1: c = '>'; break;
}
printf("\n\n%s %c %s\n\n", s1, c, s2);
return 0;
}
|
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.
strncmp(adres_łańcucha_s1, adres_łańcucha_s2, liczba_znaków); |
| adres_łańcucha | – | wskaźnik pierwszego znaku łańcucha uczestniczącego w porównaniu. |
| liczba_znaków | – | tyle maksymalnie znaków będzie porównywanych |
Uruchom program:
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 2.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char s1[100],s2[100],c;
setlocale(LC_ALL,"");
printf("Wpisz dwa wyrazy:\n\n");
scanf("%s %s",s1,s2);
switch(strncmp(s1,s2,3))
{
case -1: c = '<'; break;
case 0: c = '='; break;
case 1: c = '>'; break;
}
printf("\n\nWg trzech pierwszych znakow %s %c %s\n\n",
s1,c,s2);
return 0;
}
|
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).
strstr(adres_łańcucha_s1, adres_łańcucha_s2); |
| adres_łańcucha | – | wskaźnik pierwszego znaku łańcucha. |
Uruchom program:
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 3.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char s1[] = "Kuba nie lubi kawy, mleka i kakao";
char s2[] = "ka"
char *p;
int i;
setlocale(LC_ALL,"");
strcpy(s1,);
strcpy(s2,"ka");
p = s1;
printf("Przed: %s\n\n",s1);
while((p = strstr(p,s2)))
for(i = 0; s2[i]; i++) *p++ -= 32;
printf("Po : %s\n\n",s1);
return 0;
}
|
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.
strpbrk(adres_łańcucha_s1, adres_łańcucha_s2); |
| adres_łańcucha | – | wskaźnik pierwszego znaku łańcucha. |
Uruchom poniższy program, który w łańcuchu s zamienia wszystkie samogłoski małe na duże:
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 3.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char s[80],*p;
setlocale(LC_ALL,"");
printf("Wpisz wiersz tekstu (do 79 znaków):\n\n");
gets(s);
p = s;
while((p = strpbrk(p,"aeiou"))) *p++ -= 32;
printf("%s\n\n",s);
return 0;
}
|
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:
strtok(adres_łańcucha_s, adres_łańcucha_separatorów); |
| adres_łańcucha_s | – | wskaźnik pierwszego znaku łańcucha, który będzie rozbijany na słowa. |
| adres_łańcucha_separatorów | – | wskaźnik pierwszego znaku łańcucha zawierającego znaki separujące. |
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:
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 5.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main()
{
char s[80],*p,*t = ",?!.;: ";
int i;
setlocale(LC_ALL,"");
printf("Wpisz wiersz tekstu (do 79 znaków):\n\n");
gets(s);
printf("\n");
p = strtok(s, t); // pierwsze słowo
i = 1;
while(p) // dopóki są słowa
{
printf("Wyraz nr %2d : %s\n",i++,p);
p = strtok(NULL, t); // następne słowa
}
return 0;
}
|
Nie ma funkcji standardowej, która usuwa z łańcucha znak. Jednak funkcję taką można łatwo napisać. Uruchom poniższy program:
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 6.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
// Usuwa znak wskazywany przez p
void delchr(char *p)
{
if(p) // jeśli p wskazuje łańcuch
do
{
p++; // następny znak w łańcuchu
*(p - 1) = *p; // kopiujemy znaki
} while(*p); // aż do znaku NUL włącznie
}
int main()
{
char t[80], *p;
setlocale(LC_ALL,"");
printf("Wpisz wiersz tekstu (do 79 znaków):\n\n");
gets(t);
p = t;
while(*p)
if(*p == 'a') delchr(p);
else p++;
printf("%s\n\n",t);
return 0;
}
|
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.
/*
Teksty
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 6.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
// dodaje znak na pozycję p
void inschr(char *p, char a)
{
if(p) // jeśli p wskazuje łańcuch
{
memmove(p+1,p,strlen(p)+1); // robimy miejsce
*p = a; // wstawiamy znak
}
}
int main()
{
char t[80], *p;
setlocale(LC_ALL,"");
printf("Wpisz wiersz tekstu (do 79 znaków):\n\n");
gets(t);
p = t;
while(*p)
{
if(*p == 'a') inschr(p++,'x');
p++;
}
printf("%s\n\n",t);
return 0;
}
|
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.
atoi(adres_łańcucha); |
| adres_łańcucha | – | wskaźnik pierwszego znaku łańcucha. |
Jeśli tekstu nie da się zinterpretować jako liczbę całkowitą, funkcja zwraca wartość 0.
/*
Konwersje znakowo-liczbowe
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 3.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
char s[] = "-1236";
setlocale(LC_ALL,"");
printf("%d\n\n",atoi(s));
return 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.
atol(adres_łańcucha); |
| adres_łańcucha | – | wskaźnik pierwszego znaku łańcucha. |
Jeśli tekstu nie da się zinterpretować jako liczbę całkowitą, funkcja zwraca wartość 0.
/*
Konwersje znakowo-liczbowe
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 3.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
char s[] = "386799588";
setlocale(LC_ALL,"");
printf("%ld\n\n",atol(s));
return 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.
atof(adres_łańcucha); |
| adres_łańcucha | – | wskaźnik pierwszego znaku łańcucha. |
Jeśli tekstu nie da się zinterpretować jako liczbę rzeczywistą, funkcja zwraca wartość 0.
/*
Konwersje znakowo-liczbowe
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 3.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
char s[] = "3.141575";
setlocale(LC_ALL,"");
printf("%9.6f\n\n",atof(s));
return 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.
itoa(liczba, adres_bufora, podstawa); |
| liczba | – | liczba, która zostanie poddana konwersji |
| adres_bufora | – | adres tablicy znakowej, w której
zostanie umieszczony ciąg cyfr. Tablica musi posiadać wystarczającą pojemność na wszystkie cyfry oraz znak NUL. |
| podstawa | – | liczba, która określa podstawę
systemu, w którym zostanie zapisana liczba. Zakres podstawy wynosi od 2 do 36. |
Funkcja zwraca adres bufora.
/*
Konwersje znakowo-liczbowe
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 4.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
char buf[50];
int n, i;
setlocale(LC_ALL,"");
printf("liczba = "); scanf("%d", &n);
printf("\n");
for(i = 2; i <= 16; i++)
printf("%d(10) = %s(%d)\n",n,itoa(n,buf,i),i);
return 0;
}
|
Uwaga: w środowisku mikrokontrolerów PIC argumenty funkcji itoa( ) są w innej kolejności:
itoa(adres_bufora, liczba, podstawa); |
W środowiskach programowania mikrokontrolerów dostępne są podobne funkcje, których niestety nie ma w Code::Blocks (nie są one standardowe):
char * ltoa (long val, char *s, int radix) char * utoa (unsigned int val, char *s, int radix) char * ultoa (unsigned long val, char *s, int radix) |
| val | – | liczba, która zostanie poddana konwersji |
| s | – | tablica znakowa, w której zostanie
umieszczony ciąg cyfr. Tablica musi posiadać wystarczającą pojemność na wszystkie cyfry oraz znak NUL. |
| radix | – | liczba, która określa podstawę
systemu, w którym zostanie zapisana liczba. Zakres podstawy wynosi od 2 do 36. |
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.
| isalnum(c) | – | czy c jest literą lub cyfrą: 0...9, a...z lub A...Z ? |
| isalpha(c) | – | czy c jest literą a...z lub A...Z ? |
| isascii(c) | – | czy c jest 7-bitowym znakiem ASCII ? |
| iscntrl(c) | – | czy c jest znakiem sterującym ? |
| isdigit(c) | – | czy c jest cyfrą dziesiętną ? |
| islower(c) | – | czy c jest małą literą a...z ? |
| isprint(c) | – | czy c jest znakiem drukowalnym ? |
| isgraph(c) | – | czy c jest znakiem drukowalnym oprócz spacji ? |
| ispunct(c) | – | czy c nie jest literą lub cyfrą, lecz jest znakiem drukowalnym ? |
| isspace(c) | – | czy c jest znakiem spacji, tabulacji lub nowego wiersza ? |
| isupper(c) | – | czy c jest dużą literą A...Z ? |
| isxdigit(c) | – | czy c jest cyfrą szesnastkową: 0...9, a...f lub A...F ? |
Uruchom program:
/*
Znaki
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 4.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <locale.h>
int main()
{
char t[80], *p;
int a,d,s,o;
setlocale(LC_ALL,"");
printf("Wpisz wiersz (do 79 znaków)\n\n");
gets(t);
a = d = s = o = 0; // zerujemy liczniki
p = t;
while(*p)
{
if(isalpha(*p)) a++; // litery
if(isdigit(*p)) d++; // cyfry
if(isspace(*p)) s++; // spacje
if(ispunct(*p)) o++; // pozostałe znaki
p++;
}
printf("\n\nStatystyka:\n\n"
"Litery: %2d\n"
"Cyfry : %2d\n"
"Spacje: %2d\n"
"Inne : %2d\n\n", a, d, s, o);
return 0;
}
|
Kolejne trzy makra zwracają w wyniku przetworzoną wartość argumentu jako znak ASCII:
| toascii(c) | – | zwraca kod podstawowy ASCII
(0...127) przez wyzerowanie starszych bitów argumentu c |
| tolower(c) | – | jeśli c jest dużą literą
A...Z, to
zwraca kod małej litery a...z. Jeśli c nie jest dużą literą, zwraca wartość c bez zmiany. |
| toupper(c) | – | jeśli c jest małą literą
a...z, to zwraca kod dużej litery A...Z. Jeśli c nie jest małą literą, zwraca wartość c bez zmiany. |
Funkcje tolower( ) i touper( ) nie reagują na polskie litery, których kody nie należą do podstawowego zestawu ASCII.
Uruchom program:
/*
Konwersje znakowo-liczbowe
(C)2016 mgr Jerzy Wałaszek
Data utworzenia: 4.11.2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <locale.h>
int main()
{
char t[80], *p;
setlocale(LC_ALL,"");
printf("Wpisz wiersz (do 79 znaków)\n\n");
gets(t);
for(p = t; *p; p++) *p = toupper(*p);
printf("%s\n\n", t);
return 0;
}
|
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.