Pascal. Język programowania: w zintegrowanym środowisku Delphi 7



Podobne dokumenty
Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Pascal typy danych. Typy pascalowe. Zmienna i typ. Podział typów danych:

PASCAL Kompendium. Środowisko TURBO PASCAL Skróty klawiaturowe. Edycja kodu Pomoc spis treści. Skopiowanie zaznaczonego bloku do schowka

OPERACJE NA PLIKACH. Podstawowe pojęcia:

Pascal - wprowadzenie

DIAGRAMY SYNTAKTYCZNE JĘZYKA TURBO PASCAL 6.0

Programowanie Delphi obliczenia, schematy blokowe

Wstęp do programowania. Różne różności

Wykład II PASCAL - podstawy składni i zmienne, - instrukcje wyboru, - iteracja, - liczby losowe

Algorytmika i Programowanie VBA 1 - podstawy

Język programowania PASCAL

PoniŜej znajdują się pytania z egzaminów zawodowych teoretycznych. Jest to materiał poglądowy.

Wykład PASCAL - Pliki tekstowe

typ zakres sposob zapamietania shortint integer bajty (z bitem znaku) longint byte word

Pliki. Operacje na plikach w Pascalu

Ćwiczenie 2 Wczytywanie i zapisywanie do plików tekstowych

Język programowania DELPHI / Andrzej Marciniak. Poznań, Spis treści

INSTRUKCJA PUSTA. Nie składa się z żadnych znaków i symboli, niczego nie robi. for i := 1 to 10 do {tu nic nie ma};

Wykład II PASCAL - podstawy składni i zmienne, - instrukcje wyboru, - iteracja cz. 1

Podstawy programowania skrót z wykładów:

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

Podstawy Programowania C++

Programowanie. programowania. Klasa 3 Lekcja 9 PASCAL & C++

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Elementy języków programowania

Właściwości i metody obiektu Comment Właściwości

1 Podstawy c++ w pigułce.

Kompendium wiedzy z Pascala

PODSTAWY PROGRAMOWANIA

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Wprowadzenie do programowania w VBA

Wstęp do programowania

Programowanie w Turbo Pascal

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Podstawy programowania

1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja. 2. Schemat blokowy przedstawia algorytm obliczania

Instrukcja standardowa Writeln

Podstawy Programowania Podstawowa składnia języka C++

Wykład IV PASCAL - łańcuch znaków, - procedury i funkcje, - sortowanie bąbelkowe

Zasady Programowania Strukturalnego

Podstawy programowania

Programowanie komputerowe. Zajęcia 1

Instrukcje podsumowanie. Proste: - przypisania - wejścia-wyjścia (read, readln, write, writeln) - pusta - po prostu ; (średnik) Strukturalne:

Wprowadzenie do języka Pascal

Programowanie C++ Wykład 2 - podstawy języka C++ dr inż. Jakub Możaryn. Warszawa, Instytut Automatyki i Robotyki

Spis treści WSTĘP CZĘŚĆ I. PASCAL WPROWADZENIE DO PROGRAMOWANIA STRUKTURALNEGO. Rozdział 1. Wybór i instalacja kompilatora języka Pascal

Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Delphi Laboratorium 3

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Podstawy programowania. Wykład PASCAL. Zmienne wskaźnikowe i dynamiczne. dr Artur Bartoszewski - Podstawy prograowania, sem.

Wszystkie zmienne typu plikowego, z wyjątkiem Output i Input muszą być zadeklarowane w sekcji deklaracji programu, który z nich korzysta.

Wykład 2 Składnia języka C# (cz. 1)

Przykład programu Rozwiązanie równania postaci:

LibreOffice Calc VBA

Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227 WYKŁAD 7 WSTĘP DO INFORMATYKI

Procedury i funkcje - powtórzenie i uzupełnienia. Przykład funkcji potęgowanie przy wykładniku naturalnym

Języki skryptowe w programie Plans

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Cw.12 JAVAScript w dokumentach HTML

Wydział Zarządzania AGH. Katedra Informatyki Stosowanej. Procedury i funkcje. Programowanie komputerowe

Podstawy programowania w języku C

1 Podstawy c++ w pigułce.

Programowanie strukturalne i obiektowe : podręcznik do nauki zawodu technik informatyk / Adam Majczak. Gliwice, cop

1. Wprowadzanie danych z klawiatury funkcja scanf

JAVAScript w dokumentach HTML (1)

Informatyka I. Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki

Podstawy programowania w języku Visual Basic dla Aplikacji (VBA)

Programowanie RAD Delphi

Programowanie w języku Python. Grażyna Koba

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Programowanie. Pascal - język programowania wysokiego poziomu. Klasa 2 Lekcja 9 PASCAL

P R OGRA M OW A N I E KOMPUTERÓW Ćwiczenia laboratoryjne

Wykład III PASCAL - iteracja cz, 2, - liczby losowe, - tablice

Podstawy Informatyki. Metalurgia, I rok. Wykład 3 Liczby w komputerze

Wydział Zarządzania AGH. Katedra Informatyki Stosowanej. Podstawy VBA cz. 1. Programowanie komputerowe

WIADOMOŚCI WSTĘPNE WPROWADZENIE DO JĘZYKA TURBO PASCAL. Klawisze skrótów. {to jest właśnie komentarz, moŝna tu umieścić dowolny opis}

Podstawy programowania Laboratorium. Ćwiczenie 2 Programowanie strukturalne podstawowe rodzaje instrukcji

MATERIAŁY DO ZAJĘĆ II

Podprogramy. Procedury

ZASADY PROGRAMOWANIA KOMPUTERÓW

Część 4 życie programu

LABORATORIUM 3 ALGORYTMY OBLICZENIOWE W ELEKTRONICE I TELEKOMUNIKACJI. Wprowadzenie do środowiska Matlab

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

Zmienne, stałe i operatory

Informatyka 1. Przetwarzanie tekstów

2 Przygotował: mgr inż. Maciej Lasota

Instrukcja do ćwiczeń nr 4 typy i rodzaje zmiennych w języku C dla AVR, oraz ich deklarowanie, oraz podstawowe operatory

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.

Informatyka 1. Wyrażenia i instrukcje, złożoność obliczeniowa

INFORMATYKA Studia Niestacjonarne Elektrotechnika

JAVAScript w dokumentach HTML (1) JavaScript jest to interpretowany, zorientowany obiektowo, skryptowy język programowania.

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Metody numeryczne Laboratorium 2

Temat 1: Podstawowe pojęcia: program, kompilacja, kod

Laboratorium Wstawianie skryptu na stroną: 2. Komentarze: 3. Deklaracja zmiennych

1 Powtórzenie wiadomości

ECDL Podstawy programowania Sylabus - wersja 1.0

Transkrypt:

Język programowania: Pascal w zintegrowanym środowisku Delphi 7 15 h wykładu, środa, godz. 12:00 12:45, sala 4,31 45 h ćwiczeń laboratoryjnych, środa, godz. 15:15 17:30, sala 4.25 Wykład: prof. UAM dr hab. Stanisław Lamperski, p. 3.10 Laboratorium: dr Mirosław Gilski, Zakład Krystalografii Kurs kończy się egzaminem Materiały do wykładu: http://www.staff.amu.edu.pl/~slamper

Mimo że w świecie profesjonalnych programistów króluje język C++, Pascal pozostaje nadal najpopularniejszym językiem nauczania informatyki. Pisane w nim programy charakteryzują się czytelną i logiczną strukturą, są łatwe do analizowania i objaśniania. Pascal jest prawdopodobnie także najlepszym narzędziem do opisywania metod rozwiązywania problemów informatycznych, czyli prezentacji algorytmów. A.Kierzkowski, T.M. Sadowski Turbo Pascal. Poradnik dla nauczyciela, Helion 2004 Pascal is a language with a remarkably clear syntax, good control structures, and some extraordinarily compiler implementations. Because the language is so strongly structured, Pascal programs often execute correctly the first time, while FORTRAN and C programs almost never do! W.H. Press, B.P. Flannery, S.A. Teukolsky, W.T. Vetterling Numerical Recipes in Pascal The Art of Scientific Computing 2

