4 TurboPascal Struktury i typy danych

background image

Struktury i typy danych

Do czego służą

W Turbo Pascalu można używać różnych formatów danych, takich jak liczba, napis, znak.
Istnieją różne typy, niektóre zajmują mniej pamięci i są mniej dokładne, inne zajmują więcej
pamięci, za co mają większą precyzję. Te dłuższe zazwyczaj wymagają też więcej czasu
pracy procesora. Podstawowe typy danych zostały opisane w rozdziale Pierwsze programy,
Zmienne.

Struktury danych pozwalają komputerowi w łatwiejszy sposób przetwarzać informacje,
szybciej zapisywać do pliku, lepiej organizować w pamięci, szybciej wyszukiwać i ułatwić
pracę programiście.

Tablice

W bibliotece znajdują się szafki z kartotekami skatalogowanych książek. W każdej szafce są
takie kartoteki. Tych szafek jest dość dużo. Są poustawiane obok siebie. Każda szuflada ma
swój numer, czy literę. Są w nich tylko kartoteki. Jeśli biblioteka jest duża, regałów z
kartotekami może być wiele.

Tablice są podobne do szuflad bibliotecznych. Tablica składa się z wielu 'schowków',
poustawianych obok siebie w pamięci. W tablicy znajdują się tylko zmienne i to zmienne
jednego typu. Każdy element tablicy ma swój indeks. Tablice mogą być wielowymiarowe, nie
tylko w poziomie, ale i w pionie a nawet wgłąb.

Do czego służą? Przechowują grupy danych. Mogą zawierać listę liczb. Mogą zawierać
kartoteki pracowników -ich nazwiska, imiona, bądź całe rekordy z danymi.

Aby je zadeklarować używa się w sekcji var wyrażenia: Array[{min}..{max}] of {...}

background image

var tablica : Array[0..30] of Integer;

tablica_imion : Array[1..10] of string;

tab2 : Array[0..30, 1..3] of Integer; {tablica dwuwymiarowa}

A jak się odwoływać w programie do tablic?


Tablica[1] := 1; {zwykłe podstawienie}

for i:= 0 to 30 do {w pętli...}
tablica[i] := 0; {wyzerowanie całej tablicy}

tab2[i][1] := x; {dwuwymiarowa}
tab2[i, 1] := x; {drugi sposób}

{*****************************************}
{wczytanie i wyświetlenie 10 imion w pętli}

for i:= 1 to 10 do {w pętli...}
begin
Write('Podaj ', i, ' imię: ');
ReadLn(tablica_imion[i]);
end;

WriteLn('Wpisane imiona:');

for i:= 1 to 10 do {w pętli...}
begin
Write(tablica_imion[i]);
end;

Łatwo zauważyć, że do tablicy można się odwoływać za pomocą indeksu. I właściwie o to
chodzi w używaniu tablic. Pozwalają znacznie zaoszczędzić czasochłonne wklepywanie kodu.

Przypuśćmy, że w tablicy liczb Integer, o nazwie tablica chcesz znaleźć wartość największą.
Jak to zrobić? Trzeba przejść przez całą tablicę i sprawdzić, czy kolejny element jest większy
nich dotychczas największy. Uwaga, na początku elementem dotychczas największym musi
być ten, który jest pierwszym elementem tablicy, nie 0. Dlaczego? Ponieważ gdy tablica
będzie zawierała jedynie liczby ujemne, program uważałby, że największą dotychczasową
wartością jest 0, a tak nie będzie.


var tablica : Array[0..30] of Integer;
i, max : Integer;

background image


begin
{tutaj można wypełnić tablicę jakimiś wartościami, np. losowymi}
Randomize; {Inicjowanie losowania}

for i:= 0 to 30 do {w pętli...}
tablica[i] := Random(100) - Random(100); {losowanie w zakresie -99..+99}

max := tablica[0];
for i:= 1 to 30 do {w pętli...}
begin
{Jeśli największy dotychczas element jest mniejszy niż badany...}
if max < tablica[i] then
max := tablica[i];{zmień dotychczas największy}
end;

