Opowieść o programowaniu w Adzie



Pobieranie 0.69 Mb.
Strona10/16
Data28.04.2016
Rozmiar0.69 Mb.
1   ...   6   7   8   9   10   11   12   13   ...   16

Typ łańcuchowy


Zapoznaliśmy się już z typami znakowymi character i wide_character. W praktyce jednak częściej niż pojedynczych znaków używamy ich ciągów. Ciągiem takim jest np. imię, nazwisko... Przydatny byłby więc typ pozwalający na przechowanie danych tego rodzaju w postaci jednej zmiennej, a nie np. wielu pojedynczych zmiennych typu character. Powyższe oczekiwania spełniają dwa zdefiniowane w Adzie typy: string obejmujący ciągi znaków (inaczej łańcuchy) złożone z elementów typu character oraz wide_string obejmujący ciągi znaków należących do typu wide_character. Zmienne tych typów deklarujemy następująco:
nazwisko : string(1..20);

imie : string(5..21);

PESEL : string(1..11);

jakis_wide_string : wide_string(1..10);


czyli, mówiąc ogólnie, piszemy:
zmienna_łańcuchowa :

string (dolne_ograniczenie_indeksu .. górne_ograniczenie_indeksu);


lub
zmienna_łańcuchowa : wide_string
(dolne_ograniczenie_indeksu .. górne_ograniczenie_indeksu);
gdzie ograniczenia indeksu muszą byc liczbami typu positive, przy czym ograniczenie dolne powinno być mniejsze od ograniczenia górnego (jeżeli nie jest, deklarowany jest łańcuch pusty).

Jako łańcuch traktowany jest dowolny ciąg znaków ujęty w apostrofy, np.


"Ada95" "1134" "A+B=C" "Jan Kowalski" ""
Ostatni z łańcuchów jest łańcuchem pustym (zapisany został jako dwa następujące po sobie cudzysłowy, między którymi nie stoi żaden znak). Jeżeli natomiast chcemy, aby znak cudzysłowu był elementem łańcucha, musimy oznaczyć go przez dwa cudzysłowy nastepujące po sobie, np.

"Adam Mickiewicz jest autorem ""Pana Tadeusza"".".


Występujące w deklaracji ograniczenia indeksu określają długość łańcucha oraz sposób numerowania jego elementów. Obrazowo zmienną zadeklarowaną

imie : string (1..8):="Karolina";

możemy przedstawić


'K'

'a'

'r'

'o'

'l'

'i'

'n'

'a'

1

2

3

4

5

6

7

8

Chcąc nadać zmiennej imie nową wartość musimy pamiętać, że wolno nam podstawić jedynie łańcuch o długości takiej, jak podana w deklaracji. Zatem nie możemy napisac na przykład


imie := "Anna";

imie := "Klementyna";


ale możemy
imie := "Polikarp";

imie := "Anna ";


O zadeklarowanych rozmiarach łańcucha mogą nas poinformowac odpowiednie atrybuty. I tak:


zmienna_łańcuchowa'first

zwraca liczbę będącą dolnym ograniczeniem indeksu łańcucha

zmienna_łańcuchowa'last


zwraca liczbę będącą górnym ograniczeniem indeksu łańcucha

zmienna_łańcuchowa'range

zwraca zakres indeksu łańcucha (ograniczenie_dolne .. ograniczenie_górne) - jest odpowiednikiem napisania zmienna_łańcuchowa'first .. zmienna_łańcuchowa'last

zmienna_łańcuchowa'length

zwraca długość danego łańcucha (zadeklarowaną ilość znaków, czyli ograniczenie_górne minus ograniczenie_dolne).

Mając łańcuch możemy wykonywac działania na jego elementach - znakach, oraz na fragmentach - podłańcuchach. Przy wyodrębnianiu ich z łańcucha wykorzystujemy fakt istnienia indeksu (ponumerowania znaków). Do znaku stojącego w łańcuchu odwołujemy się pisząc


zmienna_łańcuchowa (pozycja_w_łańcuchu),
natomiast do podłańcucha
zmienna_łańcuchowa

(pozycja_znaku_początkowego .. pozycja_znaku_końcowego).
Daje nam to możliwość zamiany czy wypisywania fragmentów łańcucha. Mając na przykład
imie : string (1..8) := "Karolina";
i podstawiając
imie(1):='C';

imie(8):= 'e';


dostaniemy łańcuch "Caroline", natomiast podstawiając
imie(3 ..5):="cia"
zmienimy łańcuch wyjściowy na "Karolcia".
Należy zwrócić uwagę na fakt, iż napisanie imie(1) oraz imie(1..1) oznacza dwie różne rzeczy. Pierwsze - to litera 'K', czyli znak (element typu character), drugie natomiast - "K" - łańcuch o długości jeden (należący do typu string).