Mój pierwszy program w Delphi Delphi pozwala pisać programy pracujące zarówno w trybie tekstowym (konsola) jak i okienkowym. Program tekstowy otwiera specjalne okienko tekstowe, które pełni rolę monitora tekstowego. Pozwala ono użytkownikowi komunikować się z programem. Z kolei programy okienkowe to te, z którymi najczęściej mamy do czynienia pod systemem Windows. Do nauki programowania w Pascalu wystarcza pisanie programów tekstowych. Dlatego nimi będziemy się zajmować. Każdy program napisany w Pascalu ma następującą strukturę: program nazwa programu; część deklaratywna część wykonawcza end. Słowa wytłuszczone to słowa kluczowe języka. W części deklaratywnej opisujmy obiekty występujące w programie. Wprowadzamy tu identyfikatory (nazwy) oraz ich typ. Identyfikator to ciąg liter i cyfr zaczynający się od litery. Litery duże i małe nie są rozróżniane. Dopuszczalne jest użycie podkreślnika. Nie ma ograniczeń na długość identyfikatora, ale tylko pierwsze 63 znaki są rozróżnialne. Wskazane jest używanie takich nazw, które same się komentują lub są ogólnie przyjęte jak np. T, temp, czas, V, h, v_sr, delta itp. Z kolei część wykonawcza składa się z szeregu instrukcji. Każda instrukcja musi być zakończona średnikiem, chyba że występuje po niej słowo kluczowe end lub else. Instrukcja może być zapisana w wielu wierszach, może zawierać spacje i puste linie. Każda zmienna jest określonego typu. Typem zmiennej nazywamy zbiór wartości, jakie może przyjąć. W dowolnym miejscu programu można umieścić komentarz. Komentarz to dowolny tekst umieszczony pomiędzy znakami { i } lub (* i *) albo poprzedzony znakami //. Przykłady { Wyprowadzanie wyników } (* Tu się zaczyna główna część programu *) (* poprawne {zagnieżdżenie} komentarzy *) //blok 3 3

Komentarze zwiększają czytelność programu, a są ignorowane przez kompilator. Delphi tworzy dla każdego programu co najmniej cztery pliki. Dlatego dobrym zwyczajem jest zapisywanie każdego programu do odrębnego foldera. Zaczynamy więc pracę od utworzenia nowego foldera. Następnie uruchamiamy Delphi 7 poprzez menu Start: Wszystkie programy Borland Delphi 7 Delphi 7 lub korzystając ze skrótu na pulpicie. Zamykamy okienka Form1 i Unit1.pas. Na pytanie Save changes to Unit1.pas? wybieramy odpowiedź No. Z głównego menu wybieramy: File New Other. Pokazuje się okienko New Items. Wybieramy Console Application. Zapisujemy program w przygotowanym dla niego folderze nadając mu własną nazwę (np. Program1.dpr). File Save Project As... Uwaga! Nazwy programu nie wolno zmieniać inaczej niż poprzez Save Project As... Kod źródłowy programu doprowadzamy do postaci: program Program1; {$APPTYPE CONSOLE} uses SysUtils; Writeln('Moj pierwszy program'); Readln end. Po słowie uses deklarowany jest moduł SysUtils biblioteki Run-Time Library (RTL). Konstrukcja {$AppType Console} jest tzw. dyrektywą kompilatora powodującą, że program będzie pracował w trybie tekstowym. Instrukcja writeln służy do wyprowadzania wyników do okienka tekstowego. W naszym przypadku wynikiem jest łańcuch czyli ciąg znaków zaczynający się i kończący apostrofem. Instrukcja readln pełni tu szczególną rolę. Powoduje, że po naciśnięciu klawisza ENTER następuje zamknięcie okienka tekstowego. 4

W obszarze między pierwszym i ostatnim end wprowadzamy własne instrukcje. Przed uruchomieniem programu sprawdzamy jego poprawność pod względem syntaktycznym (składniowym) Project Syntax check Program1, a poprawną wersję programu zapisujemy naciskając przycisk z dyskietką na pasku narzędzi. Program uruchamiamy naciskając klawisz F9, naciskając przycisk z zielonym trójkątem na pasku narzędzi lub korzystając z menu głównego: Run Run Teraz zmodyfikujemy Program1 tak, aby miał postać: program Program1; {$APPTYPE CONSOLE} uses SysUtils; var tekst: string; Write('Jak masz na imie? '); Readln(tekst); Writeln; Writeln; Writeln( Witaj,tekst,! ); Writeln( To ja, Twoj komputer! ); Writeln; Writeln; Write('Nacisnij ENTER '); Readln end. W części deklaratywnej została zadeklarowana zmienna tekst typu łańcuchowego. Instrukcja readln odczytuje tekst napisany przez użytkownika i zapamiętuje go pod zmienną tekst. Litery ln na końcu instrukcji read i write powodują przejście kursora do nowej linii. Argumenty instrukcji write lub writeln mogą być różnego typu. W naszym programie jest to łańcuch i zmienna łańcuchowa. Argumenty rozdzielamy przecinkiem. Argumentami instrukcji read lub readln mogą być tylko zmienne. Instrukcja writeln; bez argumentów podanych w nawiasie powoduje utworzenie nowej, pustej linii. 5

Typy proste Typy porządkowe W obrębie typu porządkowego ściśle zdefiniowana jest tzw. relacja porządku określająca miejsce danego elementu: przed którym i za którym elementem się znajduje. Z wyjątkiem typów całkowitych pierwszy element typu porządkowego ma wartość 0, drugi 1, itd. Do typu porządkowego należą: 1. typ całkowity 2. typ wyliczeniowy 3. typ znakowy 4. typ okrojony 5. typ logiczny Typ całkowity Mamy do dyspozycji szereg predefiniowanych typów całkowitych (Tabela 1). Przykład deklaracji zmiennych całkowitych Var i, j: ShortInt; M, n: Integer; Operacje arytmetyczne na liczbach całkowitych: dodawanie +, odejmowanie -, mnożenie *, dzielenie całkowite div, reszta z dzielenia całkowitego mod. Uwagi 1. Operatorów div i mod używamy tak samo jak: +, -, *. 7 div 2 3 7 mod 2 1 2. Dzielenie za pomocą operatora / daje liczbę rzeczywistą 1 / 3 0.33333333 1 div 3 0 1 mod 3 1 Wynik operacji arytmetycznej przeważnie przypisujemy zmiennej. Służy do tego instrukcja przypisania := 6

zmienna := wyrażenie arytmetyczne ; Operacje arytmetyczne wykonywane są w kolejności określonej przez priorytety operatorów (Tabela 3). Jeżeli w wyrażeniu arytmetycznym mamy operatory o tym samym priorytecie, to operacje wykonywane są od lewej strony do prawej. Kolejność wykonywania operacji można zmienić stosując nawiasy okrągłe. Przykłady (zmienne a, b, c, d są typu całkowitego) a := 2*5; b := 3; c := a div b; d := a*b+c; d := a*(b+c); Do wprowadzania i wyprowadzania na ekran (konsolę) wartości zmiennych typu całkowitego służą poznane już instrukcje read, readln, write, writeln, np: Readln(a); Write(a,b,c); Wyprowadzane wyniki można formatować pisząc za identyfikatorem zmiennej lub wyrażeniem typu całkowitego dwukropek (:) i liczbę miejsc, na których wynik ma być zapisany, np. Writeln(a:5,b:10,c:3); Poprawny jest też zapis: Writeln( A =,a:5); ale nie: Readln( A =,a); Tu piszemy: Write( A = ); Readln(a); 7

Dodawanie liczb całkowitych zapisanych w kodzie dwójkowym Kod dziesiętny Kod dwójkowy Kod szestnastkowy 0 1 2 3 4 5 6... 10 11 12 13 14 15 16... 255 0 1 10 11 100 101 110... 1010 1011 1100 1101 1110 1111 10000... 11111111 0 1 2 3 4 5 6... A B C D E F 10... FF Jeśli mamy zdefiniowane cztery podstawowe operacje 0+0=0, 0+1=1, 1+0=1 i 1+1=10 to możemy wykonać dodawanie analogicznie jak w kodzie dziesiętnym 4 100 +5 +101 =9 =1001 Przy operacjach na liczbach całkowitych należy zwracać uwagę na zakres typu zadeklarowanej zmiennej. Przykład Niech a będzie zmienną typu byte. Po wykonaniu operacji a := 255+1; jaką wartość przyjmie zmienna a? Liczby całkowite zapisane za pomocą cyfr szestnastkowych poprzedzamy znakiem $ (dolara). Ewentualny znak + lub stawiamy przed $. Instrukcję podstawienia z poprzedniego przykładu można więc zapisać: a := +$FF+1; 8

