Operacje na tekstach
Length
Funkcja Length zwraca długość testowanego napisu. Za jej pomocą możesz ocenić długość
słowa wpisanego przez użytkownika Twojego programu.
Budowa znaku, kod ASCII
W pamięci komputera pojedyncze znaki 'char' są przechowywane jako jeden bajt. Jest 256
różnych znaków. Każdy z tych znaków ma swój kod liczbowy. W rzeczywistości w pamięci
są przechowywane właśnie te kody liczbowe zwane jako kod ASCII. W kodzie tym litera 'A'
ma wartość 65, 'B' 66, 'C' 67 itd. Małe litery zaczynają się od 97. 'a' ma kod 97, 'b' 98, 'c' 99
itd.
Po co te kody? Ułatwiają pracę. Np. pomagają sprawnie zmieniać wielkość liter (do kodu
znaku wystarczy dodać lub odjąć 32). Właściwości te przydadzą Ci jeszcze później.
Budowa napisu
Każdy napis -czyli zmienna typu string jest w pewien sposób zapisywana w pamięci
komputera. Składa się przeważnie z 256 bajtów. W Pascalu pierwszy z nich przechowuje
długość napisu, a reszta sam napis jako zbiór znaków typu 'char'.
Dla zmiennej o nazwie: 'napis' o wartości 'Ala ma kota' wygląda to tak:
Nr bajtu
0
1
2
3
4
5
6
7
8
9
10
11
Co przechowuje
Długość
A
l
a
m
a
k
o
t
a
napisu,
czyli
liczba
11
Programista ma dostęp do każdej z tych liter za pomocą odwołania takiego jak w tablicy. Gdy
chce wyświetlić pierwszą literę w tej zmiennej, może napisać
WriteLn(napis[1]);
Gdyby napisać tzw. rzutowanie (zmianę typu: char na byte) elementu o indeksie 0
WriteLn(Byte(napis[0]));
Otrzymamy 11, czyli to samo, co gdybyśmy napisali:
WriteLn(Length(napis));
Gdybyśmy chcieli więc wyświetlić ostatnią literę zmiennej napis, wystarczy napisać:
WriteLn(napis[Length(napis)]);
A dlaczego nie można wpisać WriteLn(napis[11]); ? To proste, możemy, ale nie zawsze by to
była ostatnia litera napisu, dlatego, bo zawartość zmiennej może przecież być inna! Gdy
piszemy programy, muszą być one zawsze elastyczne. Nie mogą działać tylko dla jednego
przez nas określonego założenia.
Jak zbadać ostatnią literę wczytanego z klawiatury imienia? Teraz jest to proste
ReadLn(napis);
WriteLn(napis[Length(napis)]);
Zmiana wielkości liter
W niektórych programach zachodzi potrzeba zmiany wielkości liter. Np. gdy użytkownik
wpisze swoje imię małą literą, może być miło zaskoczony, gdy komputer i tak wyświetli je
wielką literą.
Do zmiany wielkości znaku służy funkcja UpCase(ch : char); Zmienia ona jednak wielkość
pojedynczego znaku a nie całego napisu. Żeby zmienić wielkość całego napisu musimy to
zrobić ręcznie za pomocą pętli.
Jeśli chcemy zmienić pierwszą literę wczytanego napisu, można użyć:
ReadLn(napis);
napis[1] := UpCase(napis[1]);
WriteLn(napis);
A co jeśli chcemy zmienić cały napis na duży? Wystarczy dodać pętlę, a zamiast cyfry 1 w
powyższym przykładzie, zmienną, która będzie stopniowo zwiększana.
ReadLn(napis);
for i:=1 to Length(napis) do
napis[i] := UpCase(napis[i]);
WriteLn(napis);
Kopiowanie części napisu
Do kopiowania fragmentów napisu służy funkcja Copy(napis : string; start, dlugosc : Integer;
).
Oznacza to, że gdy ze zmiennej 'napis' o wartości 'Ala ma kota' chcemy skopiować do innej
zmiennej pierwsze 3 litery, używamy:
Zmienna := Copy(napis, 1, 3);
Możemy oczywiście wpisać
WriteLn(Copy(napis, 1, 3));
Najczęściej jednak, musimy najpierw sami wykryć miejsce, od którego zaczniemy
kopiowanie, potem długość szukanego słowa a dopiero zacząć kopiować.
Szkolne problemy
Odwrócenie liter
Jednym z często spotykanych problemów jest napisanie programu, odwracającego kolejność
liter w napisie.
Wystarczy użyć pętli, która podmieni znak z początku na znak z końca i na odwrót, potem
zrobi to ze znakiem następnym i następnym aż do... końca napisu? Nie! Gdyby pętla przeszła
dalej niż za połowę napisu, zaczęłaby znowu odwracać znaki, które przecież już zostały
odwrócone. Efektem nic by się nie zmieniło, choć program byłby napisany ogólnie
poprawnie. Pętla odwracająca musi iść od pierwszego znaku, tylko do połowy napisu.
Inny problem pojawi się z zamianą znaku z końca na początkowy I na odwrót. Jaki to
problem? Gdy za znak z początku podstawimy znak z końca, to co wstawimy na koniec?
Gdybyśmy wstawili teraz znak z początku, to już nie jest to znak, który był rzeczywiście na
poczatku. Trzeba po prostu najpierw zapamiętać znak, który jest na początku, potem na
początek wstawić znak z końca, a na koniec, ten zapamiętany.
var s : string;
tmp : char;
i : Integer;
begin
ReadLn(s);
for i := 1 to Length(s) div 2 do {pętla tylko do połowy napisu}
begin
tmp := s[i]; {kopiujemy znak z początku}
s[i] := s[Length(s) + 1 – i]; {wstawiamy znak z końca na początek}
s[Length(s) + 1 – i] := tmp; {na koniec wstawiamy kopię znaku z początku}
end;
WriteLn(s);
end.
Odwrócenie wyrazów
Żeby odwrócić kolejność wyrazów w napisie będziemy musieli wyszukiwać spacje od końca
napisu. Gdy znajdziemy spację, kopiujemy wyraz, który będzie za nią do miejsca, na którym
skończyliśmy ostatnio i wstawiamy skopiowany wyraz na koniec naszej nowej zmiennej.
Idziemy tak aż do pierwszego znaku w napisie.
var s, tmp : string;
i, koniec : Integer;
begin
ReadLn(s);
koniec := Length(s); {To jest numer ostatniego znaku na którym kończymy kopiowanie}
tmp := '';
for i := Length(s) downto 1 do {pętla od końca napisu do początku}
begin
if s[i] = ' ' then {jeśli znajdziemy spację}
begin
tmp := tmp + Copy(s, i + 1, koniec – i) + ' '; {doklejanie wyrazu na koniec}
koniec := i – 1;
end;
end;
tmp := tmp + Copy(s, 1, koniec);
WriteLn(tmp);
end.
Kasowanie słowa
Gdy chcemy skasować jakieś słowo trzeba po prostu skopiować wszystko inne.
var s, tmp, wyraz : string;
i, poczatek : Integer;
begin
WriteLn('Podaj napis:');ReadLn(s);
WriteLn('Ktory wyraz skasowac?');ReadLn(wyraz);
poczatek := 1; {To jest numer znaku od którego zaczynamy kopiowanie}
tmp := '';
for i := 1 to Length(s) do
begin
if s[i] = ' ' then
begin
if Copy(s, poczatek, i – poczatek)<> wyraz then {gdy nie kasowany}
tmp := tmp + Copy(s, poczatek, i – poczatek + 1); {kopiujemy}
poczatek := i + 1; {Będziemy zaraz kopiować od znaku za spacją}
end;
end;
if Copy(s, poczatek, Length(s) – poczatek + 1)<> wyraz then
tmp := tmp + Copy(s, poczatek, Length(s) – poczatek + 1);
WriteLn(tmp);
end.