Plan wykładu Ada 95 #1/5 - typy Wojciech Complak, Instytut Informatyki, Politechnika Poznańska e-mail : Wojciech.Complak@cs.put.poznan.pl www : http://www.cs.put.poznan.pl/wcomplak Hierarchia typów w Adzie Typy skalarne Typy dyskretne Typ znakowy Typ logiczny Typy całkowite Typy rzeczywiste Tablice i typ tablicowy Typ łańcuchowy Typy rekordowe 2006-03-26, v. 0.14 Hierarchia typów w Adzie Typy skalarne wskaźnikowe proste typy Ady skalarne złożone tablice rekordy zadania typy chronione wartości typów skalarnych są uporządkowane liniowo dostępne operatory : =, /=, <, <=, >, >= ważniejsze atrybuty: T First dolna granica zakresu typu T, typem wyniku jest typ T dyskretne rzeczywiste T Last górna granica zakresu typu T, typem wyniku jest typ T wyliczeniowe całkowite zmiennopozycyjne stałopozycyjne T Range równoważny zakresowi T First.. T Last ze znakiem resztowe dziesiętne zwykłe T Base podtyp bazowy typu T Typy dyskretne to takie typy skalarne, w których wartości mają numer pozycji będący liczbą całkowitą dodatkowe atrybuty: Typ znakowy w Adzie 83/95 są dostępne dwa typy znakowe Character 8-bitowy typ znakowy, kod Latin-1 T Pos T Val zwraca numer pozycji wartości będącej argumentem w zbiorze wartości typu dyskretnego T zwraca tę wartość typu T, której numer wartości jest równy argumentowi wywołania Wide_Character 16-bitowy kod ISO 10646 w Adzie 2005 pojawił się nowy typ znakowy Wide_Wide_Character 32-bitowy typ znakowy
Typ logiczny predefiniowany typ wyliczeniowy Boolean zawiera dwa literały True i False (False < True) dodatkowe dostępne operatory : not, and, or, xor w Adzie dostępne są skrócone formy sterowania and then i or else, w przypadku ich użycia lewy operand jest obliczany zawsze jako pierwszy i jeśli jego wartość wystarczy do określenia wartości wyrażenia prawy operand nie jest obliczany Typ całkowity predefiniowany typ całkowity ze znakiem Integer, przekroczenie zakresu powoduje wygenerowanie wyjątku Constraint_Error typinteger standard, zakres co najmniej 2**15.. +2**15-1, GNAT 32 bity typlong_integer opcjonalny, jeśli jest, zakres co najmniej -2**31.. +2**31-1, GNAT 32 bity pozostałe typy całkowite ze znakiem są opcjonalne, jeśli są muszą spełniać zależność : zakres(long_long_integer) zakres(long_integer) zakres(integer) zakres(short_integer) zakres(short_short_integer) dla kompilatora GNAT : Long_Long_Integer ma 64 bity, Short_Integer ma 16 bitów, Short_Short_Integer ma 8 bitów Typ całkowity resztowy typ całkowity bez znaku, maksymalna podstawa to: System.Max_Binary_Modulus dla podstaw będących potęgami dwójki (GNAT 2**Long_Long_Integer'Size) System.Max_Nonbinary_Modulus dla pozostałych (GNAT : Integer'Last) type Byte is mod 256; type Word is mod 2**16; d : Byte; e : Word; Typy rzeczywiste typ zmiennopozycyjny a : Float; -- typ predefiniowany w pakiecie Standard type T1 is digits 8; -- dokładność 8 cyfr type T2 is digits 6 range 3.1.. 5.4; -- dokładność 6 cyfr w podanym zakresie typ stałopozycyjny zwykły i dziesiętny type T1 is delta 0.250 range 0.0.. 10.0; -- wartości określane z rozdzielczością 0.250 -- w zadanym zakresie type T2 is delta 0.01 digits 9; -- typowe zastosowanie bankowo/księgowe -- 9 cyfrowe kwoty z dokładnością do groszy Tablice deklaracje, typ tablicowy przykłady deklaracji zmiennych tablicowych : W1 : array (1..3) of Integer; W2 : array (-5..4,2..3) of Boolean; przykłady definicji typów i deklaracji tablic : -- typ tablicowy zawężony type T_W1 is array (1..5) of Integer; W1, W2 : T_W1; -- -------------------------------------------------------------------------------------------------------------------------------------------- -- typ tablicowy niezawężony type T_W2 is array (Positive range <>, Natural range <>) of Integer; W3 : T_W2(1..2,0..3); W4 : T_W2(2..2,3..3); -- -------------------------------------------------------------------------------------------------------------------------------------------- -- typ tablicowy niezawężony, rozmiar ustalany podczes inicjalizacji type T_W3 is array (Natural range <>) of Integer; W5 : T_W3 := (1,2,3,4,5); Tablice inicjalizacja przykłady inicjalizacji ( :=,..,, =>, others) W1 : array (1.. 3) of Integer := (1, 2, 3); -- OK -- W2 : array () of Integer := (others => 5); -- źle -- tak nie można, to nie C! W2 : array (2.. 4) of Integer := (others => 5); -- OK -- W3 : array (1.. 8) of Integer := -- (1..2=>1, 3 6 =>4, 4..5=>2); -- źle -- inicjalizacja musi być kompletna W3 : array (1.. 8) of Integer := (1..2=>1, 3 6=>4, 4..5=>2, others=>3); -- OK
Tablice atrybuty rozmiaru tablic (atrybut First) Tablice atrybuty rozmiaru tablic (atrybut Last) A First - dolna granica zakresu tablicy jednowymiarowej (lub pierwszego zakresu A Last - górna granica zakresu tablicy jednowymiarowej (lub pierwszego zakresu A First(N) - dolna granica zakresu N-tego wymiaru A Last(N) - górna granica zakresu N-tego wymiaru Tablice atrybuty rozmiaru tablic (atrybut Length) A Length - liczba elementów tablicy jednowymiarowej (lub pierwszego wymiaru tablicy wielowymiarowej), typem wyniku jest liczba całkowita, A Length(N)- liczba elementów N-tego wymiaru tablicy wielowymiarowej), typem wyniku jest liczba całkowita, Tablice atrybuty rozmiaru tablic (atrybut Range) A Range - równoważne A First..A Last, typem wyniku jest zakres, A Range(N) równoważne A First(N)..A Last(N), typem wyniku jest zakres, Tablice - korzystanie z atrybutów (#1/6) przykład atrybuty First, Last, Length, tablice jedno- i dwuwymiarowa with Ada.Text_IO, Ada.Integer_Text_IO; use Ada.Text_IO, Ada.Integer_Text_IO; W4 : array (1..2, 3..4) of Integer; Put_Line(""); Put(W1'First); Put(W1'Last(1)); Put(W1'Length); Put_Line(""); Put(W4'First); Put(W4'First(1)); Put(W4'First(2)); 1 3 3 1 1 3 Tablice - korzystanie z atrybutów (#2/6) for ind in 1.. 3 loop -- fatalnie, 2! W1(ind) := 1; for ind in 1.. W1'Length loop W1(ind) := 2; - niby troche lepiej, 2+
Tablice - korzystanie z atrybutów (#3/6) for ind in W1'First.. W1'Last loop W1(ind) := 3; -- dobrze, rosnące indeksy for ind in reverse W1'First.. W1'Last loop W1(ind) := 4; -- dobrze, malejące indeksy Tablice - korzystanie z atrybutów (#4/6) for ind in W1'Last.. W1'First loop W1(ind) := 5; -- pętla się nie wykona, Last > First for ind in reverse W1'Last.. W1'First loop W1(ind) := 6; -- bezcelowe, pętla się nie wykona Tablice - korzystanie z atrybutów (#5/6) for ind in W1'Range loop W1(ind) := 7; -- optymalne, rosnące indeksy for ind in reverse W1'Range loop W1(ind) := 8; -- optymalne, malejące indeksy Tablice - korzystanie z atrybutów (#6/6) przykład dlaczego warto korzystać z atrybutu Range, tablica dwuwymiarowa W4 : array (1..2,2..3) of integer; for i in W4'First(1).. W4'Last(1) loop for j in W4'First(2).. W4'Last(1) loop W4(i,j) := 1; -- typowy błąd przy kopiuj/wklej for i in W4'Range(1) loop for j in W4'Range(2) loop W4(i,j) := 2; -- tak jest bezpieczniej Typ łańcuchowy (#1/3) typ łańcuchowy jest zdefiniowany jako: type String is array(positive range <>) of Character; type Wide_String is array(positive range <>) of Wide_Character; dostępny jest operator konkatenacji & (łańcuch/znak & łańcuch/znak, wynikiem jest łańcuch) with Ada.Text_IO; use Ada.Text_IO; Stars : String(1.. 120) := (1.. 120 => '*' ); Question : String := "How are you?"; Put(Stars); Put(Question); Put(Stars & Question); Typ łańcuchowy (#2/3) łańcuchy można porównywać za pomocą operatorów = i /= łańcuchy można sortować leksykograficznie (operatory <, <=, >, >= ) w Adzie są trzy typy łańcuchów : fixed długość jest stała (tablice znaków), określana w trakcie kompilacji (SCRy) pakiet Ada.Strings.Fixed bounded długość jest znana i/lub ograniczona (bazy danych, SCRy) pakiet Ada.Strings.Bounded unbounded długość jest dynamicznie zmienna, ograniczona zakresem liczb całkowitych (Integer Last) i dostępną pamięcią sterty (systemy ogólnego przeznaczenia) pakiet Ada.Strings.Unbounded
Typ łańcuchowy (#3/3) przykład z użyciem Unbounded_String with Ada.Text_IO, Ada.Integer_Text_IO, Ada.Strings.Unbounded; use Ada.Text_IO, Ada.Integer_Text_IO, Ada.Strings.Unbounded; Str : Unbounded_String; -- Str := "test"; -- nie można, niezgodne typy Str := To_Unbounded_String("test"); Put(Length(Str)); Typ rekordowy nieparametryzowany definicja typu rekordowego type Person is Initial : Character; Age : Natural; end ; type Cpx is re, im : Float := 0.0; end ; deklaracje zmiennych C1 : Cpx := (1.0, 2.0); A, B : Person := ('A',0); Typ rekordowy z wariantami definicja typu rekordowego type Device is (Printer, Disk, Drum); type State is (Open, Closed); type Peripheral(Unit : Device := Disk) is Status : State; case Unit is when Printer => Line_Count : Integer range 1.. Page_Size; when others => Cylinder : Cylinder_Index; Track : Track_Number; end case; end ; deklaracje zmiennych Writer : Peripheral(Unit => Printer);