Informatyka 2 MPDI Wykład 9 Delphi tablice, rekordy
Typ tablicowy (array) Pojęcie: - skończony zbiór elementów tego samego typu składowego (homogeniczne) - o położeniu (selekcji) określanym przez indeks(-y) (numery) składowej Opis: array [ lista typów indeksów ] of typ bazowy (składowych) typ porządkowy (o ograniczonym zakresie): okrojony integer (najczęściej) okrojony char wyliczeniowy boolean dowolny: prosty strukturalny (bez plików) tablica tablic,napisów, rekordów
Uwagi tablice służą do gromadzenia wielu wartości tego samego typu (nietrwałe – tylko w pamięci operacyjnej – później poznamy jak zapisywać do plików) wymiar tablicy 1-wymiarowa -wektor 2-wymiarowa (prostokątna) 3-wymiarowa (przestrzenna) itd.. rozmiar – w każdym wymiarze! zawartość – dowolna – także inna tablica! np. array [1..5,1..5] of array [1..2,1..2] of integer;
array[ 1..20] of array[ 1..30] of real; przykłady: array[ 1..50 ] of integer; array[ 1..20, 1..30] of real; array[ 1..20] of array[ 1..30] of real; może być też 30 wierszy i 20 kolumn, zależy od wizualizacji
rozmiar w każdym wymiarze Tablica ma: wymiar rozmiar w każdym wymiarze mogą być indeksy ujemne array [ -10 .. 0 ] of real
Zmienne tablicowe indeksowane (składowe) całościowe
Z [ W1, ..., Wn ] y := 10*x[ k ] - 5.2; //użycie w wyrażeniu zmienne indeksowane (składowe) - dostęp do składowych Z [ W1, ..., Wn ] Wtypu składowego nazwa tablicy indeksy wyrażenia typu zgodnego z typem indeksów zgodne co do liczby, typu i kolejności z deklaracją użycie - w wyrażeniach lub instrukcjach, jak zmienne typu składowego Przykłady: var x: array[ 1..100 ] of real; begin x[ 2 ] := 10.5; //nadanie wartości y := 10*x[ k ] - 5.2; //użycie w wyrażeniu z:=sin( sqrt( x[ 5 ] - 5.2 ) ) //użycie w wyrażeniu if x[5] >0 then .... //sprawdzenie
var x, y: array[ 1..5] of integer ; begin y[1] := 35 ; zmienne całościowe - tylko przypisanie - dla typów tożsamych! brak: + - * / porównania np: var x, y: array[ 1..5] of integer ; begin y[1] := 35 ; x := y; //przepisz całą zawartość tablicy y do tablicy x ..... end
Nadanie wartości początkowych zmiennym tablicowym dla tablic konstrukcja typu: ( (st11, st21,..., stn1 ), (st12, st22,..., stn2 ), . . . (st1m, st2m,..., stnm) ) const osoby: array[ 1..3] of string[20] = ( 'Nowak', 'Kowalski', 'Nycz' ); albo zmienna (zmiennym można w programie zmienić wartości a stałym NIE): var wyniki: array[ 1..3, 1..4] of real = ( ( 3, 4, 4.5, 5), ( 2, 3.5, 5.0, 4.5), (5.0, 4, 3.5, 2) );
var wyniki: array[ 1..3, 1..4] of real = (( 3, 4, 4.5, 5), Przykład: program p2; {APPTYPE CONSOLE} uses SysUtils; var wyniki: array[ 1..3, 1..4] of real = (( 3, 4, 4.5, 5), ( 2, 3.5, 5.0, 4.5), (5.0, 4, 3.5, 2)); begin writeln (wyniki[1,1]:10:2); //wypisze wartość 3.00 readln; end.
Przykłady operacji tablicowych type tab = array [1..2, 1..5] of real; var t1, t2 : tab; wie,kol: integer; begin write ('Podaj element 1,1:'); readln(t1[1,1]); //itd. // najczęściej operacje w pętli zagnieżdżanej jeśli tablica 2-wymiarowa for wie:=1 to 2 do for kol:= 1 to 5 do t1[wie, kol] :=1; //wyświetlenie na ekranie też w pętli zagnieżdżanej write(t1[wie, kol]); writeln; end; readln; end. cała tablica wypełniona jedynkami pętla zewnętrzna po wierszach pętla wewnętrzna po kolumnach każdego wiersza po wypisaniu wiersza tabeli przejdź do nowego wiersza
Zadanie: w wektorze zsumować co drugi element (nieparzyste indeksy) program test; const N=12; type zakres = 1..N; var k: zakres; suma: real; x: array [ 1 .. N ] of real= ( 3, 4, 4.5, 5, 2, 3.5, 5.0, 4.5, 5.0, 4, 3.5, 2); begin suma := 0; for k := 1 to N do if (k mod 2) = 1 then suma := suma + x [k]; writeln ( suma :10:3) ; readln end. zastanowić się! albo można tak: for k := 1 to ( N+1 ) div 2 do suma := suma + x [ 2*k - 1 ];
Pamiętajmy: Nie ma gotowych operacji macierzowych (mnożenie, obliczanie wyznacznika, znajdowanie macierzy odwrotnej itp.), trzeba samemu stworzyć algorytm lub posiadać odpowiednie biblioteki z gotowymi podprogramami Przykładowo mnożenie tablic: program mn24; var t1:array[1..2, 1..4] of real = ((1,2,4,-1),(0, -1, 8, 1)); t2 :array[1..4,1..2] of real = ((1,1.1),(4,-2.0),(0, -1),(-3,-2.5)); wyn: array[1..2,1..2] of real; i:1..4; begin // obliczanie elementu 1,1 wyn[1,1]:=0; for i:=1 to 4 do wyn[1,1]:= wyn[1,1]+ t1[1,i]*t2[i,1]; writeln(wyn[1, 1]:10:2); readln; end. 1 2 4 -1 8 1 1.1 4 -2 -1 -3 -2.5
Całość: program mn24; const N=2; M=4; var t1:array[1..N, 1..M] of real = ((1,2,4,-1),(0, -1, 8, 1)); t2 :array[1..M,1..N] of real= ((1,1.1),(4,-2.0),(0, -1),(-3,-2.5)); wyn: array[1..N,1..N] of real; wie,kol, i:1..4; begin //potrójna pętla! for wie:=1 to N do for kol:=1 to N do for i:=1 to M do wyn[wie,kol]:= wyn[wie,kol]+ t1[wie,i]*t2[i,kol]; //wyswietlenie wyniku for kol:= 1 to N do write(wyn[wie, kol]:10:2); //wypisanie wiersza writeln; //zmiana wiersza end; readln; end.
Można wyświetlać wyniki od razu po utworzeniu elementu ... begin //potrójna pętla! for wie:=1 to N do begin for kol:=1 to N do //utworzenie elementu for i:=1 to M do wyn[wie,kol]:= wyn[wie,kol]+ t1[wie,i]*t2[i,kol]; // i od razu wyświetlenie write(wyn[wie, kol]:10:2); end; writeln; readln; end.
string[20] tożsame z array[0..20] of char; Pamiętamy typ string – typ łańcuchowy – zmienna zawiera ciąg znaków Można typ string traktować jako wektor znaków string[20] tożsame z array[0..20] of char; var zmienna:string[20]; begin zmienna:= 'lokomotywa'; writeln (zmienna[3]); { wyświetli literę k } {…..} end.
Przeszukiwanie tablic jednowymiarowych Algorytm przeszukiwania tablic polega na porównywaniu podanego wzorca z kolejnymi elementami tablicy. Pseudokod algorytmu wygląda następująco. 1. Start. 2. Wczytaj tablicę i wzorzec przeszukiwań. 3. Ustaw licznik na wartość 1. 4. Sprawdź czy wzorzec jest równy elementowi tablicy o indeksie równym licznikowi. Jeżeli tak to przejdź do punktu 7, jeśli nie to kontynuuj. 5. Zwiększ licznik o 1. 6. Sprawdź czy licznik nie jest większy od rozmiaru tablicy. Jeśli tak, to napisz, że nie znaleziono wzorca i przejdź do punktu 8, jeśli nie to przejdź do punktu 4. 7. Wypisz licznik i element o indeksie równym aktualnemu licznikowi. 8. Stop. Oczywiście algorytm znajdzie tylko pierwsze wystąpienie – co zrobić gdy w tablicy elementy się powtarzają?
Wyznaczanie minimum (maksimum) Algorytm przeszukiwania tablic polega na początkowym założeniu, że minimum (maksimum) X jest pierwszym elementem tablicy. Następnie kolejno sprawdzamy elementy od 2 do N - jeśli analizowany element jest mniejszy (większy) od aktualnego X ustawiane jest nowe X. Pseudokod algorytmu wygląda następująco. 1. Start. 2. Wczytaj tablicę. 3. Przypisz pierwszy element tablicy do Emin. 4. Zwiększ licznik o 1. Sprawdź czy licznik nie jest większy od rozmiaru tablicy. Jeśli tak, przejdź do punktu 9. Sprawdź czy aktualny element jest mniejszy od Emin.Jeśli tak wstaw go do Emin. Przejdź do punktu 4. 9. Wypisz Emin. 10. Stop.
if x[k]>max then max:=x[k]; program maximum; {$APPTYPE CONSOLE} uses SysUtils; var x:array[1..20] of integer; k,max:1..20; begin randomize; for k:=1 to 20 do // losowe wypełnienie tablicy x[k]:= random(100); write(x[k]:5); end; max:= x[1]; for k:=2 to 20 do if x[k]>max then max:=x[k]; writeln; writeln(max:10); readln; end.
Sortowanie bąbelkowe Algorytm polega porównywaniu kolejnych par elementów sąsiadujących i zamianie miejscami w przypadku niewłaściwej kolejności. Po wykonaniu pierwszego przebiegu porównań i ewentualnych zamian miejscami, element największy znajdzie się na końcu (w przypadku porządku sortowania według kolejności rosnącej). Następnie wykonujemy kolejny przebieg porównań par i tak dalej…
Sortowanie Sortowanie bąbelkowe Algorytm polega porównywaniu kolejnych par elementów sąsiadujących i zamianie miejscami w przypadku niewłaściwej kolejności 1 2 3 4 ..... N N-1 porównań w każdym przebiegu Wykonujemy N przebiegów
N=6 zauważamy nadmiarowe porównania 1 przebieg 12 5 11 4 7 2 zamiana 1 5 11 4 7 2 12 efekt ostatniej zamiany – największy na końcu 2 przebieg 5 11 4 7 2 12 5 11 4 7 2 12 zmiana 6 5 4 11 7 2 12 zmiana 7 5 4 7 11 2 12 zmiana 8 5 4 7 2 11 12 3 przebieg 5 4 7 2 11 12 zamiana 9 4 5 7 2 11 12 4 5 7 2 11 12 zamiana 10 4 5 2 7 11 12 4 przebieg 4 5 2 7 11 12 zamiana 11 4 2 5 7 11 12 N=6 zauważamy nadmiarowe porównania
30 operacji= (N-1)*N=6*5 5 przebieg 4 2 5 7 11 12 zmiana 12 2 4 5 7 11 12 6 przebieg 30 operacji= (N-1)*N=6*5
Sortowanie bąbelkowe skrócone Algorytm polega na porównywaniu kolejnych par elementów sąsiadujących, z tym, że: - w każdym kolejnym przebiegu liczba analizowanych par jest zmniejszana o 1 - przebiegów wykonujemy N-1
15 operacji 5 4 3 2 1 1 przebieg 12 5 11 4 7 2 zamiana 1 5 11 4 7 2 12 efekt 2 przebieg 5 11 4 7 2 12 5 11 4 7 2 12 zamiana 6 5 4 11 7 2 12 zamiana 7 5 4 7 11 2 12 zamiana 8 5 4 7 2 11 12 efekt 3 przebieg 5 4 7 2 11 12 zamiana 9 4 5 7 2 11 12 4 5 7 2 11 12 zamiana 10 4 5 2 7 11 12 efekt 4 przebieg 4 5 2 7 11 12 4 5 2 7 11 12 zamiana 11 4 2 5 7 11 12 efekt 5 przebieg 4 2 5 7 11 12 zamiana 12 2 4 5 7 11 12 efekt 5 4 15 operacji 3 2 1
lop=90 const N=10; k, m:1..N; Bąbelkowe pom, lop:integer; begin var tab:array [1..N] of integer; k, m:1..N; pom, lop:integer; begin randomize; //wypełnienie losowe tablicy 1-wymiarowej for k:=1 to N do tab[k]:=random(100); //sortowanie for m:=1 to N-1 do begin lop:=lop+1; if tab[m]>tab[m+1] then pom:=tab[m]; tab[m]:=tab[m+1]; tab[m+1]:=pom; end; //wypisanie wyniku for k:= 1 to N do write(tab[k]:6); writeln;writeln(lop); readln; end. Bąbelkowe zamiana wartości tab[m] i tab[m+1] lop=90
lop=45 szybsze const N=10; k,m:1..N; Bąbelkowe skrócone var tab:array [1..N] of integer; k,m:1..N; pom,lop:integer; begin randomize; //wypełnienie losowe tablicy 1-wymiarowej for k:=1 to N do tab[k]:=random(100); //sortowanie for k:=1 to N-1 do for m:=1 to N-k do begin lop:=lop+1; if tab[m]>tab[m+1] then pom:=tab[m]; tab[m]:=tab[m+1]; tab[m+1]:=pom; end; //wypisanie wyniku for k:= 1 to N do write(tab[k]:6); writeln;writeln(lop); readln; end. Bąbelkowe skrócone różnice! lop=45 szybsze
Typ rekordowy (record) pojęcie: - skończony zbiór elementów dowolnego typu składowego tak zwane pola - ułożone jednowymiarowo - o położeniu (selekcji) określanym przez nazwę składowej (pola) - tzw. dostęp kwalifikowany Czyli zestaw nazwanych pól dowolnego typu (i różnego rozmiaru)
pole może być liczbą, tekstem, tablicą, napisem, innym rekordem opis: record lista_nazw_pól: typ1; lista_nazw_pól: typ2; . . . end typ dowolny: prosty lub strukturalny (bez plików) pole może być liczbą, tekstem, tablicą, napisem, innym rekordem
Przykłady: type data = record rok: 1900 .. 2100; mies: 1..12; dzien: 1..31 end; var student : record nazw: string[ 20 ]; imie: array[1..2] of string[ 15 ]; data_ur: data; stypend: real end; St. Wołek - Podst. Progr. Komput.
Porównanie: jednakowe składowe selektor typu indeks dostęp bezpośredni statyczny rozmiar różne składowe selektorem jest nazwa pola dostęp bezpośredni statyczny rozmiar Uwaga: Rekord to jeden zestaw danych (np. dane jednego studenta), jeśli potrzebujemy analizy większej liczby to tworzymy tablicę rekordów
Deklaracje (opis) zmiennych Zmienna tablicowa var t1:array [1..5, 1..6] of real; Zmienna rekordowa var student : record nazw: string[ 20 ]; imie: array[1..2] of string[ 15 ]; stypend: real end; type dane = record nazw: string[ 20 ]; imie: array[1..2] of string[ 15 ]; stypend: real end; var student: dane; lub
Wykorzystanie zmiennych rekordowych w programie zmienne całościowe - tylko przypisanie – możliwe jedynie dla typów tożsamych czyli dokładnie takie same składowe! brak: + - * / porównania wejścia/wyjścia – wczytać lub wypisać można tylko składową (pole) np: var r1, r2: record ..definicja... end ; begin //… ustalenie zawartości zmiennej r1 r2 := r1; //przepisz zawartość r1 do r2
Z . p Ztypu składowego UWAGA: kropka oddzielająca! desygnator pola (składowa) - dostęp do pola Z . p Ztypu składowego nazwa zmiennej rekordowej nazwa pola UWAGA: kropka oddzielająca!
dzien, miesiac, rok:integer end; Przykład1 type data= record dzien, miesiac, rok:integer end; var student: record nazw: string[ 20 ]; imie: array[1..2] of string[ 15 ]; data_ur: data;//zdefiniowany typ rekordowy stypend: real begin student.nazw:= 'Kowalski'; student.stypend:= 300; student.data_ur.dzien:= 3; student.data_ur.rok := 1993; student.imie[1]:= 'Jan'; writeln(student.imie[1][2] ) ; //to 2-ga litera 1-go imienia //itd. definicje użycie: w wyrażeniach lub instrukcjach, w zależności od typu składowej program
Przykład2: program test; type data= record dzien, miesiac, rok:integer end; var student: record nazw: string[ 20 ]; imie: array[1..2] of string[ 15 ]; data_ur: data; stypend: real begin write('Podaj imię1:'); readln(student.imie[1]); write('Podaj drugie imię:'); readln(student.imie[2]); write('Podaj dzien urodzenia:'); readln(student.data_ur.dzien); //itd. writeln(student.imie[1]); //wypisz na ekranie end.
rekord student.nazwisko student.imie[1] student.data_ur.rok Użycie elementów tablicy i rekordu w części wykonawczej programu: tablica t1[5, 6] indeks (-y) rekord student.nazwisko student.imie[1] student.data_ur.rok w zależności od typu nazwy pól zmienna
var os1: osoba; // zmienna rekordowa pomocnicza TABLICE REKORDÓW Tablice rekordów służą do gromadzenia wielu danych typu rekordowego (zwykle 1-wymiarowe) type data = record rok: 1900 .. 2100; mies: 1..12; dzien: 1..31 end; osoba = record nazw: string[ 20 ]; imie: array[1..2] of string[ 15 ]; data_ur: data; var os1: osoba; // zmienna rekordowa pomocnicza grupa: array[1..100] of osoba; //tablica rekordów !!!!
grupa – zmienna typu tablicowego grupa[k] – zmienna typu rekordowego grupa[1].nazw - zmienna typu string grupa[2].imie – zmienna typu tablicowego grupa[k].imie[1] - zmienna typu string grupa[k].data_ur - zmienna typu rekordowego grupa[k].data_ur.rok – zmienna typu integer grupa[2].imie[2][5] – zmienna typu char Użycie zależne od typu: writeln( grupa[3].nazw); os1.nazw := 'Nowak'; grupa[50]:=os1; os1:= grupa[51]; writeln (grupa[k].imie[1]); writeln(length(grupa[30].nazw)) if grupa[k].data_ur.rok>1970 then…
Instrukcja wiążąca - with dotyczy tylko zmiennych rekordowych (obiektowych) upraszcza zapis !! Opis: with lista_zmiennych_rekordowych do instrukcja; najczęściej begin . . . end można tu używać nazw pól bez specyfikowania zmiennej rekordowej przykład: with student do begin nazw :='Kowalski'; imie[1] := 'Jan'; data_ur.rok := 1988; stypendium := 420.0; end; student.nazw :='Kowalski'; student.imie[1] := 'Jan'; student.data_ur.rok := 1988; student.stypendium := 420.0;