W12 Typy strukturalne cd Typ String ---------- Uwaga1: to nie jest standard Pascala! Tylko FreePascal, TP, BP, Delphi) Uwaga2: Niektóre implementacje (np. FreePascal, Delphi) dopuszczają drugą implementację napisów, dozwalającą na napisy o długości do 2GB, tu skupiamy się na tradycyjnej implementacji napisów (o długości do 255 znaków). Ten typ danych pozwala przechowywać napisy zmiennej długości. Maksymalną dozwoloną długość napisu ustalamy podczas kompilacji programu. Zmienne napisowe można deklarować na jeden z dwu poniższych sposobów: var s: String[ ]; lub var s: String; gdzie jest liczbą z przedziału 1..255. Druga postać deklaracji jest równoważna podaniu rozmiaru równego 255. Rozmiar podawany w deklaracji jest największą dopuszczalną długością napisu, zatem deklaracja var s: String[10]; oznacza, że zmienna s może przechowywać napisy dowolnej długości od 0 do 10. Napis długości 0 to napis pusty. Aktualną długość napisu podaje funkcja Length, jej argumentem jest napis. Można odwoływać się do poszczególnych znaków napisu, stosując taką samą składnię, jak w przypadku tablic. Poszczególne znaki napisu są indeksowane od 1. Oto przykład, fragment programu zamieniający wszystkie małe litery w napisie s na wielkie: var s: String; i: integer; {...} begin { ... } for i := 1 to Length(s) do s[i] := UpCase(s[i]); { ... } end; Funkcja UpCase (tylko niektóre implementacje Pascala) dostaje jako argument znak i jako wynik daje ten znak zamieniony na wielką literę (jeśli był literą, pozostałe znaki pozostawia bez zmian, przez literę rozumiemy tu literę alfabetu łacińskiego). Zwróćmy uwagę w tym przykładzie na to, że poszczególne znaki napisu można także zmieniać (a nie tylko odczytywać) i że są one typu char. Na zmienne napisowe można przypisywać napisy: s1 := 'To jest napis'; s2 := s1; lub można ich wartości wczytywać z wejścia: readln(s1); Kompilator zadba o to, by za długie napisy zostały obcięte do zadeklarowanej maksymalnej długości zmiennej napisowej. Uwaga na wczytywanie napisów operacją read(s)! Oczywiście można także wypisywać zmienne napisowe: writeln(s); Dla argumentów będących napisami zdefiniowano następujące operatory: = <> < <= > >= (porównania leksykograficzne) + (łączenie napisów) Na przykład: var s1, s2: String; begin s1 := 'ala '; s2 := 'ma kota'; if s1 < s2 then writeln('Jest mniejsze') Else writeln('Nie jest większe'); writeln(s1 + s2); end. Wypisze (kolejno): Jest mniejsze ala ma kota Uwagi: 1) Wynik operacji + jest obcinany do 255 znaków. 2) W przypisaniach := przypisywana wartość jest obcinana do maksymalnej długości napisu. 3) Typ String może być wynikiem funkcji. Typ String[n] dopiero po nazwaniu. W FreePascalu, TP/BP, Delphi zdefiniowano też wiele operacji działających na typie napisowym: function Copy(s: String; skąd: Integer; ile: Integer): String Daje podnapis s zaczynający się na pozycji skąd, mający ile znaków. Jeśli skąd jest większe niż długość napisu s, to wynikiem jest pusty napis. Jeśli od miejsca skąd do końca napisu jest mniej niż ile znaków, to kopiowane są wszystkie znaki do końca napisu. procedure Delete(var s: String; skąd: Integer; ile: Integer) Wycina z s ile znaków zaczynając od pozycji skąd. Jeśli napis s jest za krótki, usuwa wszystkie znaki do końca napisu. procedure Insert(s1: String; var s: String; gdzie: Integer) Wkleja do s napis s1 na pozycji gdzie. function Pos(co: String; s: String): Integer Daje pozycję pierwszego wystąpienia napisu co w napisie s (lub 0). Rozróżnia małe i wielkie litery. procedure Val(s: String; var wart: Integer lub Real; var kod: Integer) Stara się zamienić napis s na zapisaną nim liczbę. Jeśli się uda, przekazuje tę liczbę jako wart, zaś kod ustawia na 0, wpp. kod ma wartość <> 0. procedure Str(wart [: Szerokość [: LiczbaMiejscPoPrzecinku]], var s: String) Zamienia liczbę wart na jej postać tekstową i zapisuje ją w napisie s. Reasumując: zmienne napisowe są bardzo wygodnym środkiem do operowania na napisach. Jedyną niedogodnością jest to, że trzeba z góry określić maksymalny rozmiar napisu, i że nie może on być większy od 255. Implementacja zmiennych napisowych: Typ napisowy String[n] jest realizowany jako tablica: array [0..n] of Char Elementy tej tablicy od 1 do n służą do przechowywania znaków napisu, element o indeksie 0 służy do pamiętania długości napisu. Ponieważ typ Char odpowiada wartościom od 0 do 255, maksymalna długość napisów jest ograniczona do właśnie 255. Przykłady programów wykorzystujących typ napisowy Spróbujmy napisać własną funkcję zamieniającą liczby na napisy. Zrobimy to dla typu LongInt. ---> program wypliczb (zapis dziesiętny) ---> program wypliczb2 (zapis przy podstawie 2..10)