Opracował: mgr inŝ. Zbigniew JANIK Strona 1/11 Zakres tematyki: Komentarze, zmienne, stałe, operatory oraz typy w Object Pascalu Instrukcje pętli Procedury i funkcje Wybrane elementy języka Object Pascal W tej części wykładu omówiono wybrane elementy języka Object Pascal takie jak: Komentarze Zmienne, nazywanie zmiennych, nadawanie wartości zmiennym Stałe Operatory przypisania, porównania, logiczne Typy w języku Object Pascal. Typy poleceń Deklaracje Polecenia sterujące Polecenia przypisania Komentarze Komentarz jest najprostszym elementem języka programowania i stanowi swobodny tekst mający znaczenie jedynie dla czytelności programu. Jest on całkowicie ignorowany przez kompilator. Język Object Pascal dopuszcza trzy rodzaje ograniczników komentarza: nawiasy klamrowe {..}, znane z Turbo Pascala ogranicznik typu "nawias-gwiazdka" (*...*), równieŝ występujące w Turbo Pascalu podwójny ukośnik / / (ang. double slash), występujący w języku C++ Oto przykłady komentarzy: { to jest komentarz języka Object Pascal, podstawy Delphi 3.0 } (* to równieŝ jest komentarz, tylko z innymi ogranicznikami *) // Ten komentarz musi zmieścić się w jednej linii Jako koniec komentarza w ostatniej z prezentowanych postaci przyjmuje się koniec linii. Komentarze tej samej postaci nie mogą być zagnieŝdŝane, gdyŝ jest to sprzeczne z regułami składniowymi języka. Zmienne W języku Pascal wszystkie deklaracje zmiennych zlokalizowane są przed blokiem kodu danej procedury, funkcji lub programu głównego:
Opracował: mgr inŝ. Zbigniew JANIK Strona 2/11 Procedure Fifo; x, y: integer; f: double; x := 1; Inc(x); y := 2; Język Object Pascal, podobnie jak Visual Basic, lecz w przeciwieństwie do C i C++ nie rozróŝnia duŝych i małych liter w nazwach swoich elementów. Programista ma dość duŝą swobodę stylistyczną w pisowni nazw, na przykład nazwa prostesortowaniemetodąprzesiewania Z pewnością jest mniej czytelna niŝ NieTakSzybkaLeczProstaProceduraSortowaniaPrzezWstawianie Deklaracje zmiennych tego samego typu mogą być łączone, na przykład deklarację Zmiennal : integer; Zmienna2 : integer; moŝna skrócić do postaci Zmienna1, Zmienna2 : integer; Jak widać, po liście zmiennych następuje dwukropek i nazwa typu. Nazywanie zmiennych Widzisz więc, Ŝe musisz nadać zmiennym nazwy. MoŜesz nazywać je jak tylko chcesz, lecz musisz stosować się do poniŝszych reguł: Nazwa moŝe mieć długość do 63 znaków. Nazwa musi zaczynać się literą albo znakiem podkreślenia _ Wszystkie inne znaki w nazwie mogą być literami, cyframi albo znakiem podkreślenia _ Nie moŝesz w nazwach uŝywać takich symboli, jak #, $ czy % ani znaku spacji. Nie moŝesz uŝywać Ŝadnego ze słów, które w języku Object Pascal są słowami zastrzeŝonymi. Proponuję nazywanie zmiennych tak, aby nazwa ich coś znaczyła i jednocześnie w miarę krótka, aby łatwo było pisać program. Nadawanie wartości zmiennym Odbywa się w innym miejscu niŝ ich deklarowanie, mianowicie w treści programu. Nowością, która pojawiła się w Delphi jest moŝliwość inicjowania zmiennych juŝ podczas ich deklaracji, na przykład: i: integer = 10; P: Pointer = NIL; s: String = 'Napis domyślny'; d: Double = 3.1415926 ;
Opracował: mgr inŝ. Zbigniew JANIK Strona 3/11 Jest to jednak dopuszczalne wyłącznie dla zmiennych deklarowanych w programie głównym - zmiennych lokalnych procedur i funkcji nie wolno w ten sposób inicjować, nie pozwoli na to kompilator. Stałe Stałe (ang. constants) są synonimami konkretnych wartości występujących w programie. Wprowadzone zostały do języka z potrzeby rozróŝnienia identycznych wartości, mających jednakŝe róŝne znaczenie dla programu. JeŜeli, dla przykładu, w duŝym programie liczba 7 oznacza zarówno liczbę dni w tygodniu jak i liczbę stanowisk w zakładzie, to po powiększeniu liczby stanowisk do 10 i modyfikacji programu trzeba bardzo uwaŝnie wybrać te siódemki, które mają być zamienione na dziesiątki. Nie zawsze jest to łatwe, a problem staje się juŝ niezwykle trudny, jeŝeli chodzi o wartości pochodne (czy ta wartość 28 oznacza liczbę dni w czterech tygodniach, czy teŝ liczbę taboretów przy stanowiskach, po cztery na stanowisko?). UŜywając stałych, programiści wolni są od tego typu obaw, a sam program bardziej czytelny i łatwy do modyfikacji. Deklaracja stałych poprzedzona jest słowem kluczowym const i składa się z jednego lub więcej przypisań wartości nazwie synonimicznej, na przykład: const DniWTygodniu = 7; Stanowisk = 7; TaboretyNaStanowisku = 4; TaboretyOgolem = TaboretyNaStanowisku * Stanowisk; Przy tak zaprojektowanym programie, po zmianie liczby stanowisk naleŝy zmienić jedynie drugą z powyŝszych deklaracji. Object Pascal nie wymaga deklarowania typów stałych; kompilator sam ustala typ stałej na podstawie wartości. Kompilator stara się przydzielić kaŝdej wartości moŝliwie najmniejszy obszar pamięci zdolny ją pomieścić, i tak: wartościom całkowitym z zakresu -128 do 127 przydzielany jest bajt (typ ShortInt) wartościom całkowitym z zakresu -32768 do 32767 przydzielane jest dwubajtowe słowo (typ Smalllnt) pozostałe wartości całkowite zajmują czterobajtowe podwójne słowo (typ Longlnt) wartości rzeczywiste bez części wykładniczej oraz nie dłuŝszej niŝ cztery cyfry części ułamkowej reprezentowane są jako liczba stałoprzecinkowa ośmiu bajtach pamięci (typ Comp) pozostałe wartości rzeczywiste zajmują pole dziesięciobajtowe (typ Extended) napisy reprezentowane są, zaleŝnie od ustawienia przełącznika kompilacji $H bądź jako typ String, znany z Turbo Pascala, bądź teŝ jako wprowadzony w Delphi 2.0 typ AnsiString dla zbiorów liczbowych i znakowych rozmiar zajętej pamięci wynika bezpośrednio z ich postaci Operatory Operatory są symbolami języka słuŝącymi - mówiąc najogólniej - do manipulowania na danych. Tak więc istnieją operatory arytmetyczne - dodawania, odejmowania, mnoŝenia i dzielenia wartości liczbowych, operatory przypisanie, wyboru elementu z tablicy itp. Obecnie rozpatrzymy większość operatorów Object Pascala.
Opracował: mgr inŝ. Zbigniew JANIK Strona 4/11 Operator przypisania Operator przypisania (ang. assignment operator) słuŝy do przypisania zmiennej wartości; jest to bodaj najprostszy, lecz jednocześnie jeden z najwaŝniejszych operatorów języka. Oto jeden z przykładów zastosowania: Numberl := 5; PowyŜsza instrukcja przypisuje zmiennej Numberl wartość 5. Operatory porównania Operatory porównania (ang. comparison operators) są w Delphi niemalŝe identyczne jak w Visual Basicu. SłuŜą do stwierdzenia równości lub nierówności dwóch wartości lub porównania pod względem relacji mniejszości. W Tabeli 2.1 przedstawione zostaną łącznie operatory porównania i operatory logiczne. Tabela 2.1. Operatory przypisania, porównania i logiczne w Pascalu. Operatory logiczne Operator Pascal Przypisania Przypisania := Porównania Równy = RóŜny od <> Mniejszy od < Większy od > Mniejszy od lub równy <= Większy od lub równy >= Logiczne Alternatywa or Koniunkcja and Negacja not RóŜnica symetryczna xor Arytmetyczne Dodawania + Odejmowania - MnoŜenia * Dzielenia rzeczywistego / Dzielenia całkowitego div Reszty z dzielenie mod Operatory logiczne (ang. logical operators) realizują (w ograniczonym zakresie) operacje wynikające z algebry Boole'a (stąd ich częsta nazwa Boolean operators). Ich typowym zastosowaniem jest jednoczesne testowanie kilku warunków, na przykład: if (warunekl) and (warunek2) Then Cokolwiek While (warunekl) or (warunek2) do Cokolwiek Operatory logiczne obecne są w kaŝdym języku programowania, chociaŝ ich postać jest róŝnorodna. Procedury zwiększenia i zmniejszenia Procedury te realizują zoptymalizowaną operację zwiększenia (ang. increment) lub zmniejszenia (ang. decrement) zmiennej typu porządkowego. Występują w dwóch odmianach. Pierwsza z nich powoduje zmianę wartości zmiennej o 1 (w górę lub w dół): Inc(zmienna); Dec(zmienna);
Opracował: mgr inŝ. Zbigniew JANIK Strona 5/11 Dwuargumentowa postać: Inc(zmienna, dystans); Dec (zmienna, dystans); powoduje zmniejszenie lub zwiększenie zmiennej o wartość zadaną jawnie w postaci drugiego argumentu. Kompilator Delphi jest tak inteligentny, Ŝe sam rozpoznaje operację zmniejszania lub zwiększania zmiennej za pomocą zwykłej operacji dodawania lub odejmowania, tak więc wynik wykonania instrukcji x := x + 1 nie róŝni się od wyniku wykonania instrukcji Inc(x) dlatego główną korzyścią wynikającą z uŝycia omawianych procedur jest wygoda programisty. Typy w języku Object Pascal Jedną z najkorzystniejszych cech Object Pascala jest tzw. bezpieczeństwo typów (ang. type safety). Oznacza to, Ŝe kompilator prowadzi rygorystyczną kontrolę typów zmiennych biorących udział w operacjach i będących parametrami wywołań procedur i funkcji. Jakiekolwiek odstępstwo od ściśle zdefiniowanych reguł powoduje błąd kompilacji. UŜytkownik ma, co prawda moŝliwość świadomego osłabienia tej kontroli, ale to juŝ zupełnie inna sprawa. Wykaz typów Pascala Całkowity 8-bitowy ze znakiem Całkowity 8-bitowy bez znaku Całkowity 16-bitowy ze znakiem Całkowity 16-bitowy bez znaku Całkowity 32-bitowy ze znakiem Całkowity 32-bitowy bez znaku Zmiennoprzecinkowy 4-bajtowy Zmiennoprzecinkowy 6-bajtowy Zmiennoprzecinkowy 8-bajtowy Zmiennoprzecinkowy 10-bajtowy Stałoprzecinkowy 64-bitowy Znak 1-bajtowy Znak 2-bajtowy Łańcuch krótki Łańcuch długi Łańcuch szeroki Łańcuch logiczny oznacza to samo co: {$H-} ShortString; {$H+} AnsiString; Logiczny 1-bajtowy Logiczny 2-bajtowy Logiczny 4-bajtowy ShortInt Byte SmallInt Word Integer, LongInt Cardinal Single Real Double Extended Currency Char WideChar ShortString WideString String Boolean, ByteBool WordBool LongBool Typy poleceń Program komputerowy manipuluje danymi za pomocą zbioru instrukcji, podanych mu przez programistę. Instrukcje te podane są w postaci poleceń. KaŜde polecenie w programie jest jak krok zawarty w instrukcji obsługi. Niektóre instrukcje definiują narzędzia i części, których
Opracował: mgr inŝ. Zbigniew JANIK Strona 6/11 potrzebujesz. Inne instrukcje wymagają podejmowania decyzji i kierują do odpowiedniej następnej instrukcji. Są teŝ instrukcje, które informują cię, Ŝe masz wykonać odpowiednie zadanie. Większość programów dzieli się na szereg mniejszych części procedur i funkcji. KaŜda z tych procedur czy funkcji zawiera szereg poleceń, które informują komputer o tym, co ma zrobić. Polecenia te mogą być podzielona na trzy kategorie: Deklaracje (ang. Declaration statements) Definiują zmienne i stałe, które będą uŝywane w procedurze. Polecenia sterujące (ang. Control statements). Na podstawie decyzji zlecają komputerowi wykonanie określonych fragmentów programu. Polecenia przypisania (ang. Assignment statements). Wykonują manipulacje danymi i przechowują informacje w zmiennych albo we właściwościach komponentów. Deklaracje Polecenia przypisania Polecenia sterujące Procedure Tform1.Button1Click(Sender: TObject); new, I : integer; msg : string; r : single; new := 0; r := 20; if new <= 0 then new := 10; for I:= 1 to new do r := r + I; Instrukcje pętli p UmoŜliwiają cykliczne wykonywanie bloku instrukcji. Instrukcje te róŝnią się sposobem określenia warunków, przy spełnieniu których pętla ma być kontynuowana. Pętla For.. Do Instrukcja For.. Do słuŝy do wykonania ciągu instrukcji uwarunkowanych określoną liczbę razy. Liczba obrotów pętli znana jest więc przed jej rozpoczęciem. Schemat pętli przedstawiono poniŝej: { kolejność rosnąca } For zmienna_ster := wart_początkowa to wart_końcowa do instrukcja { kolejność malejąca } For zmienna_ster := wart_początkowa downto wart_końcowa do instrukcja JeŜeli wzajemna relacja wartości początkowej i końcowej nie odpowiada kierunkowi przebiegu pętli (np. For i:=5 to 3 do), to pętla nie wykona się ani razu.
Opracował: mgr inŝ. Zbigniew JANIK Strona 7/11 Pętla Repeat.. Until Instrukcja Repeat.. Until słuŝy do wykonania ciągu instrukcji uwarunkowanych nieokreśloną liczbę razy. Liczba obrotów pętli znana jest dopiero przy sprawdzaniu warunku końca pętli zapisanym za słowem kluczowym Until.. Schemat pętli przedstawiono poniŝej: Repeat Instrukcja 1 Instrukcja 2... Instrukcja n Until (wyraŝenie logiczne) Instrukcje wewnętrzne są wykonywane co najmniej jeden raz, a zakończenie przetwarzania instrukcji powtarzaj następuje, gdy wartością wyraŝenia logicznego występującego po słowie kluczowym Until jest True. Innymi słowy: instrukcje wewnętrzne wykonywane są dopóty, dopóki wspomniane wyraŝenie logiczne ma wartość False. Pętla while Instrukcja while (dopóki) słuŝy do opisywania iteracji ze sprawdzeniem warunku na początku i ma postać: while wyraŝenie do instrukcja WyraŜenie, które najczęściej jest wyraŝeniem porównania, powinno w wyniku dawać wartość logiczną (True lub False) a instrukcją występującą po słowie do moŝe być dowolną instrukcją prostą lub strukturalną. Instrukcja ta jest wykonywana tak długo, jak długo wartością wyraŝenia jest True (chyba Ŝe nastąpi skok przekazujący sterowanie na zewnątrz instrukcji dopóki ) ZauwaŜmy, Ŝe jeśli przed rozpoczęciem wykonywania instrukcji dopóki wartością wyraŝenia występującego po słowie while jest False, to instrukcja wewnętrzna nie będzie wykonana ani razu. Jeśli natomiast przed rozpoczęciem wykonywania instrukcji dopóki wartością wspomnianego wyraŝenia będzie True, a instrukcja wewnętrzna nie spowoduje zmiany jego wartości, to omawiana instrukcja iteracyjna nie zostanie nigdy zakończona. Przy posługiwaniu się instrukcją while naleŝy zatem zwracać szczególną uwagę na właściwe sterowanie występującym w niej wyraŝeniem. Przykład: k:=1; x:=0; while k<10 do x:=(x+k)/k; k:=k+1
Opracował: mgr inŝ. Zbigniew JANIK Strona 8/11 PROCEDURY I FUNKCJE Podprogram jest to wyodrębniona część programu realizująca pewien algorytm, posiadająca jednoznaczną nazwę i ustalony sposób wymiany informacji z programem. WyróŜnia się dwa rodzaje podprogramów: procedury i funkcje. Podprogramy stosuje się aby: umoŝliwić podział problemu na prostsze zadania rozwiązywane oddzielnie, zwiększyć czytelność programu, ułatwić projektowanie uruchamianie i modyfikacją programu, zorganizować wykonywanie czynności wielokrotnie powtarzanych w programie, umoŝliwić lepsze wykorzystanie pamięci poprzez wykorzystywanie zmiennych deklarowanych lokalnie w podprogramie. RóŜnica między procedurą i funkcją polega na sposobie wywołania ich w programie oraz na sposobie przekazywania wyników. Zadaniem procedury jest wykonanie pewnych czynności niekoniecznie związanych z obliczeniami; natomiast funkcja oblicza jedną wielkość będącą jej wartością. Definicja procedury ma postać: procedure nazwa_ procedury (lista_paramctrów_formalnych); część_opisowa ciqg_instrukcji Definicja funkcji ma postać: function nazwa_funkcji (lista_paramctrów_formalnych) : typ_wyniku; część_opisowa ciąg_instrukcji Funkcje Funkcje mają naturę zbliŝoną do procedur, inny jest jednak ich sens w programie. Procedura symbolizuje pewien zamknięty zestaw czynności, odzwierciedlających się być moŝe w zmianach parametrów, funkcja ucieleśnia pod swą nazwą konkretną wartość, określonego typu. Ma to wpływ na postać nagłówka funkcji: po słowie kluczowym function następuje nazwa funkcji, potem nieobowiązkowo lista parametrów formalnych, jednak przed średnikiem następuje jeszcze wskazanie wyniku funkcji (poprzedzone dwukropkiem). W części wykonywalnej funkcji musi wystąpić przynajmniej jedna instrukcja, w której nastąpi przypisanie funkcji konkretnej wartości. W Delphi wykorzystuje się do tego celu słowo kluczowe result, symbolizujące zmienną przechowującą aktualny wynik funkcji. Zatem musi wystąpić, co najmniej jedna instrukcja: result := wyraŝenie_wynikowe; Funkcja jest wywoływana kaŝdorazowo, gdy jej nazwa wystąpi jako część wyraŝenia łącznie z parametrami aktualnymi w nawiasach..
Opracował: mgr inŝ. Zbigniew JANIK Strona 9/11 Schematyczna postać funkcji: function nazwa_funkcji (parametry):typ_wyniku; { lokalne zmienne i typy deklarowane w dowolnej kolejności} instrukcje; result := wyraŝenie_wynikowe; Język Object Pascal umoŝliwia grupowanie procedur i funkcji w moduły, które mogą być dołączane do róŝnych programów. śeby wykorzystywać funkcje i procedury w programie naleŝy umieścić ich definicje w części opisowej programu. Parametry formalne i aktualne W definiowaniu podprogramów waŝną rolę spełniają parametry formalne. Są to nazwy zastępujące właściwe obiekty uŝywane przy odwołaniu się do podprogramu. W definicji podprogramu słuŝą one do zapisu algorytmu. W momencie wykonywania tego algorytmu (w wyniku wywołania podprogramu w programie) parametry formalne są zastępowane obiektami rzeczywistymi spoza podprogramu tzw. parametrami aktualnymi. Podprogram nie musi posiadać parametrów, wówczas w definicji nie podaje się listy parametrów formalnych. Instrukcje realizujące algorytm podprogramu mogą być wykonywane na obiektach lokalnych wyszczególnionych w jego części opisowej, lub nielokalnych opisanych na zewnątrz podprogramu. Obiekty lokalne są tworzone (na skutek ich deklaracji) w momencie rozpoczęcia wykonywania podprogramu i istnieją tylko do momentu zakończenia jego wykonywania. Obiekty nielokalne mogą być uŝywane w treści procedury lub funkcji bezpośrednio lub przekazywane do mej przez parametry. W zaleŝności od sposobu przekazywania wartości do podprogramu (tzn. zastępowania parametrów formalnych parametrami aktualnymi) wyróŝnia się parametry przekazywane przez wartość parametry przekazywane przez zmienną (adres zmiennej). Deklaracje tych parametrów (w liście parametrów formalnych) mają odpowiednio postać: lista_parametrów : typ lista_parametrów : typ; JeŜeli parametr przekazywany jest przez wartość, to przy wywołaniu procedury lub funkcji odpowiadający mu argument musi być wyraŝeniem o wartości zgodnej z typem tego parametru. Parametr taki jest w treści podprogramu traktowany jako zmienna lokalna o wartości początkowej równej wartości wyraŝenia będącego parametrem aktualnym. Ewentualne operacje wykonywane w pod programie na tym parametrze formalnym nie powodują zmiany wartości odpowiadającego mu parametru aktualnego. JeŜeli parametr przekazywany jest przez zmienną (adres zmiennej), to przy wywołaniu podprogramu odpowiadający mu argument musi być zmienną typu zgodnego z typem parametru formalnego. Operacje wykonywane w treści procedury czy funkcji na parametrze, który jest zmienną, powodują (po wywołaniu podprogramu) wykonywanie tych operacji na odpowiadającym mu
Opracował: mgr inŝ. Zbigniew JANIK Strona 10/11 argumencie, czyli na nielokalnej zmiennej, i dotyczą bezpośrednio tej zmiennej. Dzięki temu w przypadku procedur uzyskujemy moŝliwość przekazywania wyników za pośrednictwem takich zmiennych. Parametry typu plikowego mogą być przekazywane tylko przez zmienną. Z problemem zgodności typów parametrów formalnych i aktualnych wiąŝe się kwestia definiowania własnych typów. Definicja typu programisty wygląda następująco: type nazwa_typu = opis_typu; Od momentu zdefiniowania typu moŝna wykorzystywać jego nazwę do deklarowania zmiennych takiego typu. Przykłady: type kolory = (czerwony, zolty, niebieski, zielony, czarny); macierz = array [1..5, 0..7] of byte; farba : kolory; A, B : macierz; Zadanie przykładowe: Napisz w Object Pascalu procedurę, która wczytuje z klawiatury liczbę n, oraz n liczb całkowitych wprowadzonych takŝe z klawiatury Liczby będą zapamiętane na jednowymiarowej tablicy X o elementach całkowitych. Następnie napisz funkcję która oblicza sumę elementów tego wektora. W Lazarusie z menu Projekt Nowy projekt wybrać Program. Zostanie wygenerowany następując kod programu: program Project1; {$mode objfpc}{$h+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes { you can add units after this }; {$R *.res} end. Pamiętaj, Ŝe Ŝadnej z wygenerowanych instrukcji nie moŝesz edytować. Dopisz na końcu programu instrukcję: Readln; tuŝ przed ostatnią instrukcją programu: end. i uruchom program. Powinno pojawić się czarne okno Trybu Poleceń Systemu Windows. W tym oknie w trybie tekstowym będą wyświetlane wyniki programu. Zamknij te okno. Zapisz projekt pod nazwą Parametry. Uzupełnij program o brakujące instrukcje (zaznaczono je poniŝej kolorem niebieskim) i uruchom go.
Opracował: mgr inŝ. Zbigniew JANIK Strona 11/11 program Parametry; {$mode objfpc}{$h+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes { you can add units after this }; {$R *.res} const max=100; type tab1 = array [1..max] of integer; n : integer; X : tab1; Sum : integer; procedure Czytaj( n : Integer; A : tab1); i : integer; Write('Podaj liczbe elementow wektora n = '); Readln(n); Writeln('Wprowadz kolejne elementy wektora X'); for i:=1 to n do Write('X[',i,']= '); Readln(A[i]); function Suma(k:integer; B:tab1):integer; i,s : Integer; s:=0; for i:=1 to k do s:=s+b[i]; result:=s; Czytaj(n,X); Sum:=Suma(n,X); Writeln('Suma wektora wynosi = ',Sum); Readln; end.