{tu możesz wyświetlić max}
WriteLn('Max: ', max);
end.

Własne typy danych

Czasami zachodzi potrzeba utworzenia własnego typu -tzw. rekordu, który będzie
przechowywał wymyślone przez nas dane. Przypuśćmy że chciałbyś zbudować prostą bazę
danych zawierającą imiona i nazwiska swoich klientów. Zamiast przechowywać wszelkie
dane w osobnych tablicach np.


const
MaxDanych = 200;

var
{imiona - tablica o rozmiarze MaxDanych elementów }
imiona : array[0..MaxDanych-1] of string[20];
nazwiska : array[0..MaxDanych-1] of string[30];
telefony : array[0..MaxDanych-1] of string[20];

{...}
{odwoływanie}

imiona[10]:='Moje Imię';
nazwiska[10]:='Moje Nazwisko';
telefony[10]:='0700 00 000';

Można pogrupować je blisko siebie. W taki sposób by znajdowały się obok siebie w pamięci
(jest bardziej fachowo).

background image

Można to zrobić choćby tak:


const
MaxDanych = 200;

type
TDaneOsobowe = record
imie : string[20];
nazwisko : string[30];
telefon : string[20];
rok_ur : integer;
end;

var
Dane : array[0..MaxDanych-1] of TDaneOsobowe;

{…}
{odwoływanie}

Dane[0].imie := 'Moje imie';
Dane[0].nazwisko := 'Moje nazwisko';
Dane[0].telefon := '0 700 00 000';
Dane[0].rok_ur := 1999;

{lub za pomocą with – uproszczenie}
with Dane[0] do
begin
imie := 'Moje imie';
rok_ur := 1999;
end;

W przykładzie zademonstrowano korzystanie z polecenia with - które dla każdego elementu
wewnątrz dodaje przedrostek, w typ wypadku Dane[0]. Dzięki temu poleceniu możemy
znacznie skrócić kod.

Do tablicy własnego rekordu można odnosić się jak do każdej innej tablicy. Można
przeglądać tą tablicę za pomocą pętli i zmiennej iterowanej (zwiększanej).

Wskaźniki w turbo pascalu (pointer)

background image

Wskaźniki przypominają spis treści w grubej książce. Gdybyś podczas rozmowy telefonicznej
chciał wskazać koledze konkretne miejsce w jakiejś publikacji, co zrobisz? Czy powiesz mu,
otwórz swoją książę na zdaniu... I tu zaczniesz cytować, czy raczej podasz numer strony?
Oczywiście numery stron są lepsze, bo ułatwiają szybie odnajdywanie miejsc. Tak samo
wskaźniki w programowaniu -pozwalają przeszukiwać spore ilości danych bez wertowania
całej pamięci. Podobnie jak przy rozmowie przez telefon, tak samo przy porozumiewaniu się
między procedurami w programie potrzeba jak najściślejszych, ale jak najszybszych
informacji.

Wskaźniki to adresy pamięci, które pokazują komputerowi miejsce gdzie znajdują się jakieś
dane. Możesz przykładowo przechowywać w pamięci wskaźnik na obrazek bitmapowy,
podczas gdy przechowywanie obrazu w tablicy byłoby niezbyt praktyczne. Pamięć do której
odnoszą się wskaźniki można w każdej chwili zwalniać, deklarować i zmieniać.

Bez wskaźników nie byłoby możliwe nieograniczone tworzenie nowych danych, np. w
słowniku. Gdyby nie wskaźniki mielibyśmy z góry określoną liczbę słów, które słownik
byłby w stanie zapamiętać. W grach komputerowych, liczba ludzików, zbudowanych
elementów w strategii, zawsze byłaby z góry ograniczona. Nie moglibyśmy w systemie
uruchomić większej liczby programów niż zaplanowano.

Wskaźniki mogą wskazywać na dowolny obszar pamięci, a adres ten można zmieniać. Są
pomocne podczas alokacji pamięci. Kiedy chcemy ją zadeklarować w czasie trwania
programu, funkcja GetMem zwraca nam właśnie wskaźnik -czyli miejsce gdzie będziemy
mogli wpisywać swoje dane. Gdybyśmy spróbowali wspisać swoje dane bez wcześniejszego
zarezerwowania pamięci, w najlepszym wypadku zakończyłby się nasz program, w gorszym
zawiesilibyśmy komputer.