Jeżeli przy wybieraniu fragmentów łańcucha (zarówno znaków, jak i podłańcuchów) przekroczymy dolne bądź górne ograniczemie indeksu, to zgłoszony będzie błąd - Constraint_Error.

Możliwe jest łączenie łańcuchów ze sobą. Operacja ta nosi miano konkatenacji. Możemy np. napisać
s1 : string (1..3) := "Jan";

s2 : string (1..5) := "Nowak";

s3 : string (1..9) := s1&' '&s2;
co spowoduje nadanie łańcuchowi s3 wartości "Jan Nowak".

Do łączenia łańcuchów służy operator &. Zezwala on na dodawanie do siebie nie tylko łańcuchów, ale i znaków (w powyższym przykładzie dołączyliśmy spację), jednak wynik zawsze jest typu string:


"Jan" & "Kowalski" daje "JanKowalski"

"Jan" & ‘K’ daje "JanK"

'a' & 'b' daje "ab"

'+' & "12" daje "+12".


Łańcuch będący wynikiem konkatenacji ma długość równą sumie długości jego składników (tzn. łączonych łańcuchów), można go podstawić jedynie pod zmienną łańcuchową odpowiedniej długości. Natomiast numeracja znaków w poszczególnych łańcuchach nie ma żadnego znaczenia:

l1 : string (1..3) := "Ala";

l2 : string (10 .. 11) := "ma";

l3 : string(2 .. 5) := "kota";

l4 : string(121 .. 132):= l1 & ' ' & l2 & ' ' & l3;
Za wprowadzanie i wyprowadzanie znaków odpowiadają procedury umieszczone w pakiecie ada.text_io. Procedura put wypisuje łańcuch lub jego część
imie : string(1..8) := "Karolina";

...


put (imie); -- wypisze Karolina

put(imie(1..5)); -- wypisze Karol


natomiast do wczytania zmiennej łańcuchowej używamy procedur get lub get_line. Napisanie
get(zmienna_łańcuchowa)
wymaga podania łańcucha o długości dokładnie takiej, jak zadeklarowana zmienna, natomiast
get_line(zmienna_łańcuchowa, zmienna_całkowita)
pozwala na podanie łańcucha o długości mniejszej bądź równej długości zadeklarowanej. Wprowadzanie trwa do naciśnięcia klawisza (lub do momentu, gdy wprowadzany ciąg znaków osiągnie zadeklarowaną długość). Pod zmienną_całkowitą podstawiana jest rzeczywista długość wprowadzonego łańcucha.
Łańcuchy można porównywać ze sobą używając operatorów <, <=, >, >=, =, /=. Operacja ta jest wykonywana zarówno dla łańcuchów o jednakowej, jak i o różnej długości, a porównywane są kolejne ich znaki . Prawdziwe są następujące zależności:
string'("Jan") <= string'("Jaroslaw")

wide_string'("Ewa") >wide_string'("Anna")

string'("Jan") < string'("Janusz")
Jak widać, w przypadku porównywania łańcuchów o których nie wiemy, do jakiego typu należą, konieczne jest określenie tegoż typu w celu uniknięcia niejednoznaczności.

Warto pamiętać również o możliwości zamiany liczby (lub danej innego typu) na typ string i odwrotnie. Służą do tego (omawiane juz w podrozdziale “Atrybuty typów”) atrybut T’image, zamieniający element typu T na odpowiadający mu łańcuch, oraz T’value, zamieniający łańcuch na element należący do typu T.

-- program wypisuje pewne dane osobowe

-- na podst. podanego numeru PESEL

with ada.text_io;

use ada.text_io;


procedure pr33 is
PESEL : string(1..11);
begin
put("Podaj swoj numer PESEL > ");

get(PESEL);

new_line;

put_line("Powiem Ci, czego dowiedzialem sie o Tobie:");

put(" ...urodziles sie " & pesel(5..6) & '.' & pesel(3..4) &

'.' & "19" & pesel(1..2) & " roku" );

new_line;

put(" ...jestes ");

if integer'value(pesel(10..10)) mod 2 = 0 then

put("kobieta");

else

put("mezczyzna");



end if;
end pr33;

-- przyklady operacji na stringu

-- na przyklad dopelnianie

-- koncowki lancucha spacjami

-- oraz zamiana malych liter na duze

with ada.text_io,ada.integer_text_io;

use ada.text_io,ada.integer_text_io;
procedure pr34 is
imie, nazwisko : string(1..40);

d1,w1,poz : integer;


begin

put_line("Program wypisze ozdobna wizytowke ");

-- wczytanie imienia i umieszczenie go -- w srodku lancucha

put("Podaj imie : ");

get_line(imie,d1);