Typ wyliczeniowy Definicja type identyfikator-typu = (lista identyfikatorów); Na elementach typu wyliczeniowego nie wykonujemy obliczeń arytmetycznych Deklaracja typu i zmiennej wyliczeniowej type litery = (A, B, C, D, E, F); var moje_litery: litery; Typ znakowy Predefiniowane są typy: - Char (1 bajt) - AnsiChar (1 bajt, alfabet ANSI) - WideChar (2 bajty, alfabet Unicode) Przykład Var znak: Char; Znak może mieć postać łańcucha jednoelementowego, postać dziesiętną lub szesnastkową. Znak w postaci dziesiętnej lub szesnastkowej składa się ze znaku #, bezpośrednio po którym mamy kod znaku zapisany odpowiednio za pomocą cyfr dziesiętnych lub szesnastkowych. Kody znaków zestawu ASCII podane są w Tabeli 4. Przykład Trzy postacie zapisu znaku a: a #97 #$61 Zapisu znaku w postaci dziesiętnej lub szesnastkowej używa się, gdy dany znak nie jest dostępny z klawiatury. Znaki niedostępne to generalnie znaki o kodach od 0 do 31(znaki sterujące) i od 128 w górę, ale są wyjątki. Kody przydatnych znaków zestawione są poniżej. 9

