Napisy

edytuj

Napisy 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

edytuj

Napisy 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

edytuj

Literały zwykłe, WYSIWYG i szesnastkowe

edytuj

Najczęś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[]

edytuj

Aby 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

edytuj

Do 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

edytuj

Z 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

edytuj

Ję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

edytuj

bool 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

edytuj

int 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

edytuj

const(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

edytuj

int 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

edytuj

string 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

edytuj

string 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

edytuj

immutable(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

edytuj

immutable(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

edytuj

String 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

edytuj

bool 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

edytuj

string 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

edytuj

string insert(string s, size_t index, string sub);

Wstawia ciąg znaków sub do napisu s w miejscu określonym przez index.