D/Napisy
Napisy
edytujNapisy w języku D są po prostu tablicami znaków. Do ich reprezentacji można używać typu char[] (string również istnieje, ale jest tylko aliasem do typu invariant(char)[]). Ciągi znaków domyślnie są tylko do odczytu (invariant). Dlatego w celu zapisania ich do zmiennej typu char[] wymagane jest utworzenie zapisywalnej kopii używając własności tablic dup. Dodatkowo dla kodowań UTF-16 oraz UTF-32 przeznaczone są typy wchar[] oraz dchar[].
Kodowanie napisów w D
edytujNapisy w D są kodowane w systemie Unicode. Nie są również zakończone znakiem \0, dlatego - kiedy zakończenie zerem jest wymagane (a tak może być w niektórych funkcjach z C) to należy je dopisać.
Domyślnie napisy są kodowane w UTF-8 i są zapisywane w tablicach char[]. Możliwe jest również użycie kodowań UTF-16 (typ wchar[]) oraz UTF-32(dchar[]).
Typy literałów
edytujLiterały zwykłe, WYSIWYG i szesnastkowe
edytujNajczęściej ciągi znaków zapisujemy w cudzysłowie, podobnie jak w innych językach programowania. Takie łańcuchy respektują sekwencje ucieczki i łamania wierszy:
"ab " // Ten łańcuch zawiera trzy znaki: a, b, i łamanie wiersza.
"ab\n" // Ten tak samo.
Oprócz tego D oferuje jeszcze inne typy literałów - łańcuchy WYSIWYG oraz szesnastkowe. Łańcuch WYSIWYG ignoruje sekwencje ucieczki, czyli - zgodnie z zasadą WYSIWYG (What You See Is What You Get = "To, co widzisz, jest tym, co dostajesz") - zawiera te znaki, które wpiszemy. Takie literały poprzedza się prefiksem r lub umieszcza między znakami `:
r"ab\n" // Łańcuch WYSIWYG. Zawiera 4 znaki - a, b, \ oraz n. `ab\n` // To też jest łańcuch WYSIWYG.
Łańcuch szesnastkowy umożliwia nam wprowadzanie znaków za pomocą kodów szesnastkowych. Poprzedzane są literą x:
x"af 20 3b" // Ten łańcuch zawiera znaki o kodach 0xaf (g), 0x20 (spację) oraz 0x3b (średnik).
Łańcuchy szesnastkowe ignorują białe znaki, więc można je wstawiać dla zwiększenia czytelności.
Literały char[], wchar[] i dchar[]
edytujAby określić typ danych reprezentowany przez literał, możemy dopisać przyrostek za cudzysłowem zamykającym:
"Ten łańcuch jest typu char[] (UTF-8)"c "Ten łańcuch jest typu wchar[] (UTF-16)"w "Ten łańcuch jest typu dchar[] (UTF-32)"d
Jeżeli nie podamy żadnego przyrostka, łańcuch będzie typu char[].
Porównywanie napisów
edytujDo porównywania napisów używamy tych samych operatorów, co do porównywania liczb.
string c = "hello"; if (c == "hello") { writefln("hi"); // Wypisze "hi" }
Napisów możemy również używać w instrukcji switch.
switch (napis) { case "hello": writefln("hi"); break; case "czesc": writefln("hej!"); break; default: writefln("cos calkiem innego"); }
Wycinanie
edytujZ racji, że napis jest tablicą, wycinanie przebiega w identyczny sposób, jak w innych rodzajach tablic:
string tekst = "jakis tekst przykladowy"; string fragment = tekst[6 .. 11]; // fragment będzie zawierał: "tekst"
Moduł std.string
edytujJęzyk D oferuje również sporo funkcji przeznaczonych do wykonywania operacji na napisach. Funkcje te zawarte są w module std.string. Oto najważniejsze elementy tego modułu:
iswhite() - Sprawdzanie, czy znak jest biały
edytujbool iswhite(dchar c);
Funkcja iswhite() służy do sprawdzania, czy dany znaj jest białym znakiem. Obsługuje wszystkie typy znakowe: char, wchar i dchar:
bool a = iswhite('a'); // false; bool b = iswhite('\n'); // true;
icmp() - Porównywanie ignorujące wielość liter
edytujint icmp(in char[] s1, in char[] s2);
Ta funkcja pozwala porównywać napisy ignorując wielkość liter. Zwracane wartości:
- <0, jeśli s1 jest mniejsze
- 0, jeśli s1 = s2
- >0, jeśli s2 jest mniejsze
Dokładniej, funkcja porównuje znaki na kolejnych pozycjach. Jeżeli na którejś pozycji są znaki są różne, zwraca różnicę kodów odpowiadających znaków z napisów s1 i s2. Jeżeli na wszystkich pozycjach znaki są takie same, zwraca zero.
toStringz() - Konwersja na ciągi znaków w stylu C
edytujconst(char)* toStringz(const(char)[] s);
Funkcja toStringz() konwertuje ciąg znaków do postaci znanej z C. Wynikowy ciąg znaków otrzymujemy w postaci stałej typu char*. Jest on również zakończony zerem.
find(), rfind(), ifind(), irfind() - wyszukiwanie w napisach
edytujint find(in char[] s, dchar c);
int ifind(in char[] s, dchar c);
int rfind(in char[] s, dchar c);
int irfind(in char[] s, dchar c);
int find(in char[] s, in char[] sub);
int ifind(in char[] s, in char[] sub);
int rfind(in char[] s, in char[] sub);
int irfind(in char[] s, in char[] sub);
Powyższe osiem funkcji umożliwia wyszukiwanie znaków lub ciągów znaków w napisie. Argument s to ciąg znaków, w którym chcemy znaleźć sekwencję, zaś jako argument c lub sub podajemy szukany znak lub wyrażenie.
Funkcje find oraz ifind zwracają miejsce pierwszego wystąpienia szukanego wyrażenia, a rfind oraz irfind - ostatniego. Jeżeli wyrażenie nie zostanie znalezione, zwrócona zostanie wartość -1.
Funkcje o nazwach rozpoczynających się od "i" ignorują wielkość liter.
char[] tekst = "Hello World"; int index;
index = find(tekst, 'o'); // 4 index = rfind(tekst, 'o'); // 7 index = ifind(tekst, 'W'); // 6 index = irfind(tekst, 'W'); // też 6 index = find(tekst, "world"); // -1, wielkość liter się nie zgadza index = ifind(tekst, "world"); // 6, ifind ignoruje wielkość liter
tolower(), toupper(), capitalize(), capwords() - zamiana wielkości liter
edytujstring tolower(string s);
string toupper(string s);
string capitalize(string s);
string capwords(string s);
Te funkcje służą do zamiany wielkości liter:
- tolower - zamienia cały napis na małe litery.
- toupper - zamienia CAŁY NAPIS NA DUŻE LITERY.
- capitalize - zamienia Pierwszą literę na dużą, resztę na małe.
- capwords - zamienia Pierwszą Literę Każdego Wyrazu Na Dużą, pozostałe na małe.
join() - łączenie ciągów znaków
edytujstring join(in immutable(char)[][] words, string sep);
Ta funkcja łączy ciągi znaków w jeden, rozdzielając je napisem zawartym w argumencie sep. Pierwszy argument musi być tylko do odczytu:
invariant(char)[][] skladniki = ["Hello", "World"]; string res = join(skladniki, " "); // res = "Hello World"
split() - rozbijanie napisu na słowa
edytujimmutable(char)[][] split(string s);
immutable(char)[][] split(string s, string delim);
Powyższe funkcje zwracają w tablicy słowa składające się na dany napis. Pierwsza za "rozdzielacz" słów uznaje białe znaki, druga - parametr delim.
invariant char[][] words = split("Hello World"); // words = ["Hello" "World"]
splitlines() - rozbijanie napisu na linie
edytujimmutable(char)[][] splitlines(string s);
Rozbija napis na linie. Znaki \n oraz \r nie są zawarte w liniach.
strip(), stripl(), stripr() - usuwanie białych znaków na początku lub końcu
edytujString stripl(String)(String s);
String stripr(String)(String s);
String strip(String)(String s);
Uwaga - są to funkcje szablonowe
Usuwa białe znaki na początku lub końcu napisu:
- stripl - tylko na początku
- stripr - tylko na końcu
- strip - po obu stronach
string res = strip!(string)(" Hello World "); // res = "Hello World"
startsWith(), endsWith() - sprawdzanie, czy łańcuch zaczyna się lub kończy odpowiednim ciągiem znaków
edytujbool startsWith(A1, A2)(A1 longer, A2 shorter);
bool endsWith(A1, A2)(A1 longer, A2 shorter);
Uwaga - są to funkcje szablonowe
Sprawdza, czy wartość longer typu A1 zaczyna się (startsWith) lub kończy (endsWith) wartością shorter typu A2.
bool res = startsWith!(string, string)("Hello World", "Hello"); // res = true
replace() - zamienianie fragmentu ciągu znaków na inny
edytujstring replace(string s, string from, string to);
Zamienia ciąg znaków from na to w zmiennej s.
insert() - wstawianie ciągu znaków do innego
edytujstring insert(string s, size_t index, string sub);
Wstawia ciąg znaków sub do napisu s w miejscu określonym przez index.