====== Łańcuchy znaków (stringi) =====
* **napis** lub **łancuch znakowy** to tablica zawierająca ciąg znaków zakończony wartością 0 (znak '' '\0' '')
* dowolny ciąg znaków w cudzysłowach jest stałym napisem, np.: napis ''"Ala ma kota"''
* funkcja ''printf()'' posiada specyfikator formatu ''%s'' służący do wyświetlania zmiennych napisowych
**Przykład 1:**\\
Poniższy program oblicza ilość znaków w napisie "Ala ma kota".
#include
int main()
{
char napis[] = "Ala ma kota";
int i = 0;
while(napis[i] != '\0')
{
i++;
}
printf("Napis \"%s\" zawiera %d liter\n", napis, i);
return 0;
}
Po uruchomieniu programu na ekranie pojawi się:
Napis "Ala ma kota" zawiera 11 liter
**Przykład 2:**\\
Poniższy program wypisuje napis "Ala ma kota" w kolejnych liniach.
W każdej kolejnej linii wypisywany komunikat jest skracany o jeden, początkowy znak.
#include
int main()
{
char *napis = "Ala ma kota\n";
while(*napis != '\0')
{
printf(napis);
napis++;
}
return 0;
}
Po uruchomieniu programu na ekranie pojawi się:
Ala ma kota
la ma kota
a ma kota
ma kota
ma kota
a kota
kota
kota
ota
ta
a
==== Ćwiczenie - Czytaj linię ===
W języku C mamy do dyspozycji funkcję ''gets()'', która czyta linię tekstu ze standardowego wejścia (zobacz [[https://pl.wikibooks.org/wiki/C/gets|gets()]]).
Jednak użycie tej funkcji jest niebezpieczne, gdyż nie jest zabezpieczona przed przepełnieniem bufora, tzn.
taką sytuacją , gdy linia testu jest dłuższa niż ilość miejsca w tablicy do której wczytujemy znaki.
Napiszmy własną wersję funkcji ''gets()'', która będzie pozbawiona tej wady.
**Opis funkcji**\\
Funkcja o nazwie ''czytaj_linie()'' czyta linię tekstu ze standardowego wejścia ale nie więcej niż ''n'' znaków.
Kolejne znaki odczytane z wejścia umieszczane są w tablicy znakowej wskazywanej przez ''str'' tworząc napis
(łańcuch znakowy), tzn. za ostatnim znakiem umieszczane jest zero (znak '''\0''').
Znak nowego wiersza '''\n''' nie jest umieszczany w tablicy ''str''.
Jeżeli napotkany zostanie koniec pliku (EOF) funkcja kończy swoje działanie zwracając wartość ''NULL''.' Do wczytywania kolejnych znaków ze standardowego wejścia użyj funkcji ''[[http://pl.wikibooks.org/wiki/C/getchar|getchar()]]''.
**Argumenty funkcji:** tablica znakowa ''str'' oraz liczba całkowita ''n'' określająca maksymalną liczbę znaków jaka może zostać wczytana do tablicy ''str''\\
**Wartość zwracana:** funkcja zwraca adres tablicy ''str'' w przypadku sukcesu lub NULL w przypadku natrafienia na koniec pliku.
Niżej znajduje się fragment kodu zawierający definicje funkcji ''czytaj_linie()'' oraz krótki program, który numeruje wszystkie linie ze standardowego wejścia.
#include
char *czytaj_linie(char *str, int n)
{
int i=0, znak;
while( i < n-1 && (znak = getchar()) != '\n' && znak != EOF)
{
str[i] = znak;
i = i + 1;
}
str[i]='\0';
if (znak == EOF) return NULL;
return str;
}
#define MAXLINE 100
int main()
{
int i = 1;
char napis[MAXLINE];
while(czytaj_linie(napis, MAXLINE))
{
printf("%d: %s\n", i, napis);
i = i + 1;
}
return 0;
}
Jeżeli na standardowym wejściu powyższego programu podamy tekst
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
wówczas na ekranie powinien pojawić się taki tekst:
1: Lorem ipsum dolor sit amet,
2: consectetur adipiscing elit.
==== Biblioteka string.h ====
W bibliotece standardowej znajduje się szereg funkcji związanych z operacjami na łańcuchach znakowych.
Zadeklarowane są one w pliku [[http://www.cplusplus.com/reference/cstring/|string.h]].
Oto lista kilku wybranych funkcji:
* [[https://pl.wikibooks.org/wiki/C/strlen|strlen]] - wyznacza długość napisu \\ int strlen(char *napis)
* [[https://pl.wikibooks.org/wiki/C/strcpy|strcpy]] - kopiowanie napisu z ''src'' do ''dest'' \\ char* strcpy(char *src, char* dest)
* [[https://pl.wikibooks.org/wiki/C/strcmp|strcmp]] - porównywanie napisów w porządku alfabetycznym \\ int strcmp(char *napis1, char* napis2)
* [[https://pl.wikibooks.org/wiki/C/strcat|strcat]] - łączenie napisów, dodaje ''src'' na końcu ''dest'' \\ char* strcat(char *src, char* dest)
* [[https://pl.wikibooks.org/wiki/C/strstr|strstr]] - znajduje ''wzor'' w napisie \\ char* strstr(char *napis, char* wzor)
**Przykład**
Poniżej znajduje się program, który demonstruje użycie funkcji ''strcpy'' oraz ''strcmp''' z biblioteki ''string.h''.
Program czyta tekst ze standardowego wejścia aż do napotkania końca pliku i
wypisuje kolejne linie, z pominięciem tych, które się powtarzają.
\\ Uwaga: program używa funkcji ''czytaj_linie()'', której definicja znajduje się w poprzednim przykłądzie.
#include
#define MAXLINE 1000
int main()
{
char linia[MAXLINE];
char linia_poprzednia[MAXLINE];
linia_poprzednia[0] = '\0';
while(czytaj_linie(linia, MAXLINE) != NULL)
{
if (strcmp(linia, linia_poprzednia) != 0)
{
printf("%s\n", linia);
strcpy(linia_poprzednia, linia);
}
}
return 0;
}
Przykładowo, jeżeli na wejście programu przekierujemy plik zawierający:
Lorem ipsum dolor sit amet,
Lorem ipsum dolor sit amet,
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
consectetur adipiscing elit.
na wyjściu otrzymamy unikatowe linie
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
==== Zadnie - Szyfr cezara ====
Napisz program, który szyfruje tekst za pomocą szyfru Cezara.
W tym celu zadeklaruj w programie funkcję o nazwie ''szyfr()'', która
w danej tablicy znakowej zawierającej napis zamieni wszystkie znaki alfabetu na znaki
stojące o 3 pozycje dalej w alfabecie, tzn. ''a'' zamieniane jest na ''d'', litera ''b'' na ''e'', itd. Litera ''z'' zamieniana jest na ''a'', ''y'' na ''b'', ''z'' na ''c''. Zamianie ulegają wyłącznie znaki alfabetu (małe ''a-z'' i duże ''A-Z'').
**Argumenty funkcji:** tablica znakowa ''t'' zawierająca napis do zaszyfrowania \\
**Wartość zwracana:** adres tablicy 't' zawierającej zaszyfrowany tekst \\
Napisz program, który przeczyta linię tekstu se standardowego wejścia, zaszyfruje tekst za pomocą funkcji ''szyfr()'' a następnie wypisze wynik na ekranie. Zakładamy, że linie tekstu nie będą dłuższe niż 1000 znaków.
Przykładowo dla podanego tekstu:
Ala ma kota
na ekranie pojawi się
Dkd pd nsxd
**Dla chętnych**
* rozszerz funkcję ''szyfr()'' o możliwość zamiany znaków w tekście na znaki przesunięte o dowolną liczbę całkowitą w alfabecie. Wartość ta stanowi kolejny argument funkcji. Znaki w alfabecie zamieniane są cyklicznie. Podanie wartości ujemnej odpowiada przesunięciu znaków w przeciwną stronę w alfabecie i w efekcie deszyfrację wiadomości zakodowanej taka samą wartością dodatnią.
* niech program działa nieprzerwanie dla dowolnej liczby wprowadzonych linii aż do pojawienia się pustej linii. Każda kolejna linia wczytana na wejściu jest wypisywana w zaszyfrowanej postaci.
==== Zadanie - Odwracanie napisów =====
Napisz program, który odwraca kolejność znaków w liniach tekstu.
W tym celu zdefiniuj funkcję o nazwie ''odrwracanie()'', która w podanej tablicy znakowej odwróci kolejność wszystkich znaków w łańcuchu znakowym.
**Argumenty funkcji:** napis (tablica znakowa). Po wykonaniu funkcji znaki w napisie będą umieszczone w odwrotnej kolejności \\
**Wartość zwracana:** adres tablicy z odwróconym napisem\\
Napisz program, który czyta linie tekstu ze standardowego wejścia aż do napotkania końca pliku.
Każda linia wypisywana na ekranie z odwróconą kolejnością znaków. Zakładamy, że linie tekstu nie będą dłuższe niż 1000 znaków.
Do wczytywania linii tekstu możesz wykorzystać funkcję ''czytaj_linię()'' zdefiniowaną wyżej.
Przykład działania programu:\\
Ala ma kota
atok ma alA
a Ewa ma psa
asp am awE a