Kody polskich znaków stosowane w oknie tekstowym Znak Kod Znak Kod Ą Ć Ę Ł Ń Ó Ś Ź Ż 164 143 168 157 227 224 151 141 189 ą ć ę ł ń ó ś ź ż 165 134 169 136 228 162 152 171 190 Kody znaków do budowy tabelek Znak Kod Znak Kod 218 191 192 217 196 179 195 180 194 193 197 Przykłady Write(#7); //dźwięk Writeln(#165); //ą 10

Tabela 1. Predefiniowane typy całkowite Typ Zakres wartości Znaczenie ShortInt SmallInt LongInt Integer Int64 Byte Word LongWord Cardinal -128.. 127-32768.. 32767-2147483648.. 2147483647-2147483648.. 2147483647-2 63.. 2 63-1 0.. 255 0.. 65535 0.. 4294967295 0.. 4294967295 8-bitowa liczba całkowita ze znakiem 16-bitowa liczba całkowita ze znakiem 32-bitowa liczba całkowita ze znakiem 32-bitowa liczba całkowita ze znakiem 64-bitowa liczba całkowita ze znakiem 8-bitowa liczba całkowita bez znaku 16-bitowa liczba całkowita bez znaku 32-bitowa liczba całkowita bez znaku 32-bitowa liczba całkowita bez znaku 11

Tabela 2. Predefiniowane typy rzeczywiste Typ Zakres Znaczenie Single Real48 Real Double Extended comp Currency 1.5 10-45..3.4 10 38 2.9 10-39..1.7 10 38 5.0 10-324..1.7 10 308 5.0 10-324..1.7 10 308 3.6 10-4951..1.1 10 4932-2 63..2 63-1 -922337203685477.5808.. 922337203685477.5807 Liczba rzeczywista o pojedynczej precyzji Tradycyjna pascalowa liczba rzeczywista Liczba rzeczywista Liczba rzeczywista o podwójnej precyzji Liczba rzeczywista o rozszerzonej precyzji Bardzo długa liczba całkowita Stałoprzecinkowa wartość waluty Liczba cyfr znaczących 7-8 11-12 15-16 15-16 19-20 19-20 19-20 12

Tabela 3. Priorytety operatorów Operatory Priorytet Kategoria operatorów +, -, @, not *, /, div, mod, and, shl, shr, as +, -, or, xor =, <>, <, >, <=, >=, in, is 1 (najwyższy) 2 3 4 (najniższy) jednoargumentowe multiplikatywne addytywne relacyjne 13

14 Tabela 4. Tablica kodów znaków ASCII Kod Znak Kod Znak Kod Znak Kod Znak 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 27 29 30 31 NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 spacja! # $ % & ( ) * +, -. / 0 1 2 3 4 5 6 7 8 9 : ; < = >? 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 a b c d e f g h i j k l m n o p q r s t u v w x y z { } ~ del

Typ okrojony Typ okrojony służy do ograniczenia zakresu wartości następujących typów: całkowitego, wyliczeniowego, znakowego. Definicja type identyfikator-typu = stała..stała; Przykład - deklaracja typu i zmiennej okrojonej Type wybrane_liczby = 0.. 2000; wybrane_litery = A.. C; wybrane_znaki = a.. z ; Var i1, i2, i3: wybrane_liczby; l1, l2, l3: wybrane_litery; z1, z2, z3: wybrane_znaki; Typ logiczny Predefiniowane są następujące typy logiczne: - Boolean (1 bajt) - ByteBool (1 bajt) - WordBool (2 bajty) - LongBool (4 bajty) Podstawowym typem logicznym w programach pascalowych jest typ Boolean. Pozostałe typy wprowadzono w celu zapewnienia zgodności z programami napisanymi w innych językach. Zmienne logiczne przyjmują wartość False (0) lub True (1). Na zmiennych typu logicznego oraz całkowitego wykonujemy operacje logiczne. Są to: negacja (operator not, operacja jednoargumentowa), koniunkcja (and), alternatywa (or), różnica symetryczna (xor). Niech zmienne a i b są typu logicznego. Wynik działania operacji logicznych na tych zmiennych pokazuje tabelka: a b not a not b a and b a or b a xor b True True False False True False True False False False True True False True False True True False False False True True True False False True True False 15

Priorytety operacji logicznych podane są w Tabeli 3. Przykłady operacji logicznych na bitach. Niech zmienne a i b są typu Byte i mają odpowiednio wartości 15 i 170. W kodzie binarnym a = 00001111 (15) b = 10101010 (170) not a = 11110000 (240) not b = 01010101 (85) a and b = 00001010 (10) a or b = 10101111 (175) a xor b = 10100101 (165) Operacje porównania Do tworzenia operacji porównania służą operatory relacji. W Pascalu zapisujemy je w następujący sposób: = (równy) <> (różny) < (mniejszy) > (większy) <= (nie większy) >= (nie mniejszy) Wynik operacji porównania jest typu logicznego (Boolean). 2 < 5 = True 2 = 5 = False Porównywać można nie tylko liczby, ale także znaki i łańcuchy. Operatory relacji mają najniższy priorytet (Tabela 3), co powoduje, że przy konstruowaniu złożonych operacji porównania często korzystamy z nawiasów okrągłych. Przykład Zmienna a ma być mniejsza od b i od 5. Warunek ten zapisujemy (a < b) and (a < 5) Typy rzeczywiste Typy rzeczywiste służą do przechowywania wartości niecałkowitych i znajdują zastosowanie głównie w zadaniach obliczeniowych. Predefiniowany jest szereg typów rzeczywistych Tabela 2. Przykład deklaracji zmiennych rzeczywistych Var x1, x2: Real; a1, b1: Double; 16

a2, b2: Extended; Poprawny zapis licz rzeczywistych: 123.456 1.23456E+2 +1.23456e2-0.00123-1.23e-3-123E-5 Operacje arytmetyczne na liczbach rzeczywistych: dodawanie +, odejmowanie -, mnożenie *, dzielenie /. Operacje arytmetyczne na liczbach rzeczywistych wykonywane są podobnie jak na liczbach całkowitych w kolejności określonej przez priorytety operatorów (Tabela 3). Jeżeli w wyrażeniu arytmetycznym mamy operatory o tym samym priorytecie, to operacje wykonywane są od lewej strony do prawej. Kolejność wykonywania operacji zmieniamy stosując nawiasy okrągłe. Przykłady Zapis matematyczny i odpowiadający mu zapis w Pascalu (zmienne a, b, c, d są typu rzeczywistego) ab c a a * b / c a /( b* c) lub a / b / c bc a + b ( a + b) / c c a a /( b c) b c a b ( a b) /( c + d) c + d b a a b / c c a a /( b c / d) c b d a a /( b + ( a c) / d) a c b + d Formatowanie wyników wyprowadzanych na ekran writeln(x:p) writeln(x:p:q) x jest zmienną typu rzeczywistego 17

p określa długość pola przeznaczonego na cały wynik q określa liczbę cyfr po kropce dziesiętnej W ogólnym przypadku x, p i q mogą być wyrażeniami odpowiednio typu rzeczywistego (x) i całkowitego (p,q). Przykłady Niech x będzie zmienną rzeczywistą typu double, której przypisano wartość -123.456. Wówczas: writeln(x) -1.23456000000000E+0002 writeln(x:23) -1.23456000000000E+0002 writeln(x:25) -1.23456000000000000E+0002 writeln(x:15) -1.234560E+0002 writeln(x:10) -1.2E+0002 writeln(x:5) -1.2E+0002 writeln(x:10:5) -123.45600 writeln(x:10:2) -123.46 writeln(x:10:0) -123 writeln(x:5:2) -123.46 Znak _ oznacza spację. Typy łańcuchowe Łańcuchy służą do reprezentowania ciągu znaków. W Object Pascalu mamy dwa rodzaje łańcuchów: łańcuchy krótkie (do 255 znaków, alokowane statycznie) łańcuchy długie (~3 GB, alokowane dynamicznie, zakończone znakiem o kodzie 0) Dostępne są następujące typy łańcuchów Typ Maks. długość łańcucha Typ znaków Czy zakończony zerem ShortString AnsiString String WideString 255 ~3 GB 255 lub ~3 GB ~1,5 GB AnsiChar AnsiChar AnsiChar WideChar Nie Tak Tak lub nie Tak Dyrektywa kompilatora $H Jeżeli dyrektywa jest włączona {$H+}, wówczas zmienne typu String są typu długiego, gdy jest wyłączona {$H-} zmienne są typu krótkiego. 18

Domyślnie dyrektywa $H jest włączona Przykłady Deklaracja łańcuchów krótkich {$H-} var L1: String[10]; L2: String; L3: ShortString; L1 := Bardzo dlugi lancuch ; Zmienna L1 zawiera tylko pierwszych 10 znaków łańcucha L2 := Bardzo dlugi lancuch ; Zmienna L2 zawiera wszystkie 20 znaków łańcucha oraz 235 pustych pól. Deklaracja łańcuchów krótkich {$H+} Var L1: String[10]; L3: ShortString; Deklaracja łańcuchów długich {$H+} var L1: String; L2: AnsiString L3: WideString; Przykład Budowanie łańcucha z polskimi znakami Writeln( J #169 zyk Pascal ); Stałe W Pascalu można zadeklarować obiekty, których wartość jest niezmienna w trakcie obliczeń. Może to być stała Avogadry, ładunek elementarny, stała gazowa itd. Definicja const identyfikator-stałej : typ = wyrażenie-stałe 19

Określenie typu stałej jest opcjonalne. Przykład Const MaxInt: Integer = 100000; MinInt= -50000; e = 1.602177e-19; NA: Double = 6.02214E23; R: Single = 8.31451; Nazwisko = Kowalski ; Imie: String = Jan ; F = NA*e; Typ tablicowy Typy strukturalne (złożone) Układy danych takie jak wektor lub macierz reprezentowane są za pomocą tablic. Tablica składa się z ustalonej liczby elementów tego samego typu. Dostęp do poszczególnych elementów tablicy uzyskuje się poprzez indeks. Definicja typu tablicowego type identyfikator-typu = array [indeks1_min.. indeks1_max, indeks2_min.. indeks2_max, ] of typ-elementów; indeks jest liczbą całkowitą, stałą typu całkowitego lub wyrażeniem zbudowanym z liczb i stałych typu całkowitego. typ-elementów oznacza dowolny typ. Przykład type t1 = array [0..100] of integer; t2 = array [0..100] of t1; t3 = array [0..100] of array [0..100] of integer; t4 = array [0..100, 0..100] of integer; t5 = array [-5..15] of real; 20

Deklaracja zmiennej tablicowej var a: t1; b: t2; Zmienne tablicowe można deklarować z pominięciem deklaracji odpowiedniego typu. Przykład var a : array [0..100] of integer; b : array [-5..15] of real; z : array [1..110] of char; s : array [1..20] of string; Do elementu tablicy odwołujemy się poprzez indeks: identyfikator-tablicy [indeks1, indeks2,... ] indeks musi być wyrażeniem typu całkowitego, a jego wartość musi mieścić się w zadeklarowanym zakresie. Przykład i := a[5]; b[-i] := 3.14; s[1] := Dlugi lancuch ; 21

Instrukcje Instrukcja złożona Instrukcja złożona (blokowa) jest ciągiem instrukcji poprzedzonym słowem kluczowym i zakończonym słowem kluczowym end. Instrukcja ta tworzy z ciągu instrukcji jedną i używana jest w przypadku, gdy składnia języka wymaga użycia jednej instrukcji, a niezbędne jest wykonanie wielu. Struktura instrukcji złożonej instrukcja-1; instrukcja-2;... instrukcja-n Przykład a:=5; b:=3; c:=x*y Instrukcja warunkowa If Instrukcja warunkowa uzależnia wykonanie innej lub innych instrukcji od spełnienia lub niespełnienia podanego warunku. Definicja if wyrażenie then instrukcja; lub 22

if wyrażenie then instrukcja-1 else instrukcja-2; wyrażenie musi mieć wartość logiczną true lub false. Przed else nie może znajdować się średnik. Przykłady if x>0 then z:=x*y; if x<y then z:=y-x; y:=z*z end else z:=x-y; Instrukcja wyboru Case Jeżeli wykonanie różnych operacji zależy od wartości pewnej zmiennej, wówczas stosujemy instrukcję wyboru. Definicja case wyrażenie of stała(e) wyboru-1 : instrukcja-1; stała(e) wyboru-2 : instrukcja-2; stała(e) wyboru-n : instrukcja-n lub 23

case wyrażenie of stała(e) wyboru-1 : instrukcja-1; stała(e) wyboru-2 : instrukcja-2; stała(e) wyboru-n : instrukcja-n else instrukcja Wartość wyrażenia musi być typu porządkowego. Jeżeli jest kilka stałych wyboru, wówczas rozdzielamy je przecinkami lub dwiema kropkami (..). Przykłady var i: Byte; x,y: Real;... case i of 1 : y:=x; 2,3 : y:=2*x; 4..10 : y:=x*x var znak: Char;... readln(znak); case znak of 0.. 9 : Writeln( Wprowadziles cyfre ); a.. z : Writeln( Wprowadziles mala litere ); A.. Z : Writeln( Wprowadziles wielka litere ) else Writeln( Wprowadziles inny znak ) End; 24

Instrukcja skoku GoTo Instrukcja skoku pozwala przenieść sterowanie programu do instrukcji poprzedzonej etykietą. Instrukcja z etykietą może znajdować się powyżej lub poniżej instrukcji skoku. Definicja goto etykieta; Instrukcja poprzedzona etykietą i instrukcja skoku muszą znajdować się w tym samym bloku. Oznacza to, że nie jest dozwolony skok do lub na zewnątrz funkcji lub procedury. Etykieta składa się z identyfikatora lub ciągu do czterech cyfr. Wszystkie etykiety muszą być zadeklarowane w części deklaratywnej label lista-etykiet; Etykieta zakończona dwukropkiem (:) poprzedza instrukcję, do której ma być przekazane sterowanie. Przykład label e1;... if x>0 then goto e1; x:=-x; e1: Writeln(x);... Stosowanie instrukcji skoku nie jest zalecane, gdyż zmniejsza przejrzystość programu. Pascal posiada narzędzia, które pozwalają w pełni zastąpić instrukcję skoku. Dlatego staramy się jej nie używać. 25

Instrukcja iteracyjna for Instrukcje iteracyjne (pętle) służą do wielokrotnego wykonania pewnej sekwencji instrukcji. Pętlę typu for stosujemy wówczas, gdy z góry znana jest liczba powtórzeń. Instrukcja for może mieć jedną z dwóch postaci: for zmienna := wyrażenie1 to wyrażenie2 do instrukcja for zmienna := wyrażenie1 downto wyrażenie2 do instrukcja zmienna (tzw. zmienna sterująca) musi być typu całkowitego i powinna być zadeklarowana w danym bloku (funkcji, procedurze). Wartość wyrażenie musi też być typu całkowitego. Gdy stosujemy słowo kluczowe to, wówczas wartość zmiennej sterującej rośnie od wartości wyrażenie1 do wyrażenie2 co 1 z każdym cyklem. Natomiast gdy użyjemy downto maleje o 1. Przykłady 1. For i := 1 to 100 do Writeln (i); 2. for i := 0 to 100 do x := 0.1*i; y := Sqr(x); z := Sqrt(x); Writeln(i:3,x:5:1,y:10:5,z:10:5); 3. { oblicznie średniej arytmetycznej} var i, i_max: integer; sum, x : real;... readln(i_max); sum := 0; 26

for i := 1 to i_max do readln(x); sum := sum + x sum := sum / i_max; writeln( Srednia =, sum);... end. Instrukcja iteracyjna while (dopóki) Pętla typu while służy do wykonania iteracji ze sprawdzeniem warunku na początku. Ma ona postać: while warunek do instrukcja; warunek to wyrażenie logiczne, którego wynik daje wartość true lub false. instrukcja jest dowolną instrukcją prostą lub strukturalną. Instrukcja ta jest wykonywana tak długo, dopóki wyrażenie warunek ma wartość true. Przykład k := 10; // k typu integer while k>0 do k := k 2; x := k*k; writeln(k, x) Jakie liczby zostaną wyprowadzone na ekran? 27

Instrukcja iteracyjna repeat (powtarzaj) Pętla typu repeat służy do wykonania iteracji ze sprawdzeniem warunku na końcu. Ma ona postać: repeat instrukcja-1; instrukcja-2;... instrukcja-n; until warunek; Każda instrukcja to dowolna instrukcja prosta lub strukturalna. Może nią być np. inna pętla. warunek to wyrażenie logiczne, którego wynik daje wartość true lub false. Instrukcje zawarte między słowami kluczowymi repeat i until wykonywane są tak długo, aż wyrażenie warunek przyjmie wartość true. Przykład eps := 1.0e-12; sum := 0; x := 9.8765; y := 1; repeat y := y / x; sum := sum + y // średnik można pominąć until y<eps; 28

Funkcje i procedury Definicja Funkcją lub procedurą nazywamy wyodrębnioną część programu, stanowiącą pewną całość, posiadającą jednoznaczną nazwę i ustalony sposób wymiany informacji z pozostałymi częściami programu. Definicja procedury procedure nazwa-procedury (lista-parametrów-formalnych); część-opisowa ciąg-instrukcji Definicja funkcji function nazwa-funkcji (lista-parametrów-formalnych): typ wyniku; część-opisowa ciąg-instrukcji lista-parametrów-formalnych oraz część-opisowa są opcjonalne. lista-parametrów-formalnych zawiera deklaracje parametrów formalnych oddzielone średnikami, np.: procedure licz (a, b, c:real; var x1, x2: Real); function Moja_funkcja(a, b: real; i: integer; var x, y: double): Boolean; W ciągu-instrukcji funkcji musi wystąpić co najmniej jeden raz instrukcja przypisania lub nazwa-funkcji := wyrażenie Result := wyrażenie 29

Typ funkcji określamy za pomocą identyfikatora typu (np. extended). Są trzy podstawowe sposoby przekazywania informacji między obiektem wywołującym (np. programem) a funkcją lub procedurą: 1. przez wartość Proc1(a, b: real); (metoda bezpieczna, bo jest niemożliwe modyfikowanie przekazanej wartości, powolna w przypadku przekazywania dużych struktur tablic) 2. przez nazwę (zmienną, referencję) Proc2(var a, b: real); (pozwala wyprowadzić wyniki do programu wywołującego, szybka w przypadku przekazywania dużych struktur tablic) 3. przez stałą Proc3(const a, b: real); (łączy zalety metody 1 i 2: pozwala tylko wprowadzać wartości do procedury/funkcji, szybka w przypadku przekazywania dużych struktur tablic) Jest też metoda o nazwie efekty uboczne, w której korzysta się ze zmiennych globalnych. Deklaracja funkcji i procedur Jeżeli w definicji pierwszej procedury występuje wywołanie drugiej procedury, której definicja występuje po pierwszej procedurze, wówczas przed definicją pierwszej procedury należy zadeklarować drugą w następujący sposób: procedure identyfikator-procedury; forward; Podobnie w przypadku funkcji: function identyfikator-funkcji; forward; Deklaracja stanowi zapowiedź definicji procedury lub funkcji. W deklaracji nie podajemy list parametrów formalnych 30

Przykłady 1. procedure licz; forward; {deklaracji procedury} 2. program prog1;... procedure procedura2; forward; procedure procedura1;... procedura2;... end {procedura1}; procedure procedura2;... procedura1;... end {procedura2};... end {prog1}. Wywołanie funkcji i procedury Wywołanie funkcji następuje za pomocą podania nazwy funkcji jako argumentu dowolnego wyrażenia. Wywołanie procedury następuje za pomocą podania nazwy procedury. Jeżeli funkcja lub procedura zawiera parametry, to przy wywołaniu bezpośrednio za nazwą podaje się w nawiasach listę argumentów. Poszczególne argumenty oddziela się przecinkami. Liczba argumentów musi być zgodna z liczbą parametrów formalnych oraz typ każdego argumentu musi być zgodny z typem odpowiadającego mu parametru formalnego. Przykład If Moja_funkcja(2.5, 3.11, 7, x1, x2) then...... licz (a, b, c, x1, x2); 31

program prog2; type t1 = array [1..100] of real; t2 = array [1..100] of real; var a1 : t2; i : integer;... procedure proc1(var a2: t1; var k: ShortInt);... end {proc1};... proc1(a1,5);... end {prog2}. Czy wywołanie procedury proc1 jest poprawne? Poprawne wywołanie procedury proc1 w programie prog2: program prog2; type t1 = array [1..100] of real; t2 = array [1..100] of real; var a1 : t1; i : ShortInt;... procedure proc1(var a2: t1; var k: ShortInt);... end {proc1};... i := 5; proc1(a1,i);... end {prog2}. 32

Rekurencja Z rekurencją mamy do czynienia wówczas, gdy w części operacyjnej definicji funkcji występuje wywołanie tej samej funkcji. Przykład silnia, Matematyczna, rekurencyjna definicja silni: 1 d n 0! n, l = = n n 1!, d 0 ( ) a n l > a Odpowiednia funkcja ma postać function silnia(n: Byte): integer; if n=0 then silnia:=1 else silnia:= n*silnia(n-1) Funkcje i procedury predefiniowane w Delphi Funkcje arytmetyczne Object Pascal udostępnia w module standardowym SysUtils szeroką gamę gotowych funkcji i procedur. Funkcje arytmetyczne zestawione są w Tabeli 5. Nie ma wśród nich potęgowania. Jest tylko podnoszenie do drugiej potęgi oraz obliczanie pierwiastka kwadratowego z liczby. Sam język Pascal nie posiada operatora potęgowania. W tej sytuacji, chcąc wykonać operację potęgowania, korzysta się z zależności a b = e b lna Tak więc, jeśli chcemy podnieść liczbę 7 do potęgi 1,35, a wynik zapamiętać pod zmienną rzeczywistą x, piszemy: x := exp(1.35*ln(7)); Należy pamiętać, że argument funkcji ln musi być większy od zera i dlatego warto zrobić odpowiednie zabezpieczenie. W module Math znajdują się dwie funkcje: IntPower i Power, które służą do potęgowania. Pierwsza podnosi liczbę do potęgi całkowitej, a druga do potęgi rzeczywistej. 33

Tabela 5. Funkcje arytmetyczne Funkcja Znaczenie Typ argumentu Typ wyniku Abs ArcTan Cos Exp Frac Int Ln Pi wartość bezwzględna arcus tangens cosinus liczba e do potęgi danej przez argument część ułamkowa argumentu część całkowita argumentu logarytm naturalny 3,14159265358979322385 rzeczywisty całkowity rzeczywisty całkowity rzeczywisty całkowity rzeczywisty całkowity rzeczywisty całkowity rzeczywisty całkowity rzeczywisty całkowity ----------- rzeczywisty całkowity rzeczywisty rzeczywisty rzeczywisty rzeczywisty rzeczywisty rzeczywisty rzeczywisty Sin Sqr Sqrt sinus kwadrat argumentu pierwiastek kwadratowy rzeczywisty całkowity rzeczywisty całkowity rzeczywisty całkowity rzeczywisty rzeczywisty całkowity rzeczywisty 34

Przykłady IntPower(7,4) 7 4 Power(7,1.35) 7 1.35 Chcąc korzystać z modułu Math należy go zadeklarować w części uses uses SysUtil, Math; Moduł Math zawiera też wiele innych funkcji matematycznych, statystycznych i finansowych. Ich pełną listę można obejrzeć korzystając z systemu pomocy Delphi (przycisk F1 Delphi Help, hasło Math routines). Funkcje do wykonywania konwersji Round(x) funkcja zaokrągla wartość x typu rzeczywistego do najbliższej liczby całkowitej typu LongInt. Round(15.51) 16 Trunc(x) funkcja obcina część ułamkową argumentu rzeczywistego x i wynik zamienia na liczbę całkowitą typu LongInt. Trunc(15.51) 15 Chr(kod) funkcja zamienia zmienną kod typu Byte na znak o tym numerze. Chr(241) ± Funkcje łańcuchowe Length(łańcuch) funkcja określa długość łańcucha. Length( Moj nowy program ) 16 Concat(lista-łańcuchów) funkcja służy do połączenia kilku łańcuchów w jeden. Concat( Moj, nowy, program ) Moj nowy program Copy(łańcuch, indeks, licznik) wynikiem działania funkcji jest podłańcuch zmiennej łańcucha zaczynający od znaku określonego przez indeks i o długości licznik. Copy( Moj nowy program, 5, 4) nowy Delete(zmienna łańcuchowa, indeks, licznik) procedura usuwa z łańcucha przypisanego zmiennej łańcuchowej pewną jego część zaczynając od znaku o pozycji określonej przez indeks i o długości licznik. x := Moj nowy program ; // x zmienna łańcuchowa Delete(x, 5, 4) // x Moj program Pos(podłańcuch, łańcuch) funkcja określa pozycję, od której w łańcuchu zaczyna się podłańcuch. 35

Pos( nowy, Moj nowy program ) 5 Insert(podłańcuch, zmienna-łańcuchowa, indeks) procedura wstawia podłańcuch do łańcucha przypisanego zmiennej-łańcuchowej zaczynając od pozycji indeks. x := Moj program ; // x zmienna łańcuchowa Insert( nowy, x, 5) // x Moj nowy program StringOfChar(znak, licznik) funkcja wypełnia łańcuch powtarzającym się licznik razy znakiem. StringOfChar(M,15) MMMMMMMMMMMMMMM Str(argument-numeryczny, zmienna-łańcuchowa) procedura zamienia wartość numeryczną na wartość łańcuchową. Argument numeryczny może mieć postać: wyrażenie wyrażenie: długość wyrażenie: długość: miejsca-dziesiętne analogicznie jak w instrukcjach Write i Writeln. Str(15.1234:5:2, zmienna_str) zmienna_str 15.12 Val(łańcuch, zmienna-numeryczna, kod) procedura zamienia łańcuch na wartość numeryczną i podstawia pod zmienną-numeryczną typu całkowitego lub rzeczywistego. Zmienna kod typu Integer określa pozycję pierwszego błędnego znaku w łańcuchu, jeśli taki błąd istnieje. Gdy nie ma błędu, to kod = 0. Val( 15.1234, a, k) a = 15.1234, k = 0 (brak błędu) Liczby losowe Do generowania liczb losowych służy funkcja Random. Może ona być wywołana na dwa sposoby: bez argumentu Random lub z argumentem Random(arg) gdzie arg jest liczbą lub wyrażeniem całkowitym o wartości z zakresu liczb typu Integer. Wywołanie funkcji Random bez argumentu daje liczbę losową rzeczywistą z przedziału <0,1), natomiast wywołanie z argumentem daje liczbę całkowitą z zakresu od 0 do arg-1. Randomize bezparametrowa procedura służąca do zainicjowania generatora liczb losowych. Określa wartość predefiniowanej zmiennej RandSeed tzw. zarodek generatora liczb losowych. RandSeed jest to zmienna typu LongInt predefiniowana w module System. Przypisana jest jej wartość 0. Wartość tę można zmienić losowo wywołując procedurę Randomize lub przypisując zmiennej RandSeed dowolną wartość całkowitą, np.: RandSeed := 1; 36

W pierwszym przypadku, za każdym uruchomieniem programu będziemy mieć wygenerowany inny ciąg liczb losowych, a w drugim przypadku zawsze ten sam ciąg. Z drugiego rozwiązania korzystamy przy testowaniu programu, w którym występują zdarzenia losowe. Własna biblioteka funkcji i procedur Poprawnie funkcjonujące funkcje i procedury można gromadzić w bibliotekach w celu ich późniejszego wykorzystania w innych (nowych) programach. Własne biblioteki funkcji i procedur można tworzyć na kilka sposobów. Wybór sposobu zależy między innymi od tego, jak chcemy udostępnić bibliotekę osobom trzecim i czy chcemy ujawnić im tekst źródłowy funkcji i procedur. Dyrektywa parametryczna $Include Tutaj funkcje i procedury zapisane w tekście źródłowy umieszczamy w odrębnym pliku. Plik posiada swoją nazwę najlepiej z rozszerzeniem PAS, np. bibl_1.pas. W programie głównym w miejscu, gdzie kompilator ma widzieć funkcje i procedury zapisane w bibliotece bibl_1.pas, umieszczamy dyrektywę $Include o następującej postaci {$Include bibl_1.pas } lub krócej {$I bibl_1 } W razie konieczności nazwa biblioteki może być poprzedzona symbolem napędu lub/i nazwą foldera, np. {$I f:\moja_biblioteka\bibl_1.pas } Przykład Niech w pliku bibl_1.pas zapisana jest funkcja do rekurencyjnego obliczania silni function silnia(n: Byte): integer; if n=0 then silnia:=1 else silnia:= n*silnia(n-1) Wówczas program korzystający z tej funkcji może mieć postać program rekurencja_ins; {$APPTYPE CONSOLE} uses SysUtils; {$I 'bibl_1'} 37

var i: byte; j:integer; Write('i = '); Readln(i); j:=silnia(i); Writeln(i,'! = ',j); Readln end. Wadą tego rozwiązania jest jawna postać tekstu źródłowego oraz konieczność każdorazowego kompilowania. Wad tych pozbawione są moduły. Moduły Moduły w środowisku Delphi służą nie tylko to tworzenia skompilowanych bibliotek funkcji i procedur, ale w programowaniu obiektowym są ściśle powiązane z oknem graficznym programu każde okno ma swój moduł. Ogólna struktura modułu unit nazwa modułu; interface część opisowa implementation część implementacyjna initialization część inicjująca finalization część finalizująca end. //Modułu W części opisowej (po słowie interface) umieszczamy listę nagłówków funkcji i procedur (łącznie z listą parametrów formalnych i typem funkcji). Mogą tu znaleźć się też deklaracje zmiennych, stałych, typów a także innych modułów. Te ostatnie muszą być umieszczone bezpośrednio po słowie interface. Wszystkie elementy części opisowej są dostępne w programie lub module odwołującym się do danego modułu. Definicja zadeklarowanych funkcji i procedur znajduje się w części implementacyjnej, którą rozpoczyna słowo kluczowe implementation. Tu również można zadeklarować stałe, zmienne, typy itd. Nie będą one już ogólnie dostępne, lecz widoczne są tylko w części implementacyjnej. Części inicjująca i finalizująca są opcjonalne. Można w nich np. zarezerwować a następnie zwolnić pamięć, albo też zainicjować dane. Skompilowany moduł zapisywany jest do pliku o takiej samej nazwie jak nazwa modułu i posiada rozszerzenie dcu. Pliki dcu mogą być używane tylko w środowisku Delphi. Jeżeli w programie lub innym module chcemy skorzystać z zasobów danego modułu, musimy po słowie uses umieścić nazwę modułu. 38

Przykład W module Lib_1.dcu zdefiniowana jest funkcja silnia. Program rekurencja ma zadeklarowany moduł Lib_1 korzysta z funkcji silnia. unit Lib_1; interface function silnia(n: Byte): integer; implementation function silnia; if n=0 then silnia:=1 else silnia:= n*silnia(n-1) end. program rekurencja; {$APPTYPE CONSOLE} uses Lib_1, SysUtils; var i: byte; j:integer; Write('i = '); Readln(i); j:=silnia(i); Writeln(i,'! = ',j); Readln end. Biblioteki łączone dynamicznie, dll Zaletą bibliotek łączonych dynamicznie (z ang. dynamic link libraries, dll) jest to, że z ich zasobów korzystać mogą różne aplikacje pracujące pod systemem operacyjnym Windows. Z tego powodu biblioteki dll są bardzo użyteczne. Jednak ich tworzenie wykracza poza ramy wykładu. Typ rekordowy c.d. typu strukturalnego Rekord to złożona struktura danych, której składowe (pola) mogą należeć do różnych typów. Poszczególne pola mogą również być strukturami złożonymi. W definicji typu rekordowego określamy typ i identyfikator każdego pola. Definicja typu rekordowego 39

type identyfikator-typu = record lista-deklaracji-pól Każda deklaracja pola ma postać: lista-nazw-pól : opis-typu; Ostatnia deklaracja może mieć postać deklaracji typu wariantowego lub case deklaracja-pola-wyróżnikowego of wykaz-wariantów; case identyfikator-pola-wyróżnikowego of wykaz-wariantów; Deklaracja pola wyróżnikowego ma postać: identyfikator-pola-wyróżnikowego : identyfikator-typu-porządkowego; Przykład type data = record rok : word; miesiac : 1.. 12; dzien : 1.. 31 var dzien_urodzenia : data; dzien_urodzenia jest tu zmienną rekordową typu data. Zmienną rekordową można deklarować bezpośrednio pomijając definicję typu. Powyższy przykład można wówczas zapisać: var dzien_urodzenia : record rok : word; miesiac : 1.. 12; dzien : 1.. 31 W celu odwołania się do pola rekordu należy za identyfikatorem zmiennej rekordowej podać desygnator pola, który ma postać:.identyfikator-pola Odwołanie do pola rekordu ma więc postać: zmienna-rekordowa.identyfikator-pola Przykład dzien_urodzenia.rok := 1981; 40

dzien_urodzenia.miesiac := 12; dzien_urodzenia.dzien := 13; Odwołanie do pól rekordów można uprościć stosując instrukcję wiążącą. Ma ona postać: with identyfikator-zmiennej do instrukcja Instrukcja po słowie kluczowym do może być dowolną instrukcją prostą lub strukturalną. Najczęściej jest to instrukcja blokowa (... end). Stosując instrukcję wiążącą do poprzedniego przykładu uzyskamy: with dzien_urodzenia do rok := 1981; miesiac := 12; dzien := 13 Można zadeklarować tablicę typu rekordowego, przy czym typ rekordowy musi być wcześniej zdefiniowany. Jeżeli skorzystamy ze zdefiniowanego już typu data var dziecko : array [1.. 200] of data; wówczas zmienna dziecko jest tablicą typu rekordowego (tablicą, której elementami są rekordy). Do pól elementu nr 12 tablicy dziecko odwołujemy się w następujący sposób: dziecko[12].rok := 1981; dziecko[12].miesiac := 12; dziecko[12].dzien := 13; Można też użyć instrukcji wiążącej with dziecko[12] do rok := 1981; miesiac := 12; dzien := 13 W programowaniu obiektowym odwołanie się do metody obiektu jest podobne jak odwołanie się do pola zmiennej rekordowej: obiekt.nazwa-metody 41

np. Edit1.Text := Moje okienko ; Deklaracja zmiennej zespolonej complex var complex : record re, im : real Przypisanie wartości polom zmiennej complex complex.re := -1; complex.im := 2*pi; oraz przy użyciu instrukcji wiążącej with complex do re := -1; im := 2*pi Przykład Przekazywanie zmiennej rekordowej do procedury. type complex = record re, im : real var r,s,t : complex; procedure dodaj_cmplx(a,b: complex; var c: complex); c.re:=a.re+b.re; c.im:=a.im+b.im; {program główny}... r.re:=1; r.im:=2; s.re:=3; s.im:=4; dodaj_cmplx(r,s,t); Writeln(t.re,t.im);... end. 42

Operacje wejścia-wyjścia Do wprowadzania i wyprowadzania danych z komputera służą urządzenia zewnętrzne. Są to: klawiatura, monitor, drukarka, dyski stałe, optyczne (CD), dyskietki. Dane wyprowadzane przez te urządzenia nazywamy fizycznymi zbiorami danych. Do ich obsługi stosuje się pliki. Podstawowe operacje na plikach to: - zakładanie nowego fizycznego zbioru danych - wprowadzanie elementów do założonego pliku - dodawanie nowych elementów do istniejącego już pliku - przeszukiwanie pliku - wyprowadzanie elementów z pliku - wymiana elementów pliku W Delphi Pascalu mamy trzy klasy plików: - tekstowe - zdefiniowane - niezdefiniowane Przetwarzanie plików tekstowych 1. Deklaracja zmiennej plikowej var zmienna-plikowa : text; lub var zmienna-plikowa : TextFile; Zmienna plikowa daje w programie dostęp do pliku. 2. Skojarzenie zmiennej plikowej z fizycznym zbiorem danych AssignFile(zmienna-plikowa, wyrażenie-łańcuchowe) Wyrażenie-łańcuchowe łańcuch lub zmienna typu łańcuchowego. Określa ono nazwę zbioru (pliku) z ewentualnym napędem i ścieżką dostępu. Za pomocą procedury AssignFile skojarzyć można zmienną plikową z urządzeniami zewnętrznymi CON konsola (klawiatura i monitor) LPT1, LPT2... wyjścia równoległe na drukarkę COM1, COM2... szeregowe złącza wejścia / wyjścia NUL urządzenie puste 3. Otwarcie pliku na zapis Rewrite(zmienna-plikowa) 43

Procedura powoduje utworzenie nowego fizycznego zbioru danych o nazwie skojarzonej ze zmienną plikową Uwaga! Jeżeli plik o takiej nazwie już istnieje, to wszystkie zapisane w nim informacje zostaną zmazane. 4. Otwarcie pliku na odczyt Reset(zmienna-plikowa) Procedura powoduje otwarcie istniejącego pliku i ustawienie zewnętrznego zbioru w pozycji początkowej czyli przed pierwszym jego elementem. 5. Otwarcie pliku na dopisanie Append(zmienna-plikowa) Procedura powoduje otwarcie istniejącego pliku i ustawienie zewnętrznego zbioru na jego końcu. Dzięki temu możliwe jest dopisywanie tekstu na końcu zbioru. Uwaga! Plik otwierany na dopisywanie musi fizycznie istnieć. 6. Wyprowadzanie elementów tekstowych do pliku Write(zmienna-plikowa, lista-argumentów-wyjściowych) lub Writeln(zmienna-plikowa, lista-argumentów-wyjściowych) 7. Wprowadzanie elementów tekstowych z pliku Read(zmienna-plikowa, lista-zmiennych-wejściowych) lub Readln(zmienna-plikowa, lista-zmiennych-wejściowych) 8. Zamknięcie pliku CloseFile(zmienna-plikowa) W przetwarzaniu plików pomocne są następujące funkcje logiczne: Eof(zmienna-plikowa) Eoln(zmienna-plikowa) SeekEof(zmienna-plikowa) SeekEoln(zmienna-plikowa) Najważniejsza jest z nich jest funkcja Eof. Przyjmuje ona wartość true, gdy osiągnięty jest koniec pliku. Analogicznie funkcja Eoln ma wartość true, gdy odczytany jest cały wiersz. Przykład Dany jest plik tekstowy dane1.txt z trzema kolumnami liczb rzeczywistych. Należy skopiować go do pliku dane2.txt z pominięciem drugiej kolumny i podać liczbę wierszy. 44

... var x1,x2,x3: Real; i : Integer; plik1,plik2: TextFile; i := 0; AssignFile(plik1, dane1.txt ); AssignFile(plik2, dane2.txt ); Reset(plik1); Rewrite(plik2); while NOT Eof(plik1) do Readln(plik1,x1,x2,x3); Writeln(plik2,x1,x3); i := i+1 CloseFile(plik1); CloseFile(plik2); Writeln( Liczba wierszy w pliku =,i) End. Każda plikowa zmienna tekstowa posiada swój bufor wewnętrzny o wielkości 128 bajtów. Do jego zmiany służy procedura SetTextBuf postaci: SetTextBuf(zmienna-plikowa, bufor) lub SetTextBuf(zmienna-plikowa, bufor, rozmiar) bufor dowolna zmienna, rozmiar zmienna typu Integer. Zmienna rozmiar określa wielkość buforu w bajtach. Jeśli jest pominięta, wówczas wielkość buforu równa jest wielkości zmiennej bufor wyrażonej w bajtach, np. jeżeli zmienna bufor jest zadeklarowana następująco: var bufor : string[200]; to bufor będzie miał wielkość 200 bajtów. Do wyprowadzenia z bufora wszystkich znaków stosujemy procedurę Flush Flush(zmienna-plikowa). Bezparametrowa funkcja IOResult podaje w postaci liczby typu Integer status ostatnio wykonanej operacji wejścia-wyjścia. Warunkiem jest wyłączenie systemowej kontroli tych operacji. Do przełączania kontroli służą dyrektywy kompilatora {$I-} oraz {$I+}, które odpowiednio wyłączają i włączają kontrolę. Standardowo kontrola jest włączona! 45

Jeżeli operacja wejścia-wyjścia wykonana została bezbłędnie, wówczas wartość funkcji IOResult równa jest zeru. W przeciwnym razie jest różna od zera. Przykład Zastosowanie funkcji IOResult... AssignFile(plik1, dane1.txt ); {$I-} Append(plik1); {$I+} If IOResult <> 0 then rewrite(plik1); Jeśli plik dane1.txt istnieje, wówczas otwierany jest on na dopisywanie. W przeciwnym razie tworzony jest fizycznie nowy zbiór o nazwie dane1.txt otwarty na zapisywanie. Przetwarzanie plików zdefiniowanych Pliki zdefiniowane składają się z elementów tego samego typu. Elementami mogą być liczby, łańcuchy, tablice, rekordy. Elementy są ponumerowane. Pierwszy element posiada numer 0. W plikach zdefiniowanych można swobodnie poruszać się do przodu i do tyłu. Liczby zapisywane są dokładnie tak, jak występują w pamięci komputera czyli w kodzie binarnym. Zapis ten jest (przeważnie) krótszy, ale w pełni dokładny. Przetwarzanie plików zdefiniowanych 1. Deklaracja zmiennej plikowej var zmienna-plikowa : file of typ-elementów-pliku; Typem-elementów-pliku może być jeden z predefiniowanych typów liczb całkowitych lub rzeczywistych (np. Word, Byte, Integer, Real, Double, Extended), typ znakowy (Char) lub własny wcześniej zadeklarowany typ tablicowy albo rekordowy. 2. Skojarzenie zmiennej plikowej z fizycznym zbiorem danych wykonuje się tak samo, jak w plikach tekstowych: AssignFile(zmienna-plikowa, wyrażenie-łańcuchowe) 3. Otwarcia pliku dokonujemy za pomocą instrukcji Rewrite lub Reset. Procedura Rewrite(zmienna-plikowa) 46

powoduje utworzenie nowego fizycznego zbioru danych, natomiast Reset Reset(zmienna-plikowa) otwiera istniejący już plik. Otwarty plik znajduje się w pozycji początkowej (przed pierwszym elementem). Obie procedury pozwalają na zapisywanie i czytanie elementów z bieżącego położenia w pliku. 4. Nawigacja Procedura Seek Seek(zmienna-plikowa, pozycja) przesuwa bieżące położenie w pliku do elementu o numerze pozycja, natomiast funkcja FilePos typu LongInt FilePos(zmienna-plikowa) podaje bieżące położenie w pliku. Jeżeli znajdujemy się na początku pliku, to funkcja FilePos ma wartość zero. 5. Do odczytania i zapisania elementów do pliku służą dwie procedury Read(zmienna-plikowa, lista-zmiennych-wejściowych) Write(zmienna-plikowa, lista-argumentów-wyjściowych) Po wykonaniu każdej z tych procedur bieżące położenie w pliku zwiększa się o jeden (ustawiane jest przed następnym elementem). Nie używamy instrukcji Readln i Writeln. Przy zapisywaniu elementów do pliku nie stosuje się formatowania liczb. 6. Plik zdefiniowany zamykamy tak samo jak plik tekstowy: lub Close(zmienna-plikowa) CloseFile(zmienna-plikowa) W przetwarzaniu plików zdefiniowanych można korzystać z funkcji EoF Eof(zmienna-plikowa) Pomocna może być też funkcja FileSize typu LongInt FileSize(zmienna-plikowa) określająca aktualny rozmiar pliku (liczbę elementów w zbiorze). Przykład Otwórz nowy pliku typu Extended o nazwie losy1.txt i zapisz do niego 120 liczb losowych..... 47

var i: Word; x: Extended; plik1: file of Extended; AssignFile(plik1, losy1.txt ); Rewrite(plik1); for i := 1 to 120 do x := Random; Write(plik1,x); CloseFile(plik1); Writeln( Liczby zapisano do pliku. Naciśnij ENTER ); Readln end. Dopisz do istniejącego pliku typu Extended o nazwie losy1.txt kolejne 80 liczb losowych..... var i: Word; x: Extended; plik1: file of Extended; AssignFile(plik1, losy1.txt ); Reset(plik1); Seek(plik1, 120); for i := 1 to 80 do x := Random; Write(plik1,x); CloseFile(plik1); Writeln( Liczby dopisano do pliku. Naciśnij ENTER ); Readln end. Zaawansowane operacje na plikach Do zmiany bieżącego katalogu służy procedura ChDir ChDir(wyrażenie-łańcuchowe) gdzie wyrażenie-łańcuchowe typu String (w najprostszym przypadku łańcuch) określa nowy katalog. ChDir( A: ); ChDir( C:\Programy\dane ); 48

lancuch:= \wyniki ; ChDir(lancuch); Do utworzenia nowego katalogu służy procedura MkDir MkDir(wyrażenie-łańcuchowe) gdzie wyrażenie-łańcuchowe typu String określa nazwę nowego katalogu. MkDir( C:\Programy\dane\dane_startowe ); lancuch:= \nowe_wyniki ; MkDir(lancuch); Procedura Rename pozwala zmienić nazwę zbioru Rename(zmienna-plikowa, wyrażenie-łańcuchowe) Plik, którego nazwę chcemy zmienić, musi być skojarzony ze zmienną plikową, ale nie może być otwarty. AssignFile(plik1, dane1.txt ); Rename(plik1, dane2.txt ); Plik usuwamy za pomocą procedury Erase, Erase(zmienna-plikowa) Tutaj też plik, który chcemy usunąć, musi być skojarzony ze zmienną plikową, ale nie może być otwarty. AssignFile(plik1, dane2.dat ); Erase(plik1); Plików niezdefiniowanych nie będziemy omawiać w ramach tych zajęć Efektywne gospodarowanie pamięcią Zmienne dynamiczne Dotychczas poznane zmienne charakteryzowały się tym, że istniały przez cały czas wykonywania tej części programu, w której zostały zadeklarowane. Są to tzw. zmienne statyczne. W Pascalu możemy zbudować obiekty (zmienne, tablice, rekordy), dla których pamięć jest przydzielana i zwalniana na żądanie. Do obiektów takich odwołujemy się nie poprzez nazwę, lecz za pomocą wskaźnika. Wskaźnik określa adres pamięci zmiennej dynamicznej. Definicja typu wskaźnikowego 49

type identyfikator-typu = ^identyfikator-obiektu; type wskaznik = ^tablica; tablica = Array [1..10, 1..10] of Integer; var a: wskaznik; Zdefiniowaliśmy tu: typ tablicowy tablica, typ wskaźnikowy wskaznik oraz zmienną wskaźnikową a. Zmienna a podaje adres tablicy. Do obiektu wskazanego przez zmienną wskaźnikową odwołujemy się poprzez zmienną wskazywaną. Ma ona postać: zmienna-wskaźnikowa^ Tak więc do zdefiniowanej wcześniej tablicy odwołujemy się pisząc a^, do jej elementów a^[i,j], a^[1,2], itd. Do utworzenia zmiennej dynamicznej (przydzielenia jej pamięci) oraz ustalenia wartości zmiennej wskaźnikowej (przypisanie adresu pamięci) służy procedura New postaci: New(zmienna-wskaźnikowa) Do usunięcia zmiennej dynamicznej i zwolnienia w ten sposób pamięci służy procedura Dispose. Ma ona postać: Dispose(zmienna-wskaźnikowa) Mamy do dyspozycji też słowo kluczowe nil, które oznacza stałą typu wskaźnikowego nie określającą żadnego adresu. Potocznie mówi się, że słowo nil wskazuje na adres pusty. Przykład type wskaznik = ^tablica; tablica = Array [1..10, 1..10] of Integer; var a: wskaznik; i,j: Word;...... New(a); for j := 1 to 10 do for i := 1 to 10 do a^[i,j] := i*j; Dispose(a); 50