Budowa wskaźników*

Ze względu na ryzoko zawieszenia programu wskaźniki są traktowane jako typy, które należy
umiejętnie stosować. Wskaźniki na ogół zbudowane są z 4 bajtów. Pierwsze 2 określają
segment danych, kolejne 2 ofset.

Pamięć konwencjonalna (pierwszy 1MB pamięci komputera) podzielony jest na segmenty po
16KB każdy. Tak więc 1 segment ma adres 0, drugi 1, trzeci 2, itd... Ofset to przemieszczenie
względem segmentu. Dzięki ofsetowi możemy dojść do każdego jednego bajtu pamięci.
Adres typu pointer składa się z dwóch bajtów segmentu, dwóch ofsetu i jest najczęściej
zapisywany w kodzie szesnastkowym, dzięki czemu jest bardziej czytelny, np.

background image


$a000:00, $b800:00



Typ pointer

Typ wskaźników nazywa się pointer. Gdy jakąś zmienną zadeklarujesz jako poiner, będzie
ona wskaźnikiem. Wskaźniki mogą adresować różne typy zmiennych. Mogą adresować
liczby, napisy, tablice, itd. Gdy adresują konkretny typ, nie deklaruje się ich jako pointer,
tylko tworzy swój własny typ -o tym przeczytasz za moment.



Podstawianie wskaźników

Żeby wskaźnik wskazywał adres jakiejś zmiennej, możemy napisać:


var
wskaznik : pointer; {lub podobny typ}

{...}

wskaznik := @nazwa_zmiennej;

znacznik @ oznacza pobranie adresu zmiennej. Gdybyśmy chcieli teraz coś zapisać pod
wskazanym miejscem wystarczy wywołać wskazywane miejsce, za pomocą znaku ^


wskaznik^ := nowa_wartosc;

W podanym przykładzie trzeba by wskaźnik był zadeklarowany jako wskaźnik na liczbę.
Gdybyśmy bez rzutowania i bez określenia rodzaju wkaźnika próbowali mu podstawić
wartość wystąpiłby błąd "illegal assigment".

Jak zadeklarować wskaźnik na liczbę?
np.


type p_liczba = ^integer; {utworzenie nowego typu - wskaźnika na liczbę}
var liczba : p_liczba;
i : integer;

background image

begin
liczba := @i;
i:=2;
liczba^:=4;
end.

{teraz i = 4 a nie 2!}

Można ewentualnie potraktować typ pointer jako wskaźnik na liczbę co nazywa się
rzutowaniem -dzięki temu unikniemy błędu a powiemy kompilatorowi, że wpisujemy w
niego liczbę Integer


var liczba : pointer;
i : integer;

begin
liczba := @i;
i:=2;
integer(liczba^):=4;
end.


Document Outline


Wyszukiwarka

Podobne podstrony:
Typy danych i ich klasyfikacja, INFORMATYKA, Programowanie strukturalne i obiektowe, Semestr 1
Algorytmy i struktury danych Wykład 2 Typ danych,Proste typy danych
typy danych, Elektronika i Telekomunikacja, informatyka
lab10a, Typy danych - pliki
Java 03 Podstawowe typy danych
Lekcja jej struktura i typy
SQL Server 2005 typy danych
2 Typy danychid 19692 Nieznany
05 Normalizacja struktury bazy danych (AC)
!2 Pascal Typy Danych, szkoła VII LO, INFA
APP abstrakcyjne Typy Danych
20 typy danychid 21482 Nieznany (2)
Struktury i typy?nych
Typy danych, Skrypty, PK - materiały ze studiów, I stopień, SEMESTR 2, Geodezja, od Donia - geodezja
Programowanie i jezyk C Wyklad 01 Typy danych
APP 02 Typy Danych Podstawy 2010
Typy danych w MySQL
07. Typy danych w Delphi, Programowanie, Klasa II

więcej podobnych podstron