Napisy
Typ char
Do przechowywania pojedynczych znaków
służy typ char
.
Zmienna tego typu zajmuje zawsze 1 B.
char znak1 = 'A'; char znak2 = 65; if(znak1 == znak2){ printf("Znak 'A' to liczba 65.\n"); } printf("Kod ASCII cyfry 0 to %d.\n", '0');
Wczytywanie i wypisywanie wartości typu char
Specyfikator wejścia-wyjścia dla typu char
to %c
.
Uwaga: nie są pomijane białe znaki (spacja,
tabulacja, przejście do nowej linii itp.).
char odpowiedz; printf("Czy ten program jest poprawny? [T/N] "); scanf("%c", &odpowiedz); if( odpowiedz == 'T' ){ // ... } else { // ... }
Operacje na cyfrach i literach
Kod znaku cyfry 0 to '0'
czyli liczba 48. Aby skonwertować znak cyfry do odpowiadającej jej liczby,
wystarczy odjąć od niej znak cyfry '0'
. Aby skonwertować liczbę na znak cyfry
(oczywiście liczbę jednocyfrową),
należy do niej dodać cyfrę '0'
.
char cyfra = '3'; int liczba = cyfra - '0'; liczba *= 2; cyfra = liczba + '0'; printf("%c", cyfra);
Małe (i oddzielnie wielkie) litery alfabetu angielskiego
są umieszczone w tabeli kodów ASCII jedna za drugą bez przerw. Aby z litery 'a'
otrzymać 'b'
, wystarczy napisać 'a'+1
.
Przesunięcie między małymi a wielkimi literami,
które sobie odpowiadają, jest stałe
— 'A'-'a'
, 'B'-'b'
, ..., 'Z'-'z'
to ta sama liczba.
Dlatego, mając zmienną znak
, która spełnia
warunek 'a' <= znak && znak <= 'z'
(czyli jest małą literą),
jeśli chcemy otrzymać odpowiadającą jej wielką literę,
wystarczy, że napiszemy znak+'A'-'a'
.
Tablice znaków
Do przechowywania napisów w pamięci służą tablice znaków:
char napis[30];
Za ostatnim znakiem napisu musi
wystąpić wartość '\0'
(czyli liczba 0),
która jest znacznikiem końca napisu.
Oczywiście rozmiar tablicy znaków
przeznaczonej na przechowanie napisu nie może być mniejszy od rzeczywistej długości
napisu powiększonej o 1.
Programista musi się samodzielnie
postarać o spełnienie tego warunku w każdym
miejscu w kodzie programu. Z tego powodu posługiwanie się napisami w języku C
jest niewygodne (w porównaniu z nowszymi językami),
początkowo trudne i może przyczyniać się do powstawania częstych błędów.
Znacznikiem końca napisu jest znak '\0'
,
więc najczęściej nie ma potrzeby znać rzeczywistego
rozmiaru tablicy, w której napis jest zapisany
— o ile się w niej mieści. Z tego powodu funkcja, której przekazywany
jest napis, nie musi dostawać jego długości
podanego jawnie za pomocą dodatkowego parametru.
Iterowanie po znakach napisu
Często popełnianym błędem, gdy chcemy przejść po wszystkich znakach napisu, jest stosowanie warunku jak w pętli poniżej:
for(i=0; i < strlen(napis); ++i){ // zrob_cos_z(napis[i]); }
Tak postawiony warunek spowoduje, że długość napisu będzie musiała
być obliczona za każdym razem,
gdy ma być obliczony warunek. W tym miejscu lepiej jest wykorzystać
własność napisów dotyczącą
sposobu zaznaczania ich końca
— znak '\0'
stoi zawsze na końcu napisu.
for(i=0; napis[i] != '\0'; ++i){ // zrob_cos_z(napis[i]); }
Inicjowanie napisów
char napis1[] = {'A', 'l', 'a', ' ', 'm', 'a', ' ', 'k', 'o', 't', 'a', '\0'}; char napis2[] = "Ala ma kota"; char *napis3 = "Ala ma kota";
Jaka jest różnica między napis2
a napis3
?
napis3
to wskaźnik do stałego napisu,
czyli takiego, którego zawartości nie można modyfikować.
Wczytywanie i wypisywanie napisów
Do wczytywania napisu ze standardowego wejścia
używamy funkcji fgets
, która przyjmuje jako parametry:
napis, jego maksymalny rozmiar oraz plik, z którego
ma odbywać się wczytywanie (standardowe wejście to stdin
).
char napis[100]; fgets( napis, 100, stdin);
Funkcja fgets
wczytuje napis o długości
maksymalnie o jeden mniej, niż podany rozmiar tablicy.
Jeśli wcześniej wystąpi koniec pliku
lub znak przejścia do nowej linii,
również w tym momencie kończy się czytanie, przy czym znak przejścia do nowej linii
jest zapisywany w tablicy.
Zachowana jest konwencja zakończenia napisu znakiem '\0'
.
Nie należy używać funkcji scanf
do wczytywania napisów,
ponieważ może to powodować błąd wyjścia poza zakres tablicy. Nie jesteśmy w stanie w żaden sposób temu zapobiec,
gdy używamy scanf
a użytkownik wpisze napis o większym
rozmiarze niż rozmiar tablicy, którą przekazaliśmy do funkcji.
Do wypisywania można używać funkcji printf
, przy czym należy podać napis jako drugi lub dalszy argument:
printf("%s", napis); // dobrze printf(napis); // źle!
Można również zastosować funkcję puts
:
puts(napis);
Zadania
-
Napisz funkcję, która przyjmuje jako parametr napis i zwraca jego długość.
-
Napisz funkcję, która przyjmuje jako parametr napis oraz tablicę znaków o rozmiarze co najmniej takim jak napis. Funkcja ma umieścić w drugiej tablicy odwrócony (pierwszy) napis.
-
Napisz funkcję, która przyjmuje jako parametr napis i zwraca 1, jeśli napis jest palindromem; 0 w przeciwnym razie.
-
Napisz funkcję, która przyjmuje jako parametry dwa napisy i zwraca 1, jeśli są sobie równe; 0 w przeciwnym razie.
-
Napisz funkcję, która przyjmuje jako parametr napis i zwraca liczbę słów w nim zapisanych. Przyjmujemy, że słowa są rozdzielone pojedynczymi znakami spacji.
-
Napisz funkcję, która przyjmuje jako parametr napis oraz tablicę znaków o rozmiarze co najmniej takim jak napis. Funkcja ma skopiować pierwszy napis do drugiej tablicy.
-
Napisz funkcję, która przyjmuje jako parametr napis i zamienia w nim wszystkie wielkie litery na małe.
-
Napisz funkcję, która przyjmuje jako parametr napis i zmienia go tak, że co druga litera jest wielka a wszystkie pozostałe są małe. Na przykład napis
"Jakie to dziwne zadanie..."
zamienia na"jAkIe tO DzIwNe zAdAnIe..."
. -
Napisz funkcję otrzymującą jako parametry trzy tablice znaków i zapisującą do trzeciej tablicy konkatenację napisów znajdujących się w dwóch pierwszych tablicach (czyli dla napisów
"Ala m"
i"a kota"
znajdujących się w pierwszych dwóch argumentach do trzeciej tablicy powinien zostać zapisany napis"Ala ma kota"
). -
Napisz funkcję, która otrzymuje jako parametry dwa napisy i dopisuje drugi napis na koniec pierwszego.
-
Napisz funkcję, która w napisie podanym jako parametr usunie wielokrotne wystąpienia spacji obok siebie. Na przykład napis
" Ala ma kota. "
przekształci w napis" Ala ma kota. "
.