Pobierz slajdy prezentacji multimedialnej (format PDF).
Transkrypt
Pobierz slajdy prezentacji multimedialnej (format PDF).
PODSTAWY PROGRAMOWANIA Andrzej Marciniak Prezentacja multimedialna przygotowana za pomocą systemu Corel® Presentations X3 Copyright © 2003-2016 by Andrzej Marciniak PP-4(1 z 88) Na poprzednim wykładzie ... ‚ przegląd konstrukcji języka Delphi Pascal (program, moduł, biblioteka, funkcje i procedury, klasy i obiekty, typy danych, zmienne, instrukcje) ‚ struktura programu i modułu ‚ podstawowe elementy języka (symbole podstawowe, słowa kluczowe i dyrektywy języka, identyfikatory, liczby, łańcuchy, literały logiczne, komentarze i separatory) PP-4(2 z 88) Na tym wykładzie ... ‚ typy danych i ich opis ‚definiowanie typów ‚typy proste (porządkowe, rzeczywiste) ‚typy łańcuchowe ‚typy strukturalne (tablicowe, rekordowe, zbiorowe, plikowe) PP-4(3 z 88) Definiowanie typów Każda zmienna występująca w programie (module, bibliotece łączonej dynamicznie) posiada swoją nazwę (identyfikator) i przyjmuje wartości z określonego zbioru. Zbiór ten nazywa się typem zmiennej. Typ zmiennej może być określony w deklaracji zmiennej (będzie dalej) lub w definicji typu. Jeśli zdefiniowano typ, to w deklaracji zmiennej można do niego odwołać się za pomocą identyfikatora typu. Stosowanie w programie (module, bibliotece łączonej dynamicznie) identyfikatorów typów (zamiast ich opisów) zwiększa czytelność programu oraz ułatwia jego strukturalizację. PP-4(4 z 88) Definiowanie typów W języku Delphi występują dwie kategorie typów: ‚ typy podstawowe, ‚ typy ogólne. Postacie i zakresy wartości typów podstawowych są niezależne od procesora i systemu operacyjnego, co oznacza, że nie zmieniają się one przy różnych implementacjach języka. Typy ogólne zależą od procesora i systemu operacyjnego. W obecniej wersji języka Delphi występują cztery rodzaje typów predefiniowanych, w których rozróżnia się typy podstawowe i ogólne. Są to niektóre typy całkowite i rzeczywiste oraz typy znakowe i łańcuchowe. PP-4(5 z 88) Definiowanie typów Typy dzielą się na: ‚ standardowe, ‚ niestandardowe. Typy standardowe są predefiniowane i nie wymagają żadnego opisu. Wszystkie typy wprowadzone przez programistę muszą zostać przez niego opisane. Opis taki może być używany bez uprzedniego nadania temu opisowi nazwy (np. w deklaracjach zmiennych) albo też może być podany w definicji typu. Definicja opisuje typ i jednocześnie przyporządkowuje mu identyfikator. PP-4(6 z 88) Definiowanie typów Składnia definicji typów jest następująca: type sekwencja-definicji-typów przy czym każdy element sekwencji definicji typów ma postać identyfikator-typu = oznaczenie-typu; gdzie oznaczenie typu jest opisem typu lub identyfikatorem typu (identyfikatorem typu w opisie typu może być identyfikator typu standardowego lub typu zdefiniowanego wcześniej). PP-4(7 z 88) Definiowanie typów Wystąpienie konstrukcji postaci type identyfikator-typu-1 = identyfikator-typu-2; powoduje, że typ określony za pomocą pierwszego identyfikatora będzie uważany za identyczny z typem podanym przez drugi identyfikator. Podczas wykonywania programu konsekwencją tego faktu będzie niemożliwość rozróżnienia typów zmiennych zadeklarowanych następująco: var zmienna-1 : identyfikator-typu-1; zmienna-2 : identyfikator-typu-2; PP-4(8 z 88) Definiowanie typów W celu rozróżnienia typów definiowanych przez inne typy, należy posługiwać się konstrukcją type identyfikator-typu-1 = type identyfikator-typu-2; która wymusza na kompilatorze utworzenie nowego, innego logicznie typu o nazwie określonej przez pierwszy identyfikator. Oczywiście zbiory wartości obu typów są takie same, a typ określony drugim identyfikatorem powinien być zdefiniowany wcześniej lub oznaczać identyfikator typu standardowego. PP-4(9 z 88) Definiowanie typów Do każdej definicji typu mogą być dołączone następujące dyrektwy języka (nazywa się je dyrektywami wskazówkowymi): platform - oznacza, że definiowany typ jest specyficzny dla określonego systemu operacyjnego i może nie być implementowany w innych systemach, library - oznacza ograniczenie typu do pewnej biblioteki, deprecated - oznacza, że definiowany typ jest przestarzały lub został zdefiniowany dla zgodności z wcześniejszymi wersjami języka. Dyrektywy te powodują wyłącznie wygenerowanie podczas kompilacji pewnych wskazówek lub ostrzeżeń. Mogą być stosowane także w deklaracjach zmiennych, deklaracjach i definicjach funkcji, procedur i metod, deklaracjach pól w rekordach i klasach oraz w nagłówkach modułów. PP-4(10 z 88) Typy proste Typy proste są podstawowymi typami języka Delphi i za ich pomocą określa się bardziej złożone struktury danych. Typy proste dzielimy na: # typy porządkowe, # typy rzeczywiste. Wszystkie typy proste składają się ze skończonego i uporządkowanego zbioru wartości. Dzięki temu możliwe jest m. in. wykonywanie na wartościach tych typów operacji porównań. PP-4(11 z 88) Typy proste Typy porządkowe Do typów porządkowych zaliczamy typy: ‚ ‚ ‚ ‚ ‚ wyliczeniowe, całkowite, znakowe, logiczne, okrojone. PP-4(12 z 88) Typy proste Typy porządkowe Dla wartości każdego typu porządkowego są określone wartości poprzednie i następne (z wyjątkiem wartości krańcowych). Z każdą wartością typu porządkowego jest skojarzona liczba porządkowa (wartość całkowita) jednoznacznie określająca jej umiejscowienie wśród wszystkich wartości danego typu. Z wyjątkiem typów całkowitych domyślnie pierwsza wartość w każdym typie porządkowym ma liczbę porządkową 0, następna – numer 1 itd. PP-4(13 z 88) Typy proste Typy porządkowe S typy wyliczeniowe Typy wyliczeniowe stosuje się zwykle dla zbiorów o niewielkiej liczbie elementów, na których nie wykonuje się operacji arytmetycznych. Definicja jednego typu wyliczeniowego jest następująca: type identyfikator-typu = (lista-identyfikatorów); W liście identyfikatorów specyfikuje się identyfikatory (nazwy), które tworzą zbiór wartości danego typu wyliczeniowego. Należy przy tym pamiętać, że ten sam identyfikator nie może być użyty do oznaczania wartości w dwu różnych typach wyliczeniowych, których zakresy pokrywają się, oraz że w obrębie danego typu identyfikatory elementów muszą być różne. PP-4(14 z 88) Typy proste Typy porządkowe S typy wyliczeniowe Przykłady type tydzień = (poniedziałek, wtorek, środa, czwartek, piątek, sobota, niedziela); Typ tydzień sklada się z siedmiu elementów o wyspecyfikowanych identyfikatorach. Liczbą porządkową identyfikatora poniedziałek jest 0, a identyfikatora niedziela – liczba 6. PP-4(15 z 88) Typy proste Typy porządkowe S typy wyliczeniowe Przykłady Opis typu wyliczeniowego może być podany bezpośrednio w deklaracji zmiennej, na przykład var tydzień_1 : (poniedziałek, wtorek, środa, czwartek, piątek, sobota, niedziela); Jeśli jednak użyto powyższej deklaracji, to w zakresie ważności identyfikatora tydzień_1 nie jest możliwe zadeklarowanie innej zmiennej o takich samych elementach typu wyliczeniowego. W zakresie ważności identyfikatora tydzień_1 ewentualna deklaracja var tydzień_2 : (poniedziałek, wtorek, środa, czwartek, piątek, sobota, niedziela); jest błędna (błąd kompilacji). PP-4(16 z 88) Typy proste Typy porządkowe S typy wyliczeniowe Przykłady W celu poprawnego zadeklarowania zmiennych tydzień_1 i tydzień_2 należy użyć konstrukcji var tydzień_1, tydzień_2 : (poniedziałek, wtorek, środa, czwartek, piątek, sobota, niedziela); PP-4(17 z 88) Typy proste Typy porządkowe S typy wyliczeniowe Domyślnie liczby porządkowe kolejnych elementów w typach porządkowych rozpoczynają się od 0. Można to zmienić dodając po specyfikacji elementu znak równości i odpowiednią wartość. Przyjmuje się przy tym, że element, dla którego nie podano liczby porządkowej ma liczbę porządkową o jeden większą niż element poprzedni. PP-4(18 z 88) Typy proste Typy porządkowe S typy wyliczeniowe Przykład Z następującej definicji: type rozmiar = (mały = 2, średni = 4, duży = mały +średni); wynika, że liczbą porządkową elementu mały jest 2, elementu średni S 4, a elementu duży S 6. Definicja ta mogłaby sugerować, że typ rozmair ma trzy elementy. Elementów jest jednak pięć o liczbach porządkowych 2, 3, 4, 5 i 6, chociaż tylko trzy z nich mają swoje nazwy. Pozostałe dwa elementy (o liczbach porządkowych 3 i 5) mają „anonimowe” wartości. Wartości te mogą być przypisane zmiennym typu rozmiar. Jeśli taką zmienną jest np. mój_rozmiar, to poprawna będzie instrukcja mój_rozmiar := rozmiar(3); PP-4(19 z 88) Typy proste Typy porządkowe S typy całkowite Typy całkowite są predefiniowane (nie wymagają opisu). Wszystkie typy całkowite są podzbiorami zbioru liczb całkowitych. Liczba porządkowa elementu dowolnego typu całkowitego jest równa wartości tego elementu. Wśród typów całkowitych wyróżniamy typy podstawowe i ogólne. PP-4(20 z 88) Typy proste Typy porządkowe S typy całkowite Do podstawowych typów całkowitych zalicza się: ‚ typ ShortInt (Int8), zawierający liczby całkowite z przedziału [!128, 127], ‚ typ SmallInt (Int16) - przedział [!32 768, 32 767], ‚ typ LongInt (Int32) - [!2 147 483 648, 2 147 483 647], ‚ typ Int64 - przedział [!263, 263 ! 1], ‚ typ Byte (UInt8) - przedział [0, 255], ‚ typ Word (UInt16) - przedział [0, 65 535], ‚ typ LongWord (UInt32) - przedział [0, 4 294 967 295], ‚ typ UInt64 - przedział [0, 264!1]. PP-4(21 z 88) Typy proste Typy porządkowe S typy całkowite Ogólnymi typami całkowitymi, a więc typami zależnymi od rodzaju procesora i systemu operacyjnego, są: ‚ typ Integer, którego wartościami w 32-bitowej implementacji języka Delphi są liczby całkowite z przedziału od !2 147 483 648 do 2 147 483 647, ‚ typ Cardinal, który przy implementacji 32-bitowej obejmuje liczby całkowite z przedziału od 0 do 4 294 967 295. PP-4(22 z 88) Typy proste Typy porządkowe S typy całkowite Podstawowe typy całkowite (poza typem UInt64) są podzbiorami typu Int64, chociaż wykonywanie operacji arytmetycznych na elementach typów Int64 i UInt64 w połączeniu z elementami innych typów całkowitych może doprowadzić do błędnych wyników. Dla typu LongInt istnieje predefiniowana stała MaxLongint, która określa maksymalną wartość w tym typie, tj. liczbę 2 147 483 647. Dla typu Integer zdefiniowano stałą MaxInt określającą maksymalną wartość w tym typie (w 32-bitowej implementacji języka stała ta jest równa 2 147 483 647). PP-4(23 z 88) Typy proste Typy porządkowe S typy znakowe W języku Delphi zdefiniowano dwa podstawowe typy znakowe i jeden ogólny typ znakowy. Każdy z tych typów oznacza się za pomocą predefiniowanego identyfikatora. Podstawowymi typami znakowymi są: ‚ AnsiChar, ‚ WideChar. PP-4(24 z 88) Typy proste Typy porządkowe S typy znakowe Wartościami typu AnsiChar są znaki zajmujące jeden bajt pamięci, uporządkowane zgodnie z tabelą rozszerzonego zestawu znaków ASCII. Elementy typu WideChar zajmują dwa bajty pamięci (słowo) i są znakami uporządkowanymi zgodnie z zestawem znaków Unicode. Pierwszych 256 znaków z tego zestawu pokrywa się ze znakami ASCII. Ogólny typ znakowy jest oznaczany za pomocą predefiniowanego identyfikatora Char. W obecnej implementacji języka Delphi odpowiada on typowi WideChar. PP-4(25 z 88) Typy proste Typy porządkowe S typy logiczne Standardowymi typami logicznymi są typy: ‚ ‚ ‚ ‚ Boolean (elementy zajmują jeden bajt), ByteBool (jeden bajt), WordBool (dwa bajty), LongBool (cztery bajty). Wartości typów logicznych są oznaczane za pomocą dwu predefiniowanych literałów (stałych): False i True, oznaczających odpowiednio wartości logiczne fałsz i prawda, przy czym w sensie uporządkowania stała False poprzedza stałą True. PP-4(26 z 88) Typy proste Typy porządkowe S typy okrojone Typy okrojone służą do ograniczania zakresów wartości dowolnego z dotychczas przedstawionych typów porządkowych. Definicja jednego typu okrojonego ma postać: type identyfikator-typu = stała-1 .. stała-2; przy czym obie stałe muszą być tego samego typu porządkowego, zwanego typem bazowym. Pierwsza z nich podaje ograniczenie dolne i nie może być większa od drugiej – ograniczenia górnego. PP-4(27 z 88) Typy proste Typy porządkowe S typy okrojone Przykłady type litera = ’A’ .. ’Z’; Typ okrojony litera jest podzbiorem standardowego typu Char (WideChar). PP-4(28 z 88) Typy proste Typy porządkowe S typy okrojone Przykłady type tydzień = (poniedziałek, wtorek, środa, czwartek, piątek, sobota, niedziela); dni_robocze= poniedziałek .. piątek; W definicji tej typ tydzień jest typem wyliczeniowym, a typ dni_robocze typem okrojonym, którego elementami są poniedziałek, wtorek, środa, czwartek i piątek. PP-4(29 z 88) Typy proste Typy porządkowe S typy okrojone Przykłady const a = 10; b = 20; type przedział = 2*(a!b) .. 2*(a+b); W definicji typu okrojonego przedzial zastosowano wyrażenia stałe. Elementami tego typu są liczby całkowite z przedziału [!20, 60]. Następująca definicja jest błędna (dlaczego?): type przedział = (a!b)*2 .. 2*(a+b); PP-4(30 z 88) Typy proste Typy rzeczywiste Wszystkie typy rzeczywiste są predefiniowane. Każdy z dostępnych typów rzeczywistych jest dyskretnym i skończonym podzbiorem zbioru liczb rzeczywistych (w sensie matematycznym). W języku Delphi zdefiniowano sześć podstawowych typów rzeczywistych i jeden ogólny typ rzeczywisty. PP-4(31 z 88) Typy proste Typy rzeczywiste Typami podstawowymi są: ‚ Real48, będący typem rzeczywistym, którego elementy zajmują po sześć bajtów pamięci, ‚ Single, oznaczający typ rzeczywisty o pojedynczej długości, którego elementy zajmują cztery bajty pamięci każdy, ‚ Double, będący typem rzeczywistym o podwójnej długości (każdy element tego typu zajmuje osiem bajtów pamięci), PP-4(32 z 88) Typy proste Typy rzeczywiste Typami podstawowymi są: ‚ Extended, oznaczający typ rzeczywisty o rozszerzonej długości, w którym każdy element zajmuje 10 bajtów pamięci, ‚ Comp, którego elementy są liczbami całkowitymi z przedziału od !263 do 263!1, tj. od około !9.2e18 do około 9.2e18, zajmującymi po osiem bajtów pamięci, PP-4(33 z 88) Typy proste Typy rzeczywiste Typami podstawowymi są: ‚ Currency, który jest typem danych stałoprzecinkowych przeznaczonych do obliczeń pieniężnych o wartościach od !922 337 203 685 477.5808 do 922 337 203 685 477.5807, zajmujących też po osiem bajtów. PP-4(34 z 88) Typy proste Typy rzeczywiste Mantysa wartości typu Real48 może zawierać do 11 lub 12 cyfr znaczących (w zależności od tego, czy wyspecyfikowano kropkę dziesiętną czy nie). Dla typu Single mantysa może zawierać odpowiednio 7 – 8 cyfr znaczących, dla typu Double – 15 lub 16 cyfr, a dla typu Extended – 19 lub 20. Ogólnym typem rzeczywistym jest typ Real, który w 32-bitowej implementacji języka jest równoważny z typem Double. Oznacza to, że w implementacji tej elementy (wartości) ogólnego typu Real zajmują po osiem bajtów pamięci. PP-4(35 z 88) Typy proste Typy rzeczywiste W systemie pomocy środowiska Delphi podano następujące najmniejsze dodatnie i największe wartości elementów podstawowych typów rzeczywistych Real48, Single, Double, Extended i ogólnego typu Real: typ najmniejsza wartość dodatnia największa wartość )))))))))))))))))))))))))))))))))))))))))))) Real48 2.9e!39 1.7e38 Single 1.5e!45 3.4e38 Double 5.0e!324 1.7e308 Extended 3.4e!4932 1.1e4932 Real 5.0e!324 1.7e308 PP-4(36 z 88) Typy proste Typy rzeczywiste program FloatArithmetic; {$APPTYPE CONSOLE} {$R *.res} Ten program wykazuje, że type num = Single; najmniejszą wartością dodatnią var n : Integer; zmiennej typu Single jest ex: Extended; x : num; 2!149 . 1,40129846432481707 !45.10 begin x:=1; n:=0; Podobne testy można repeat ex:=x; przeprowadzić dla x:=x/2; pozostałych typów Inc (n) until x=0; rzeczywistych! Writeln (’2^’, !n+1, ’ = ’, ex:26); Readln end. PP-4(37 z 88) Typy łańcuchowe Łańcuchy służą do reprezentowania ciągu znaków, w tym niewidocznego znaku spacji. W języku Delphi występują następujące rodzaje typów łańcuchowych: ‚ ‚ ‚ ‚ ‚ łańcuchy krótkie, łańcuchy długie (ANSI), łańcuchy Unicode, łańcuchy zakończone znakiem pustym, łańcuchy zasobowe. PP-4(38 z 88) Typy łańcuchowe Typy łańcuchowe krótkie Elementami typu łańcuchowego krótkiego są łańcuchy, którym pamięć przydziela się statycznie i których długość może zmieniać się dynamicznie od 0 do maksymalnej długości podanej w definicji typu łańcuchowego lub przyjmowanej domyślnie. Przy wyłączonej dyrektywie $H (w stanie {$H!}) typ łańcuchowy krótki określa słowo kluczowe string. PP-4(39 z 88) Typy łańcuchowe Typy łańcuchowe krótkie Jeśli po słowie string wyspecyfikowano rozmiar ujęty w nawiasy kwadratowe (string [rozmiar]), gdzie rozmiar oznacza liczbę całkowitą z przedziału od 0 do 255 lub nazwę literału o wartości całkowitej z tego samego przedziału, to bez względu na stan dyrektywy kompilatora $H określenie takie oznacza łańcuch krótki. Brak wyspecyfikowania rozmiaru w stanie {$H!} powoduje domyślne przyjęcie długości 255 znaków (dla łańcucha krótkiego). PP-4(40 z 88) Typy łańcuchowe Typy łańcuchowe krótkie Bez względu na stan dyrektywy kompilatora $H typ łańcuchowy krótki można zdefiniować za pomocą predefiniowanego identyfikatora ShortString. Elementami typu ShortString są łańcuchy (krótkie) o maksymalnej długości 255 znaków. Każdy znak łańcucha krótkiego zajmuje jeden bajt pamięci, a cała dana zajmuje liczbę bajtów pamięci wynikającą z liczby znaków i zwiększoną o jeden. W tym dodatkowym bajcie pamięci (o indeksie 0) jest przechowywana informacja o aktualnym rozmiarze łańcucha. PP-4(41 z 88) Typy łańcuchowe Typy łańcuchowe krótkie Przykłady type nazwisko = string [20]; Typ łańcuchowy krótki nazwisko może zawierać dane będące łańcuchami o maksymalnej długości 20 znaków. type napis = ShortString; Bez względu na stan dyrektywy $H definicja ta określa typ łańcuchowy krótki napis, którego elementami mogą być łańcuchy o maksymalnej długości 255 znaków. PP-4(42 z 88) Typy łańcuchowe Typy łańcuchowe długie Typy łańcuchowe długie są oznaczane za pomocą predefiniowanego identyfikatora AnsiString. Dla elementów typów łańcuchowych długich nie jest określona ich maksymalna długość. Pamięć jest im przydzielana dynamicznie, a ich długość jest ograniczona rozmiarem pamięci przeznaczonej dla programu (teoretycznie do 2 GB). PP-4(43 z 88) Typy łańcuchowe Typy łańcuchowe długie Zmienna typu łańcuchowego długiego zajmuje cztery bajty pamięci i zawiera wskaźnik do łańcucha, tj. wskazuje na miejsce w pamięci, w którym znajduje się łańcuch. Łańcuch długi znajdujący się w pamięci jest zakończony znakiem pustym (znakiem ASCII o kodzie 0), który jednak nie jest jego częścią składową (nie zalicza się do łańcucha). Gdy zmienna typu łańcuchowego długiego nie zawiera łańcucha (zawiera łańcuch o długości 0), jej wartością jest adres pusty (nil). PP-4(44 z 88) Typy łańcuchowe Łańcuchy Unicode Do reprezentowania łańcuchów złożonych ze znaków zestawu znaków Unicode służą predefiniowane typy UnicodeString i WideString. W domyślnym stanie dyrektywy kompilatora $H ({$H +}) typ UnicodeString może też być oznaczany za pomocą słowa kluczowego string. Maksymalne długości elementów obu typów łańcuchowych są ograniczone wyłącznie dostępną pamięcią. Zmienne tych typów zajmują jednak tylko cztery bajty pamięci i zawierają wskaźnik do dynamicznie przydzielonego obszaru pamięci. Wartość nil takich zmiennych oznacza, że łańcuch jest pusty. PP-4(45 z 88) Typy łańcuchowe Łańcuchy Unicode Elementami łańcucha typu UnicodeString mogą być znaki jedno- lub wielobajtowe (w 32-bitowej implementacji języka są to znaki dwubajtowe), a typu WideString S znaki dwubajtowe zestawu znaków Unicode. PP-4(46 z 88) Typy łańcuchowe Łańcuchy zakończone znakiem pustym Przez pojęcie łańcucha zakończonego znakiem pustym rozumie się łańcuch podobny do łańcucha długiego i łańcuchów typów UnicodeString i WideString, tyle że opisany za pomocą tablicy znaków (niekoniecznie jednobajtowych) indeksowanej od 0. Przykłady type nazwisko = array [0..15] of Char; nazwa = array [0..92] of WideChar; PP-4(47 z 88) Typy łańcuchowe Łańcuchy zakończone znakiem pustym Podstawowa różnica w stosowaniu zwykłych łańcuchów i łańcuchów zakończonych znakiem pustym polega na wykonywaniu operacji na tych drugich za pomocą wskaźników. Do reprezentacji wskaźników do łańcuchów zakończonych znakiem pustym służy predefiniowany typ PChar. Zmiennej tego typu można przypisać literał zmienny, a każde jej wystąpienie można zastąpić tablicą znaków indeksowaną od 0. PP-4(48 z 88) Typy łańcuchowe Łańcuchy zakończone znakiem pustym Przykład Jeśli zmienną wsk_znak zadeklarujemy następująco: var wsk_znak : PChar; to wykonanie instrukcji przypisania wsk_znak := ’Delphi XE2’; spowoduje, że zmienna ta będzie wskazywała na obszar pamięci zawierający podany łańcuch. Ten sam skute da zastosowanie konstrukcji const łańcuch : array [0..10] of Char = ’Delphi XE2’; var wsk_znak : PChar; ... wsk_znak:=@łańcuch; PP-4(49 z 88) Typy łańcuchowe Łańcuchy zasobowe Łańcuchy zasobowe są to stałe, które są automatycznie zapamiętywane w zasobie i kompilowane do plików .exe, .dll i .dpl. Deklaracja pojedynczego łańcucha zasobowego ma postać: resourcestring identyfikator = wyrażenie-stałe; gdzie wyrażenie stałe oznacza w ogólności wyrażenie typu łańcuchowego, które może być obliczone przez kompilator. W najprostszym przypadku jest to łańcuch. PP-4(50 z 88) Typy łańcuchowe Łańcuchy zasobowe Łańcuchy zasobowe umożliwiają przygotowanie programów okienkowych, w których teksty ukazujące się na ekranie będą wyświetlane w zależności od kraju użytkownika programu. Łańcuchy zasobowe są zapisywane w oddzielnym pliku .drc. Aby utworzyć dla danego programu jeden taki plik, wszystkie łańcuchy zasobowe należy umieścić w jednym module. Zasoby, które są w wyizolowanych plikach .drc mogą być łatwo doprowadzone do odpowiednich wersji językowych za pomocą programu narzędziowego Resource DLL Wizard, uruchamianego poleceniem New 6 Other 6 Delphi Projects 6 Resource DLL Wizard. Dotyczy to także plików .dfm, w których środowisko Delphi automatycznie zapisuje zasoby zawierające menu, okienka dialogowe i mapy bitowe. PP-4(51 z 88) Typy strukturalne Typy te stosuje się do opisu obiektów złożonych. Każdy z typów strukturalnych definiuje się przez podanie typów elementów i metody strukturalizacji, która zarazem określa sposób dostępu do elementów. W ogólności definicja pojedynczego typu strukturalnego ma postać type identyfikator-typu = opis-typu-strukturalnego; PP-4(52 z 88) Typy strukturalne Opis dowolnego typu strukturalnego może zaczynać się od słowa kluczowego packed. Jego użycie jest wskazówką dla kompilatora, aby wybrał reprezentację danej struktury zajmującą możliwie jak najmniej bajtów pamięci. Reprezentację taką nazywamy postacią spakowaną lub upakowaną. Domyślnie kompilator umieszcza w pamięci poszczególne elementy składowe struktur od granicy słowa lub podwójnego słowa, co zapewnia szybszy dostęp do nich. Użycie słowa kluczowego packed powoduje zapamiętywanie elementów struktur w kolejnych bajtach, a tym samym zmniejsza całkowity obszar pamięci zajętej przez strukturę. Programista ma zatem do wyboru optymalizację programu albo ze względu na szybsze jego działanie, albo na mniejszą zajętość pamięci. PP-4(53 z 88) Typy strukturalne Typy tablicowe Tablica reprezentuje indeksowany zbiór elementów tego samego typu. Jeśli w opisie typu tablicowego podaje się liczbę wymiarów i elementów w każdym wymiarze, to tablica ma z góry określony rozmiar. Tablice takie nazywamy tablicami statycznymi. Drugim rodzajem tablic są tablice dynamiczne, dla których w opisie typu tablicowego specyfikuje się wyłącznie typ jej elementów, a pamięć przydziela się w części wykonawczej jednostki programowej (programu, modułu, biblioteki, funkcji lub procedury). PP-4(54 z 88) Typy strukturalne Typy tablicowe S tablice statyczne Tablica statyczna składa się z ustalonej liczby elementów tego samego typu, zwanego typem składowym, który może być zarówno typem prostym lub łańcuchowym, jak i typem strukturalnym. Za pomocą tablic są reprezentowane regularne układy danych, np. wektory i macierze. Dostęp do poszczególnych elementów tablic uzyskuje się za pomocą indeksowania. Indeksem może być dowolne wyrażenie, którego wartość jest zgodna w sensie przypisania (będzie dalej) z typem indeksowym. Dopuszczalny zakres indeksów jest podany w definicji typu tablicowego. PP-4(55 z 88) Typy strukturalne Typy tablicowe S tablice statyczne Definicja pojedynczego typu tablicy statycznej ma postać type identyfikator-typu = array [typy-indeksowe] of typ-składowy; gdzie typy indeksowe są opisami typu porządkowego, przy czym poszczególne opisy oddziela się przecinkami. Typ składowy oznacza dowolny typ. PP-4(56 z 88) Typy strukturalne Typy tablicowe S tablice statyczne Przykłady type wektor = array [0..50] of Integer; Powyższa definicja określa typ wektor jako typ tablicowy, o elementach ogólnego typu całkowitego (Integer), ponumerowanych od 0 do 50. PP-4(57 z 88) Typy strukturalne Typy tablicowe S tablice statyczne Przykłady type macierz = array [1..20] of array [1..30] of Extended; Typem składowym, tj. typem każdego z 20 elementów typu tablicowego macierz, ponumerowanych od 1 do 20, jest 30-elementowa tablica liczb rzeczywistych (Extended) o elementach ponumerowanych od 1 do 30. Elementami typu macierz są więc tablice dwuwymiarowe o 600 elementach typu Extended. PP-4(58 z 88) Typy strukturalne Typy tablicowe S tablice statyczne Przykłady type macierz = array [1..20, 1..30] of Extended; Definicja ta określa taki sam typ tablicowy jak poprzednio. Typ tablicowy macierz został tu wprost zdefiniowany jako zbiór dwuwymiarowych tablic, o zakresie pierwszego indeksu od 1 do 20 (liczby całkowite) i drugiego indeksu – od 1 do 30 (także liczby całkowite). Ze względu na nieco krótszy zapis, tego rodzaju definicje zaleca się stosować do opisu typów tablicowych wielowymiarowych. PP-4(59 z 88) Typy strukturalne Typy tablicowe S tablice statyczne Przykłady type tablica = array [Boolean, 1..20, znak] of Char; type tablica = array [Boolean, 1..20] of array [znak] of Char; type tablica = array [Boolean] of array [1..20, znak] of Char; type tablica = array [Boolean] of array [1..20] of array [znak] of Char; Wszystkie powyższe definicje typu tablica określają taki sam typ tablicowy. Zauważmy, że typy indeksów określone są w różny sposób. PP-4(60 z 88) Typy strukturalne Typy tablicowe S tablice dynamiczne Opis typu tablicowego (w definicji typu lub deklaracji zmiennej), który nie zawiera określenia typów indeksowych określa tablicę dynamiczną. Definicja pojedynczego typu tablicy dynamicznej ma postać type identyfikator-typu = array of typ-składowy; gdzie typ składowy oznacza dowolny typ. PP-4(61 z 88) Typy strukturalne Typy tablicowe S tablice dynamiczne W chwili deklaracji zmiennej typu tablicy statycznej następuje przydzielenie jej odpowiedniego obszaru pamięci. Deklaracja zmiennej typu tablicy dynamicznej powoduje przydzielenie jej tylko czterech bajtów pamięci. Bajty te zawierają wskaźnik do miejsca pamięci, począwszy od którego są pamiętane wartości elementów tablicy (w chwili deklaracji zmiennej bajtom tym przypisuje się wartość nil oznaczającą adres pusty). Właściwe przydzielenie pamięci tablicy dynamicznej następuje przez wywołanie procedury standardowej SetLength lub DynArraySetLength, a zwolnienie – przez przypisanie danej zmiennej wartości nil lub wywołanie dla niej procedury Finalize (będzie dalej). PP-4(62 z 88) Typy strukturalne Typy rekordowe S rekordy klasyczne Rekordem (klasycznym) nazywa się złożoną strukturę danych, której składowe, zwane polami, mogą mieć różne charakterystyki (należeć do różnych typów). Poszczególne pola mogą być same strukturami złożonymi, przy czym liczba pól rekordu jest ustalona. PP-4(63 z 88) Typy strukturalne Typy rekordowe S rekordy klasyczne Definicja pojedynczego typu rekordowego (klasycznego) jest następująca: type identyfikator-typu = record lista-deklaracji-pól end; (cdn.) PP-4(64 z 88) Typy strukturalne Typy rekordowe S rekordy klasyczne Każda z deklaracji pól ma postać lista-nazw-pól : opis-typu; lub var lista-nazw-pól : opis-typu; Deklaracje pól mogą zawierać dyrektywy wskazówkowe. Ostatnia deklaracja (wariantowa) może mieć postać case deklaracja-pola-wyróżnikowego of wykaz- wariantów; lub case identyfikator-typu-porządkowego of wykaz- wariantów; (cdn.) PP-4(65 z 88) Typy strukturalne Typy rekordowe S rekordy klasyczne Deklaracja pola wyróżnikowego wygląda następująco: identyfikator-pola-wyróżnikowego : identyfikator-typu- porządkowego Każdy element wykazu wariantów ma postać lista-etykiet-wyboru : (lista-deklaracji-pól) PP-4(66 z 88) Typy strukturalne Typy rekordowe S rekordy klasyczne Deklaracja pól ustala listę stałych pól danego typu rekordowego i dla każdego pola określa jego nazwę oraz typ. Deklaracje wariantowe stosuje się co najmniej w dwóch przypadkach. Po pierwsze, gdy chcemy utworzyć jeden typ rekordowy zawierający różne typy danych, ale z góry wiemy, że tylko z jednego rodzaju danych będziemy korzystać dla każdej zmiennej tego typu rekordowego. Po drugie, gdy zamierzamy w różny sposób interpretować dane zapisywane w części wariantowej rekordu. PP-4(67 z 88) Typy strukturalne Typy rekordowe S rekordy klasyczne Liczba bajtów zajętych przez elementy typów rekordowych zależy od użycia lub nie słowa kluczowego packed oraz od stanu dyrektywy przełącznikowej kompilatora $A. Przykłady type data = record rok : SmallInt; miesiac : 1 .. 12; dzien : 1 .. 31 end; PP-4(68 z 88) Typy strukturalne Typy rekordowe S rekordy klasyczne Przykłady W poniższej definicji typu rekwar występują dwa pola stałe (w tym jedno wyróżnikowe). Pozostałe pola są wariantowe. Informacje zapisane w odpowiednim miejscu pamięci będzie można odczytać albo jako dwie wartości typu Byte, albo jako wartość typu SmallInt. type rekwar = record a : Extended; case b : Boolean of True : (c, d : Byte); False : (e : SmallInt) end; PP-4(69 z 88) Typy strukturalne Typy rekordowe S rekordy klasyczne Przykłady Zastąpienie wiersza case b : Boolean of wierszem case Boolean of a więc zastąpienie deklaracji pola wyróżnikowego identyfikatorem typu porządkowego, spowoduje, że typ rekordowy będzie miał tylko jedno pole stałe i dwa lub jedno pole wariantowe. W przypadku zadeklarowania zmiennej r2 takiego typu, dostęp do jej pól wariantowych będzie możliwy za pomocą odwołań r2.c, r2.d i r2.e. PP-4(70 z 88) Typy strukturalne Typy rekordowe S rekordy klasopodobne Rekordy mogą mieć strukturę bardziej złożoną, która przypomina strukturę klasy (będzie dalej). Oprócz pól elementami rekordów mogą być: - metody (w tym metody klasowe), - konstruktory, - własności (w tym własności klasowe), - pola klasowe, - typy zagnieżdżone. Elementy te zostaną szczegółowo omówione przy okazji opisu typu klasowego. Tutaj ograniczymy się do podania przykładu. PP-4(71 z 88) Typy strukturalne Typy rekordowe S rekordy klasopodobne Przykład type rekord_kl = record type wzrost = Word; typ zagnieżdżony var wysoki : Word; pole class var niski : Word; pole klasowe constructor Utwórz (wartość : Word); konstruktor procedure Pokaż; metoda class procedure Zmień; metoda klasowa property własność_wysoki : wzrost własność read wysoki write wysoki; class property własność_niski : wzrost własność klasowa read niski write niski; end; PP-4(72 z 88) Typy strukturalne Typy rekordowe S rekordy klasopodobne Przykład (cd.) Po definicji tego typu rekordowego powinny wystąpić (w przypadku modułu w jego części implementacyjnej) definicje konstruktora Utwórz, metody Pokaż i metody klasowej Zmień. Różnice pomiędzy rekordami klasopodobnymi i klasami: - rekordy nie mają własności dziedziczenia, - w rekordach można przeciążać operatory, - w rekordach nie można deklarować destruktorów, metod wirtualnych, dynamicznych i metod do obsługi wiadomości. PP-4(73 z 88) Typy strukturalne Typy rekordowe S rekordy pomocnicze Rekordy pomocnicze to rekordy skojarzone z innymi rekordami, które definiują dla nich dodatkowe metody i własności. Rekordy takie są wykorzystywane przy modyfikacji kodu źródłowego, aby nie zmieniać definicji rekordu oryginalnego. Definicja: type id-typu = record helper for id-typu-oryg lista-elem-rekordu-pomoc end; PP-4(74 z 88) Typy strukturalne Typy rekordowe S rekordy pomocnicze Lista elementów rekordu pomocniczego może zawierać takie same elementy, jak w rekordzie klasopodobnym z wyjątkiem deklaracji zwykłych pól. Dla danego typu rekordowego można zdefiniować wiele pomocniczych typów rekordowych, ale będzie zastosowany ten, który znajduje się najbliżej zasięgu oryginalnego typu rekordowego. Jeśli w pomocniczym typie rekordowym zostanie zdefiniowana metoda o takiej samej nazwie, jak w typie oryginalnym, to przesłoni ona metodę zadeklarowaną w typie oryginalnym. PP-4(75 z 88) Typy strukturalne Typy zbiorowe Każdy typ zbiorowy jest zbiorem potęgowym danego typu porządkowego, tzn. jest zbiorem wszystkich podzbiorów tego typu, w tym zbioru pustego. Definicja pojedynczego typu zbiorowego ma postać type identyfikator-typu = set of typ-porządkowy; Liczba elementów typu porządkowego, zwanego typem bazowym, nie może przekraczać 256, przy czym ich liczby porządkowe muszą należeć do przedziału [0, 255]. PP-4(76 z 88) Typy strukturalne Typy zbiorowe Oznacza to, że spośród standardowych typów całkowitych jest dozwolone wyspecyfikowanie tylko typu Byte. Na ogół typ bazowy jest określany jako typ wyliczeniowy lub okrojony. Wartości typu zbiorowego zapisuje się przez podanie w nawiasach listy elementów danego zbioru (poszczególne elementy oddziela się przecinkami), a zapis [ ] oznacza zbiór pusty. Zapis taki nazywamy konstruktorem zbioru. PP-4(77 z 88) Typy strukturalne Typy zbiorowe Przykłady type dni_pracy = set of (poniedziałek, wtorek, środa, czwartek, piątek); Elementami typu dni_pracy może być dowolny podzbiór zbioru podanych nazw dni tygodnia, m. in.: [poniedziałek, czwartek] [] [wtorek, środa, piątek], [wtorek, piątek, środa], [środa, wtorek, piątek], [piątek, wtorek, środa] - te same podzbiory PP-4(78 z 88) Typy strukturalne Typy zbiorowe Przykłady type znaki = set of AnsiChar; małe_litery = set of ’a’ .. ’z’; Elementami typu znaki są dowolne podzbiory zbioru znaków ASCII, a elementami typu małe_litery – dowolny podzbiór zbioru małych liter alfabetu łacińskiego. PP-4(79 z 88) Typy strukturalne Typy plikowe Plik jest ciągiem elementów tego samego typu, tyle że liczba jego składowych jest zmienna. Jest ona uzależniona od przebiegu wykonywania programu, a w szczególności od skojarzenia pliku z fizycznym zbiorem danych, tj. zbiorem danych rezydującym w pamięci operacyjnej lub wprowadzanym czy wyprowadzanym poprzez urządzenia zewnętrzne (klawiatura, drukarka, napędy dysków). Od tablicy plik różni się też metodą dostępu do poszczególnych elementów. PP-4(80 z 88) Typy strukturalne Typy plikowe Plik jest logicznym modelem fizycznego zbioru danych. Ze względu na rodzaj operacji wykonywanych na plikach można uważać, że plik reprezentuje fizyczny zbiór danych o dostępie sekwencyjnym. Oznacza to, że w dowolnej chwili może być dostępny tylko jeden element pliku, a dostęp do pozostałych elementów jest możliwy dopiero po wykonaniu pewnych operacji na pliku. Za pomocą tego samego pliku można w programie przetwarzać różne fizyczne zbiory danych. PP-4(81 z 88) Typy strukturalne Typy plikowe Pojedynczy typ plikowy definiuje się za pomocą konstrukcji type identyfikator-typu = file of opis-typu-elementów-pliku; Opis typu elementów pliku oznacza w ogólności identyfikator typu prostego, opis typu porządkowego, typ łańcuchowy krótki lub opis typu strukturalnego. PP-4(82 z 88) Typy strukturalne Typy plikowe Opis typu plikowego może składać się z samego słowa kluczowego file. W takim przypadku przyjmuje się, że dany typ plikowy jest niezdefiniowany. Niezdefiniowane pliki są stosowane głównie w celu dostępu do fizycznych zbiorów dyskowych bez względu na ich wewnętrzny format. PP-4(83 z 88) Typy strukturalne Typy plikowe W języku Delphi istnieje też predefiniowany plik tekstowy o nazwie TextFile (synonimem tej nazwy jest Text). Elementami pliku tekstowego są wiersze podzielone na znaki. Każdy wiersz takiego pliku zakończony jest parą znaków sterujących CR/LF (skr. ang. carriage return i line feed). Pliki tekstowe stanowią logiczne modele służące do obsługi zbiorów fizycznych dostępnych głównie za pomocą takich urządzeń, jak: klawiatura, terminale, drukarki i ekran monitora. PP-4(84 z 88) Typy strukturalne Typy plikowe Przykłady type dane = file of LongInt; wyniki = file of Extended; Identyfikatory dane i wyniki zostały tu zdefiniowane jako identyfikatory typów plikowych o elementach odpowiednio LongInt i Extended. PP-4(85 z 88) Typy strukturalne Typy plikowe Przykłady type complex = file of record re, im : Extended end; Typ plikowy complex składa się z elementów będących parami danych typu Extended. PP-4(86 z 88) Typy strukturalne Typy plikowe Przykłady type data = file of record rok : SmallInt; miesiac : 1 .. 12; dzien : 1 .. 31 end; PP-4(87 z 88) PP-4(88 z 88)