w1:=(imie'length-d1)/2;

imie(w1+1..w1+d1):=imie(1..d1);

for i in 1..w1 loop

imie(i):=' ';

end loop;

for i in w1+d1+1 .. imie'length loop

imie(i):=' ';

end loop;

--wczytanie nazwiska i umieszczanie go -- w srodku lancucha

put("Podaj nazwisko : ");

get_line(nazwisko,d1);

w1:=(nazwisko'length-d1)/2;

nazwisko(w1+1..w1+d1):=nazwisko(1..d1);

for i in 1..w1 loop

nazwisko(i):=' ';

end loop;

for i in w1+d1+1 .. nazwisko'length loop

nazwisko(i):=' ';

end loop;

-- zamiana malych liter na duze

for i in 1..nazwisko'length loop

poz:=character'pos(nazwisko(i));

if poz>=character'pos('a') and poz<=character'pos('z') then

nazwisko(i):=character'val(poz-32);

end if;


end loop;

-- wypisanie wizytowki

for i in 1..42 loop put('*');end loop;

new_line;

put('*'& imie & '*');

new_line;

put('*' & nazwisko & '*');

new_line;

for i in 1..42 loop put('*');end loop;

end pr34;


Zwróćmy uwagę na występujący w programie pr33 zapis łańcucha o długości przekraczajacej długość jednej linii:
put ("To jest baaaaaaaaaaaaaaaaaaaaaaaaaaaaaardzo dlugi lancuch " &

"a moze nawet jeszcze dluuuuuuuuuuuuuuuuuuuuuuzszy lancuch " &

"i jak widac jego zapis nie zmiescil się w jednej linijce " &

"ale i tak na ekranie bedzie wygladal inaczej niz tutaj...");


Dotychczas używaliśmy łańcuchów o konkretnej, ustalonej długości. Niejednokrotnie jednak przydatna byłaby możliwośc użycia łańcuchów, których długość zostanie określona dopiero w trakcie wykonywania programu. Istnieje kilka sposobów rozwiązania tego problemu. Jednym z nich jest zadeklarowanie zmiennej łańcuchowej jako należącej do typu string (bez podawania ograniczeń indeksu) i przypisanie jej żądanej wartości, np.
x : string := integer’image(N);
gdzie N jest zmienną typu całkowitego o wcześniej przypisanej wartości (zob. rozdział “Podprogramy” w dalszej części książki). Zmienna łańcuchowa x w niejawny sposób przyjmuje długość taką, jak łańcuch będący zapisem liczby N. Niestety, długości tej nie można już zmienić w trakcie działania programu:
N : integer := 10;

x : string := integer’image (N); -- x przyjmie wartość " 10"

-- (wiodąca spacja! - liczba jest dodatnia)

....


N := 120;

x:= integer’image(N);


Ostatnia instrukcja spowoduje wystąpienie błędu Constraint_Error (próbujemy wstawić łańcuch czteroznakowy - " 120" do zmienne łańcuchowej mogącej się składać z co najwyżej trzech znaków). Przykład ten może zrazu wydawać się dziwny, ale zobacz rozdział “Bloki” w dalszej części książki.

Inną - mniej elegancką - metodą pozwalającą na używanie łańcuchów o “określanej w czasie wykonania programu długości” jest wstawianie wprowadzanego ciągu znaków do zmiennej łańcuchowej o określonej długości i dopełnianie reszty spacjami (ich ilość przeliczana jest podczas wykonywania programu). Podobną operację widzieliśmy w programie pr34.


-- przyklady wypisywania lancucha

-- jak wypisac ladnie, a jak brzydko

with ada.text_io;

use ada.text_io;


procedure pr35 is
str:string(1..60);

n:integer;


begin

put("Podaj napis (do 60 znakow) >");

get_line(str,n);

new_line;

put_line("Lancuch od 1-go do " &

integer'image(n) &"-go znaku: ");

put_line(str(1..n));

put_line("Caly lancuch: ");

put_line(str);

put_line("Teraz dopelniam koncowke spacjami... ");

for i in n+1..str'last loop

str(i):=' ';

end loop;

put_line("I ponownie caly lancuch - zakoncze go [*]: ");

put(str);put_line("[*]");

put("Prawda, ze ladniejszy?...");

end pr35;
W powyższym programie wypisywanie podłańcucha str(1..n) i - za drugim razem - str daje (na ekranie) poniekąd ten sam efekt, jednak w drugim przypadku po wypełnieniu reszty łańcucha spacjami nie musimy pamiętać ilości wprowadzonych znaków, co w dłuższych programach nie jest bez znaczenia. Bez dopisania spacji końcówka łańcucha str wypełniona będzie przypadkowymi znakami stanowiącymi interpretację aktualnej zawartości odpowiednich komórek pamięci. Po napisaniu

put(str);

te znaki również zostałyby wyświetlone na ekranie.
Omówiliśmy tutaj jedynie podstawowe operacje na typie string. Rozszerzenie przedstawionych możliwości oferują pakiety Ada.Strings i Ada.Vstrings (zob. rozdział... ) @?

1   ...   6   7   8   9   10   11   12   13   ...   16


©absta.pl 2016
wyślij wiadomość

    Strona główna