Wstęp

Transkrypt

Wstęp
1. Wstęp.
1
Wstęp
Bazą jest środowisko programowania Delphi firmy Borland International1,
bazującego na języku Object Pascal. Wersja darmowa Delphi 7 Personal jest
łatwo osiągalna w sieci.
Po uruchomieniu aplikacji wybrać z menu File\New\Other.. Console Application (tworzenie nowej aplikacji). Pojawi się okienko, w którym będziemy pisać
kod programu.
program nazwa;
//nagłówek
{$APPTYPE CONSOLE}
uses SysUtils;
blok deklaracyjny (definicje)
begin
część wykonawcza (instrukcje do wykonania)
end.
Uwaga: nie usuwać wierszy oznaczonych kolorem czerwonym.
2
2. Składowe języka. Deklaracje i definicje. Instrukcja przypisania.
2. Składowe języka - deklaracje i definicje - instrukcja
przypisania
2.1. Struktura blokowa programu i podprogramów
Rysunek 2.1 przedstawia schemat struktury bloku głównego programu.
Rys.2.1 Struktura programu źródłowego w języku Turbo Pascal
Nagłówek programu jest opcjonalny (czyli nieobowiązkowy) i składa się z:
- słowa kluczowego program i identyfikatora programu (nazwy) o długości
do 255 znaków,
- opcjonalnych parametrów programu w nawiasie - nazw plików wejścia
i wyjścia (standardowo Input oraz Output).
W sekcji deklaracji opisujemy elementy uŜywane przez program (deklaracje
i definicje). Istotna jest ich kolejność, np. wcześniej musi wystąpić definicja typu,
a potem deklaracja zmiennej tego typu.
W sekcji instrukcji występują kolejne akcje jakie ma wykonać program.
Instrukcje wykonywane są kolejno od pierwszej do ostatniej, pod warunkiem, Ŝe charakter instrukcji nie stanowi inaczej (np. iteracje, skoki, przekazanie wykonania do podprogramu itp.)
UWAGI:
• BEGIN to początek, a END to koniec sekcji instrukcji,
• kropka kończy tekst programu źródłowego, teksty po kropce są ignorowane,
• DEKLARACJE, DEFINICJE i INSTRUKCJE są oddzielane średnikami.
1. Wstęp.
3
2.2. Alfabet języka
Na alfabet języka składają się:
• duŜe i małe litery alfabetu łacińskiego (rozróŜnialne tylko dla stałych tekstowych)
• cyfry 0 do 9
• jednoznakowe symbole specjalne:
•
+
:
;
*
(
/
)
=
{
<
}
>
^
[
#
]
$
.
@
,
dwuznakowe symbole specjalne:
<>
<=
>=
:=
..
Podstawowe słowa kluczowe języka to:
AND
DOWNTO
IF
PROCEDURE
TYPE
ARRAY
ELSE
IN
PROGRAM
UNTIL
BEGIN
END
LABEL
RECORD
USES
CASE
FILE
MOD
REPEAT
VAR
CONST
FOR
NOT
SET
WHILE
DIV
FUNCTION
OF
THEN
WITH
DO
GOTO
OR
TO
Słowa kluczowe w języku Pascal moŜna pisać małymi bądź duŜymi literami.
2.3. Identyfikatory (nazwy)
Identyfikatory własne nadaje uŜytkownik dla programu, elementów przechowujących dane (zmiennych i stałych), typów, podprogramów, modułów.
Identyfikatory to nazwy złoŜone z ciągu znaków.
Identyfikatory standardowe (zastrzeŜone):
• typów danych - boolean, char, integer, real, string i inne,
• stałych (literałów) - false, true, maxint,
• funkcji - abs, sin, cos, sqr, sqrt, exp i inne,
• procedur - read, readln, reset, rewrite, write, writeln i inne,
• plików - input, output.
Zasady tworzenia identyfikatorów (nazw) własnych:
• nazwa to ciąg znaków (liter, cyfr, znaku podkreślenia _ ),
• nie wolno uŜywać spacji wewnątrz nazwy,
• pierwszym znakiem musi być litera,
• długość identyfikatora do 255 znaków,
• małe i duŜe litery nie są rozróŜniane.
4
2. Składowe języka. Deklaracje i definicje. Instrukcja przypisania.
Przykłady prawidłowych identyfikatorów:
A C5 pom2 suma wynik e22 delta dzien_p IDENT1 ident1
To_jest_dlugi_identyfikator_lecz_poprawny
UWAGI:
• IDENT1 i ident1 są identyfikatorami tego samego elementu,
• moŜna przedefiniować identyfikatory standardowe, lecz wtedy tracą one swoje znaczenie i nabierają nowego, nadanego przez uŜytkownika, np. moŜemy
wprowadzić zmienną o nazwie sin lecz wówczas tracimy moŜliwość uŜywania funkcji sinus.
2.4. Komentarz
Komentarz (własne uwagi lub opis działań) ma postać dowolnego ciągu znaków w nawiasach klamrowych lub od znaków // do końca wiersza:
{ dowolny komentarz }
// dowolny komentarz do końca wiersza
UWAGA: MoŜna dezaktywować niektóre instrukcje na etapie testowania programu zamykając je w nawiasach klamrowych. Przydatne jest i do dobrego tonu
naleŜy umieszczanie komentarzy, lecz ich nadmiar powoduje zmniejszenie przejrzystości programu.
2.5. Separatory
Separator nagłówka programu, deklaracji i instrukcji to średnik
;
Separatory symboli języka to:
spacja (lub ciąg spacji), ENTER, komentarz
z tym Ŝe:
• dwa dowolne słowa kluczowe, identyfikatory lub liczby bez znaku muszą być
oddzielone co najmniej jednym separatorem,
• ciąg spacji jest równowaŜny jednej spacji,
• po instrukcjach, po których występuje słowo kluczowe END, średnik nie jest
wymagany.
2.6. Stałe (literały)
Stałe liczbowe
- Stałe całkowite
Stałą liczbową całkowitą jest ciąg cyfr (bez spacji pomiędzy cyframi!), opcjonalnie poprzedzony znakiem + lub –.
Przykłady:
–1
23234
012
0
–1234
1. Wstęp.
5
Stałą liczbową w zapisie szesnastkowym poprzedzamy znakiem $.
Przykłady: $5
$FFF
$1A12
- Stałe rzeczywiste
Stałą liczbową rzeczywistą zapisujemy w dwóch formatach:
• zapis stałopozycyjny
[ +  ]m.n
− 
gdzie m i n to ciąg cyfr
UWAGA: w nawiasach klamrowych { } - elementy do wyboru,
w nawiasach kwadratowych [ ] - elementy opcjonalne (mogą zostać
pominięte).
Przykłady:
2.3336
–456.0
UWAGI:
1. Separatorem części całkowitej i ułamkowej jest kropka ! (nie przecinek)
2. NIE WOLNO:
.45
brak części całkowitej
3. WOLNO:
234. brak 0 po kropce dziesiętnej
• zapis zmiennopozycyjny
e 
E
[–]m[.n]   [–]k
gdzie m, n, k to ciąg cyfr.
Litera E (lub e) interpretuje pomnoŜenie liczby dziesiętnej m.n przez 10
do potęgi k.
Zapis zmiennopozycyjny (zwany teŜ naukowym) jest przydatny dla liczb
bardzo duŜych i bardzo małych.
Przykłady:
–1.55e–6
3.4E7
{tzn. –1.55.10-6=0.00000155}
{tzn. 3.4.107=34000000}
Stałe łańcuchowe
Stałą łańcuchową (tekstową) jest ciąg znaków ograniczonych apostrofami.
Przykłady:
'Turbo Pascal'
'Kowalski'
'a'
W stałych tekstowych małe i duŜe litery są istotne i rozróŜniane.
Stałe logiczne
Wartości logiczne nadawane zmiennym i wyraŜeniom typu logicznego boolean
to:
true prawda
false fałsz
6
2. Składowe języka. Deklaracje i definicje. Instrukcja przypisania.
2.7. Klasyfikacja typów danych
KaŜda stała, zmienna, wyraŜenie lub funkcja jest określonego typu - pozwala to
uniezaleŜnić się od fizycznej reprezentacji obiektów w pamięci operacyjnej,
umoŜliwia kontrolę dozwolonych wartości dla danego typu.
Typ określa:
• zbiór wartości, do którego naleŜy stała, bądź jakie moŜe przyjmować zmienna
czy wyraŜenie lub jakie mogą być generowane przez funkcję,
• zbiór operacji jakie mogą być wykonywane na danych tego zbioru.
Typy danych oferowane przez język Turbo Pascal przedstawia rys. 2.2.
Rys. 2.2 Klasyfikacja typów danych
Typ standardowy to nazwany, zdefiniowany w języku zbiór wartości, z którego uŜytkownik moŜe korzystać bez definiowania.
Typy strukturalne wprowadzone zostały w związku z praktycznymi potrzebami
reprezentacji złoŜonych danych.
W sekcji instrukcji wolno uŜywać tylko identyfikatorów standardowych i takich, których znaczenie określono w sekcji deklaracji.
2.7.1. Typy proste (porządkowe i rzeczywiste)
Typy porządkowe
Typy porządkowe zawierają skończony, uporządkowany zbiór wartości.
1. Wstęp.
7
A. Typy całkowite
Typ ten przeznaczony jest dla zmiennych, które przechowują dane o
wartościach naleŜących do zbioru liczb całkowitych. Podstawowy typ
całkowity to typ integer. UŜywamy go w deklaracji zmiennych w
przykładowej postaci:
var
x, y : integer ;
Zakres wartości typu integer zaleŜy od implementacji – dla komputera PC
stała Maxint określa maksymalną wartość dla tego typu.
B. Typ znakowy - char
Zmienne tego typu mogą przyjmować wartości pojedynczego znaku z tablicy ASCII.
Przykład:
var znak : char ;
begin
znak := 'c' ; {operacja przypisania – nadania wartości}
.....
end.
C. Typ logiczny - boolean
Zmienne tego typu mogą przyjmować wartości stałych logicznych true lub
false.
D. Typ wyliczeniowy
Typ wyliczeniowy jest typem prostym, porządkowym stanowiącym skończony, uporządkowany zbiór wartości, oznaczonych nazwami (identyfikatorami) wybranymi przez uŜytkownika:
(lista wartości)
Lista jest ciągiem nazw elementów, oddzielonych przecinkami.
MoŜna zastosować opis typu bezpośrednio przy deklaracji zmiennych:
var
forma : (prostokat, kwadrat, elipsa, okrag) ;
dzien : (pon, wto, sro, czw, pia, sob, nie) ;
lub wcześniej zdefiniować typ:
type
figura =
(prostokat, kwadrat, elipsa, okrag) ;
dni =
(pon, wto, sro, czw, pia, sob, nie) ;
var
forma : figura ;
8
2. Składowe języka. Deklaracje i definicje. Instrukcja przypisania.
dzien : dni ;
Dopuszcza się wykonywanie na elementach typu wyliczeniowego operacji
przypisania, np.:
forma := elipsa ;
dzien := pon ;
porównania (porządek według wyliczenia) np.:
po < wt
elipsa > kwadrat
a takŜe uŜycia funkcji standardowych dla typów porządkowych, np.:
pred(wt) ⇒
succ(cz) ⇒
ord(wt) ⇒
pon
pia
1
{poprzedni element}
{następny element}
{kolejny numer elementu – liczony od 0}
Dla elementów tego typu nie wolno stosować operacji arytmetycznych
oraz wykorzystywać zmiennych tego typu w instrukcjach wprowadzania
i wyprowadzania danych (read/write).
E. Typ okrojony
Typ okrojony oznacza podzbiór dowolnego typu porządkowego (boolean,
char, integer, wyliczeniowego), zwanego typem bazowym:
w1 .. w2
gdzie w1 ≤ w2
Przykład:
type
dni = (pon, wto, sro, czw, pia, sob, nie) ;
var
dzien : dni ; {zmienna bazowego typu wyliczeniowego}
zakres : 1..10 ; {okrojenie typu integer}
cyfra : '0'..'9' ; {okrojenie typu char}
dni_wolne: sob.. nie ;
Dozwolone operacje obowiązują jak dla typu bazowego.
Typy rzeczywiste
Typy rzeczywiste uŜywane są dla zmiennych przyjmujących wartość liczbową
rzeczywistą. Podstawowym typem jest typ real.
UWAGI:
• opcje pakietu dopuszczają brak sprawdzania zakresów w trakcie wykonania
programu, w menu Options – Compiler – Runtime errors – Range checking
moŜna uaktywnić sprawdzanie zakresów,
1. Wstęp.
•
9
przykładowo zmienne zajmują: char - 1 bajt pamięci, integer - 2 bajty, real
- 6 bajtów.
2.7.2. Typ łańcuchowy - string
Typ łańcuchowy umoŜliwia przechowywanie wartości typu tekstowego:
string
string [n]
– do 255 znaków
– deklaracja maksymalnej długości łańcucha n znaków
Przykład deklaracji zmiennych tego typu:
var napis
nazwisko
: string ;
: string [30] ;
2.7.3. Typy strukturalne
Typy strukturalne (tablicowy, rekordowy, zbiorowy, plikowy) to typy złoŜone zawierają wiele danych o typach prostych a takŜe strukturalnych, zostaną omówione osobno w dalszej części skryptu.
2.8. Deklaracje i definicje
2.8.1. Deklaracja modułów
Moduły są to skompilowane biblioteki gotowych elementów (najczęściej procedur, funkcji i typów danych), które, po zadeklarowaniu modułu, moŜna wykorzystać w programie.
uses lista_nazw_modułów ;
np. uses graph ;
uses crt, printer ;
2.8.2. Deklaracja nazwanych stałych i zmiennych inicjowanych
Definicja nazwanej stałej:
const nazwa1= wartość1; nazwa2=wartość2 ; ....;
Wartość nazwanej stałej nie moŜe być zmieniana w trakcie przebiegu programu.
Jej typ wynika z nadanej wartości.
Definicja zmiennych inicjowanych:
const nazwa1: typ= wartość1; nazwa2: typ=wartość2 ; ....;
Wartość zmiennej inicjowanej moŜe być zmieniana w trakcie przebiegu programu.
Przykłady:
const e = 2.71828 ;
n = 50 ;
10
2. Składowe języka. Deklaracje i definicje. Instrukcja przypisania.
2.8.3. Definicja typu
Definicja typu jest nazwanym (własnym) opisem typu, uŜywanym potem m.in.
w deklaracjach zmiennych.
type nazwa_typu1 = opis_typu1 ;
nazwa_typu2 = opis_typu2 ;
.....;
Przykład:
type
dni_tyg = (pon, wto, sro, czw, pia, sob, nie);{typ wyliczeniowy}
licznik = 1..20 ;
{typ okrojony całkowity}
napis = string[30] ;{typ łańcuchowy o długości max. 30 znaków}
2.8.4. Deklaracje zmiennych
Deklaracje wprowadzonych przez uŜytkownika zmiennych umieszczamy
w bloku poprzedzonym słowem kluczowym var, w następującej, ogólnej postaci:
var lista nazw zmiennych: nazwa_lub_opis_typu1;
lista nazw zmiennych: nazwa_lub_opis_typu2 ;
....;
Obiekty listy oddzielamy przecinkami.
Przykładowe deklaracje:
var
x, suma, v15
wynik1
znak
czy_jest
nazwisko, imie
alfa
x5, y , z
: integer ; {trzy zmienne typu całkowitego}
: real ; {typ rzeczywisty}
: char ;
{typ znakowy}
: boolean ;
{typ logiczny}
: napis ;
{ typ wcześniej opisany}
: dni_tyg ;
{ typ wcześniej opisany}
: licznik ;
{ typ wcześniej opisany}
MoŜna równieŜ stosować opisy typów w deklaracji zmiennych, na przykład:
var
liczby
dni
: 1..23 ;
: (pon, wto, sro, czw, pia, sob, nie) ;
i wówczas definicja typów nie jest wymagana.
W niektórych sytuacjach (przykładowo przy definiowaniu funkcji lub procedur), konieczne będzie wcześniejsze zdefiniowanie typów uŜywanych w programie.
1. Wstęp.
11
2.9. Instrukcja przypisania
Instrukcja przypisania jest podstawową, prostą instrukcją w większości języków programowania. Za jej pomocą zmiennym nadawane są wartości w trakcie wykonywania programu.
identyfikator_zmiennej := wyraŜenie ;
gdzie
:=
dwuznakowy operator przypisania.
Najprostsza postać wyraŜenia to stała lub zmienna:
wyraŜenie → stała
wyraŜenie → zmienna
Działanie instrukcji przypisania polega na obliczeniu wartości wyraŜenia po
prawej stronie operatora i nadanie tej wartości zmiennej o identyfikatorze po lewej stronie znaku przypisania.
UWAGA: Zachodzi konieczność zachowania zgodności typów zmiennej i wyraŜenia (wyjątkiem jest np. dopuszczenie przypisania zmiennej typu rzeczywistego wartości wyraŜenia typu całkowitego).
Przykłady prawidłowych instrukcji przypisania:
program p2_p;
var
x, y
: real ;
licznik
: integer ;
znak
: char ;
napis
: string ;
czy
: boolean ;
dzien
: (pon, wto, sro, czw, pia, sob, nie) ;
liczba
: 1..100 ;
begin
x := 2.56 ;
y := x ; {przypisanie zmiennej y tej samej wartości co x}
licznik := 234 ;
znak := 'A' ;
czy := true ;
dzien := czw ;
liczba := 34 ;
napis := 'To jest mój program' ;
{..... dalsza część programu}
end .
12
3. WyraŜenia arytmetyczne i logiczne. Operacje wejścia i wyjścia.
3. WyraŜenia arytmetyczne i logiczne operacje wejścia i wyjścia
3.1. Definicja wyraŜenia
WyraŜenia arytmetyczne słuŜą do zapisu wykonywania operacji obliczeniowych w trakcie przebiegu programu. WyraŜeniem arytmetycznym moŜe być stała,
zmienna lub zapis złoŜonej operacji na stałych, zmiennych i funkcjach (standardowych, bibliotecznych lub własnych uŜytkownika) z uŜyciem operatorów arytmetycznych.
Bardziej skomplikowane wyraŜenia zawierają operatory i funkcje. Ponadto
uŜywamy nawiasów (tylko okrągłych!) w celu zmiany kolejności działań.
Definicja rekurencyjna wyraŜenia (czyli definiowanie przez samą siebie) ma
postać:
wyraŜenie → stała
wyraŜenie → zmienna
wyraŜenie → identyfikator_funkcji (wyraŜenie)
wyraŜenie → wyraŜenie operator wyraŜenie
Z definicji wynika, Ŝe wyraŜenia po prawej stronie definicji mogą mieć kaŜdą
z postaci definiowanych, a zatem np. argument funkcji moŜe być np. inną funkcją
(tzw. zagnieŜdŜanie funkcji), a operatorami moŜna łączyć wiele wyraŜeń.
WyraŜenia uŜywane są najczęściej w instrukcjach przypisania po prawej
stronie symbolu :=. Dopuszczalne jest uŜycie wyraŜeń arytmetycznych (takŜe logicznych) jako parametru standardowej procedury wyprowadzania danych (write,
writeln), a takŜe w innych instrukcjach zgodnie z zasadami ich składni.
3.2. Operatory arytmetyczne
RozróŜniamy następujące operatory:
• jednoargumentowe
− zmiana znaku,
+ powielenie znaku,
• dwuargumentowe
multiplikatywne
∗
mnoŜenie,
/
dzielenie (rzeczywiste),
ƒdivƒ
dzielenie całkowite (obydwa argumenty operacji
muszą być całkowite, wynik jest całkowity),
ƒmodƒ
reszta z dzielenia całkowitego (jak wyŜej),
3. WyraŜenia arytmetyczne i logiczne. Operacje wejścia i wyjścia.
13
(znak ƒ przedstawia spację),
addytywne
+
–
Przykłady:
7/2 →3.5
7 div 2 → 3
dodawanie,
odejmowanie.
4/2 → 2.0
17 mod –5 → 2
6.5/2
→ 3.75
3.5*x–6/(4–x)+5
Kolejność wykonywania operacji określają następujące reguły:
WyraŜenia w nawiasach wykonywane najwcześniej (od najbardziej wewnętrznych),
• Kolejność operacji (od najwcześniej wykonywanych):
1. jednoargumentowe,
2. multiplikatywne,
3. addytywne.
•
UWAGA:
• Dla operatorów tej samej wagi - kolejność działań od lewej do prawej.
• JeŜeli w wyraŜeniu są tylko argumenty całkowite i nie ma dzielenia rzeczywistego to wynik jest typu integer.
• JeŜeli występuje chociaŜ jeden element typu real lub dzielenie rzeczywiste to
wynik jest typu real.
Na elementach tekstowych (char, string) moŜemy dokonywać operacji łączenia
tekstów (tzw. konkatenacja) uŜywając znaku +.
Przykład:
nazwisko := 'Kowalski' ;
tekst_1 := 'Panƒ' + nazwisko ;
W rezultacie zmienna tekst_1 przyjmie wartość tekstową 'Pan Kowalski'.
3.3. Funkcje standardowe
Istnieje moŜliwość uŜycia w wyraŜeniu funkcji standardowych (w kontekście
identycznym jak zmienne proste) w postaci:
identyfikator_funkcji (argument)
Argumentem moŜe być wyraŜenie odpowiedniego typu. Zestaw funkcji standardowych przedstawia tabela 3.1.
14
3. WyraŜenia arytmetyczne i logiczne. Operacje wejścia i wyjścia.
Tabela 3.1 Funkcje standardowe
Znaczenie
wartość
bezwzględna
pierwiastek
kwadratowy
kwadrat
ex
logarytm
naturalny
sinus
cosinus
Arcus tangens
Nazwa
Typ wyniku Typ argumentu
Przykład
funkcji
całkowity
całkowity
abs
abs(-2) ⇒ 2
rzeczywisty rzeczywisty
sqrt
rzeczywisty
rzeczywisty
sqrt(5.45)
sqr
exp
rzeczywisty
rzeczywisty
rzeczywisty
rzeczywisty
sqr(x-5)
exp(-x/2)
ln
rzeczywisty
rzeczywisty
ln(2∗x-4)
sin
cos
arctan
rzeczywisty
rzeczywisty
rzeczywisty
round
trunc
succ
pred
rzecz. (radiany)
rzecz. (radiany)
rzeczywisty
całkowity
rzeczywisty
rzeczywisty
całkowity
rzeczywisty
rzeczywisty
całkowity
rzeczywisty
całkowity
rzeczywisty
porządkowy porządkowy
porządkowy porządkowy
round(3.6) ⇒ 4
trunc(3.6) ⇒ 3
succ ( 'g' ) ⇒ 'h'
pred( 'j' ) ⇒ 'i'
chr
znakowy
chr(49) ⇒ '1'
ord
length
całkowity
znakowy
łańcuchowy całkowity
część całkowita int
część
ułamkowa
zaokrąglenie
obcięcie
znak następny
znak poprzedni
znak
o podanym
kodzie ASCII
kod znaku
długość tekstu
frac
całkowity
sin(3∗alfa)
cos(beta/2)
arctan(fi)
int(2.5) ⇒ 2.0
frac(3.6) ⇒ 0.6
ord( '1' ) ⇒ 49
length( 'alfa' ) ⇒ 4
W wyraŜeniach istotne są wszelkie ograniczenia obszaru określoności funkcji,
np. uŜycie ln(-3), sqrt(-5.0) spowoduje błędy wykonania.
Brak w języku operatora lub funkcji standardowej potęgowania, stąd stosuje się:
x4 ⇒ x∗x∗x∗x lub sqr (x)∗sqr (x)
lub sqr (sqr (x)),
MoŜna zastosować funkcję power(podstawa, wykładnik) – potrzeba deklaracja
biblioteki math w seksji uses, np:
program test;
uses sysutils, math;
integer:x;
begin
x:=power(5.7, 6.89);
3. WyraŜenia arytmetyczne i logiczne. Operacje wejścia i wyjścia.
15
writeln (x);
readln;
end.
w przypadku wyŜszych lub niecałkowitych potęg stosujemy zapis:
xy
⇒
exp (y∗ln (x))
Brak w języku równieŜ innych, często potrzebnych funkcji, jak na przykład
tangens czy logarytm dziesiętny. Trzeba wówczas korzystać z elementarnych
wzorów matematycznych:
tg x =
sin x
cos x
log x =
ln x
ln 10
NaleŜy zwrócić uwagę na moŜliwość wystąpienia przekroczenia dopuszczalnych zakresów wartości zmiennych przy obliczeniach.
PoniŜsze wyraŜenie w postaci matematycznej:
5 x 2 − 2 sin2 x + 1,5 ⋅ 10 −5
x + 2 − 2 + y 1,5
moŜna zapisać w przykładowej postaci:
(5∗x∗x – 2∗sin(x)*sin(x)+1.5e–5)/(abs(sqrt(x+2)–2)+exp(1.5∗ln(y)))
W przypadku zastosowania w instrukcji przypisania wyraŜenia zawierającego
zmienną, której aktualnie przypisujemy wartość, np.:
x := x + 5 ;
obliczana jest wartość wyraŜenia (wartość x powinna być wcześniej określona),
a następnie uaktualniana wartość zmiennej, np. w ciągu instrukcji:
...
x := 5 ;
x := sqr(x) ; {x będzie równe 25}
x := x +2 ;
{powiększenie poprzedniej wartości x o 2,
x będzie równe 27}
...
Pisząc wyraŜenie naleŜy szczególnie uwaŜać na:
- operatory arytmetyczne – szczególnie mnoŜenia: 2*x a nie 2x
- format wykładniczy – np.1.34E-8 (107 to 1e7 a nie e7),
- argumenty funkcji trygonometrycznych – podajemy je w radianach, w przypadku konieczności uŜywania kąta w stopniach naleŜy przeliczyć kąt na radiany wyraŜeniem stopnie*pi/180, (pi jest predefiniowaną nazwą stałej).
- hierarchię działań – odpowiednie stosowanie nawiasów,
16
-
3. WyraŜenia arytmetyczne i logiczne. Operacje wejścia i wyjścia.
brak w języku operacji potęgowania, brak funkcji tangens, cotangens, logarytm dziesiętny,
róŜnicę między funkcjami o podobnych nazwach – sqr i sqrt.
3.4. WyraŜenia logiczne
WyraŜeniem logicznym moŜe być:
1. stała logiczna
true
⇔
prawda
false
⇔
fałsz
2. zmienna typu boolean,
3. relacja - porównanie w sensie liczbowym lub tekstowym (kolejności
alfabetycznej) według schematu:
wyraŜenie1 operator_relacji wyraŜenie2
Relacja ma wartość logiczną true lub false. Operatorami relacji są:
<
=
>
<=
>=
<>
„róŜny”
Przykłady relacji:
x12 < 2
(4∗x+1.5) < 30.7
nazwisko >= 'G'
{nazwiska od litery G do końca alfabetu}
UWAGA: NaleŜy unikać operatorów < , =, >dla typów rzeczywistych ze względu na przybliŜenie wartości.
4. stałe logiczne, zmienne logiczne, relacje (w nawiasie!), połączone operatorami logicznymi:
- jednoargumentowymi:
notƒ (negacja)
np. notƒ(i < 5)
notƒobecny
- dwuargumentowymi:
ƒandƒ (iloczyn logiczny –"i" – jednoczesne spełnienie
warunków)
np. (x > 0)ƒandƒ(x < 3)
ƒorƒ (suma logiczna –"lub" – alternatywne spełnienie warunków)
np. (x < 0)ƒorƒ(x > 100)
ƒxorƒ (róŜnica symetryczna – suma „modulo2”),
(gdzie znak ƒ przedstawia spację).
PoniŜsza tabela przedstawia wartości wyraŜeń logicznych w zaleŜności od wartości argumentów:
3. WyraŜenia arytmetyczne i logiczne. Operacje wejścia i wyjścia.
17
Argument 1
Argument 2
and
or
xor
false
false
false false
false
true
false
false true
true
false
true
false true
true
true
true
true
true
false
W operacji przypisania wartości zmiennej logicznej musi zachodzić zgodność
typów. Wartość wyraŜenia logicznego moŜna przypisać zmiennej typu boolean
bądź uŜyć je w instrukcjach warunkowych lub iteracyjnych (dalsza część skryptu).
Przykład:
program p3 ;
var
zwolniony, obecny
: boolean ;
ocena
: real ;
liczba_obecnosci
: integer ;
begin
ocena := 3.5 ;
liczba_obecnosci := 12 ;
obecny := liczba_obecnosci>=10 ;
zwolniony := (ocena >= 4.5) ƒandƒobecny ;
writeln(zwolniony)
end.
3.5. Standardowe procedury wejścia/wyjścia
(wczytywania i wyprowadzania danych)
Do wprowadzenia (standardowym urządzeniem wejścia jest klawiatura) wartości zmiennej w trakcie wykonania programu słuŜy instrukcja (wykonanie procedury standardowej) read(readln) – „czytaj”, o postaci:
 read 

 [(lista zmiennych)] ;
readln 
gdzie {} – elementy do wyboru, [ ] – element opcjonalny.
Przykłady:
readln (x1, x2, x3, y) ;
read(x) ;
readln ; {brak listy – moŜna podać cokolwiek – taka instrukcja
słuŜy do chwilowego zatrzymania programu}
Oczywiście uŜyte zmienne powinny być zadeklarowane.
Po napotkaniu instrukcji read (readln) program zatrzymuje się i oczekuje podania danych dla zmiennych z listy (odpowiednich typów!). Podawane dane oddzie-
18
3. WyraŜenia arytmetyczne i logiczne. Operacje wejścia i wyjścia.
lamy co najmniej jedną spacją lub w osobnych wierszach. JeŜeli wpiszemy zbyt
wiele liczb, to nadwyŜka jest pamiętana dla następnej instrukcji read, natomiast
w instrukcji readln czytane jest tyle wartości ile elementów zawiera lista, a reszta
zostaje zignorowana.
NaleŜy uwaŜać na zgodność typów zmiennych i danych (stała całkowita moŜe
być wczytana do zmiennej rzeczywistej lecz nie odwrotnie).
Instrukcją (procedurą standardową) wyprowadzania danych (domyślnie na
ekran) jest write(writeln) – „pisz” – o strukturze:
 write 

 [ (lista elementów) ] ;
 writeln 
Po wykonaniu instrukcji write kursor pozostaje na końcu wiersza, zaś po
writeln następuje zmiana wiersza. Instrukcja writeln bez parametrów wyprowadza pusty wiersz.
Elementami listy są stałe, zmienne i wyraŜenia, wraz z opcjonalnym określeniem formatu wyprowadzenia o postaci:
wyraŜenie_typu_całkowitego:m
gdzie m to wyraŜenie całkowite określające szerokość pola (liczba znaków), dla
liczb typu real m ≥ 8, jeŜeli mniejsze (np. 0) to szerokość dopasowana będzie do
niezbędnej liczby cyfr do zapisu wartości (z ewentualnym znakiem),
wyraŜenie_typu_całkowitego:m:n
m - jak wyŜej, n - liczba cyfr po kropce dziesiętnej (tylko dla typu real !).
Przykład:
program p4 ;
var x
: real ;
y
: string ;
begin
x := -21.546 ;
y := 'Napis=' ;
writeln ;
writeln(x) ;
writeln(x:8) ;
writeln(x:10:3) ;
writeln(y:10, 'TurboPascal':12) ;
end.
{wyprowadzenie pustego wiersza)
{⇒ –2.154600000E+01}
{⇒ –2.2E+01}
{⇒ -21.546}
{⇒
Napis= TurboPascal}
{ - to spacja}
4. Schematy blokowe. Instrukcje warunkowe.
19
4. Schematy blokowe - instrukcje warunkowe
4.1. Elementy graficzne schematów blokowych
Schematy blokowe słuŜą do sporządzenia graficznej ilustracji tworzonego algorytmu. Poszczególne operacje (wprowadzanie danych, analiza warunków, iteracje) przedstawiane są w postaci bloków symbolizujących odpowiednią operację,
które są połączone strzałkami, odzwierciedlającymi kolejność wykonania operacji. PoniŜszy rysunek przedstawia podstawowe, stosowane w schematach blokowych elementy graficzne, które posłuŜą do wyjaśnienia mechanizmu instrukcji
warunkowych i iteracyjnych.
Start i stop
START
STOP
Operacje wejścia i wyjścia
wczytaj
a,b,x
Instrukcja wykonawcza (proces)
pisz suma, wynik
Blok decyzyjny
oblicz
suma:=a+b
czy
suma>0
TAK
NIE
Rys.4.1 Elementy graficzne uŜywane w schematach blokowych.
20
4. Schematy blokowe. Instrukcje warunkowe.
4.2. Klasyfikacja instrukcji
Rys. 4.2 Klasyfikacja instrukcji w języku Turbo Pascal
4.3. Instrukcje warunkowe
4.3.1. Instrukcja if.. then.. (jeŜeli.. to..)
Instrukcja warunkowa słuŜy do warunkowego wykonywania dowolnej instrukcji (grupy instrukcji). UŜywamy dwóch postaci instrukcji.
Postać skrócona:
if WB then Instrukcja ;
”jeŜeli”
”to”
W instrukcji wykonywane jest badanie warunku logicznego WB, a następnie:
- jeśli WB = true to Instrukcja jest wykonywana,
- jeśli WB = false to Instrukcja jest ignorowana.
Postać pełna:
if WB then Instrukcja_1 else Instrukcja_2 ;
”jeŜeli” ”to”
”w przeciwnym przypadku”
W instrukcji wykonywane jest badanie warunku logicznego WB, a następnie:
- jeśli WB = true to wykonywana jest Instrukcja_1,
4. Schematy blokowe. Instrukcje warunkowe.
21
- jeśli WB = false to wykonywana jest Instrukcja_2.
Instrukcja if.. then.. naleŜy do grupy instrukcji strukturalnych – w jej skład
wchodzi inna instrukcja (prosta lub strukturalna).
Schematy blokowe ilustrujące działanie obu postaci instrukcji ilustruje rys.4.3.
postać skrócona
postać pełna
Czy WB
jest
prawdą ?
Czy WB
jest
prawdą ?
NIE
NIE
TAK
TAK
Instrukcja1
Instrukcja2
Instrukcja
Rys.4.3 Schemat blokowy istrukcji if.. then..
Przykład 1:
program p4_1 ;
uses crt ;
var x : real ;
begin
clrscr ;
readln(x) ;
if x >= 0 then writeln ('Pierwiastek wynosi:', sqrt(x):10:3)
else writeln ('x jest ujemne') ;
readln
end.
W powyŜszym przykładzie instrukcja wyprowadzająca wartość pierwiastka
zostanie wykonana jeŜeli zajdzie warunek x >= 0, w przeciwnym wypadku zostanie wykonana instrukcja wyprowadzająca komunikat, Ŝe x jest ujemne.
Instrukcje wewnętrzne w instrukcji if..then.. mogą takŜe być innymi instrukcjami if..then... Taką postać stosujemy w przypadku konieczności wykonania
22
4. Schematy blokowe. Instrukcje warunkowe.
róŜnych instrukcji dla trzech przedziałów wartości zmiennej sprawdzanej w wyraŜeniu logicznym.
Przykład zagnieŜdŜania instrukcji if..then..:
program p4_2a ;
var x, y : real ;
begin
readln (x) ;
if x >0 then y := 5
else if x<0 then y := 6
else y := 7 ;
readln
end .
Po wykonaniu powyŜszej instrukcji if..then.. odbędą się przypisania:
y → 5 dla x > 0
y → 6 dla x < 0
y → 7 dla x = 0
W przypadku zagnieŜdŜania instrukcji if..then.. sytuacja czasem się komplikuje,
jak w poniŜszym przykładzie:
program p4_2b ;
var x : real ;
begin
readln(x) ;
if x>=0 then
if x=<100 then writeln('Liczba jest w przedziale 0 do 100')
else writeln('Poza przedziałem')
else writeln('Poza przedziałem') ;
end.
Oczywiście prościej moŜna zapisać powyŜszą instrukcję w postaci:
if (x>=0) and (x<=100) then writeln('Liczba jest w przedziale 0 do 100')
else writeln('Poza przedziałem') .
4.3.2 Instrukcja wyboru – case..of..
Instrukcja case umoŜliwia alternatywne wykonanie wielu instrukcji w zaleŜności od wartości wyraŜenia typu porządkowego. Postać instrukcji:
4. Schematy blokowe. Instrukcje warunkowe.
case w
s1
s2
....
[ else
end ;
23
of
:Instrukcja_1 ;
:Instrukcja_2 ;
Instrukcja_k ]
w - wyraŜenie–selektor typu porządkowego (np. całkowitego, znakowego),
s - stałe wyboru (etykiety wyboru) w moŜliwej postaci:
s
- pojedyncza wartość,
s1, s2, sn - lista wartości,
s1..s2
- zakres wartości (okrojenie),
połączenie listy i zakresów, np. s1..s2, s3 , s4.
Działanie instrukcji polega na obliczeniu wartości wyraŜenia w i w zaleŜności
od wyniku wykonywana jest instrukcja odpowiadająca wartości (wartościom, zakresowi) stałej wyboru.
W listach wyboru moŜna powtarzać te same wartości, jeśli aktualna wartość
stałej wyboru naleŜy do listy to wykonywana jest właściwa instrukcja i dalsza
analiza jest ignorowana. Instrukcja występująca po słowie kluczowym else wykonywana jest dla wartości nie występujących wcześniej.
Przykład:
program p4_3 ;
var
miesiac
: 1..12 ;
dni
: 1..31 ;
begin
write ('Podaj numer miesiąca:') ;
readln(miesiac) ;
case miesiac of
2:
dni := 28 ; {pojedyncza wartość}
4, 6 , 9, 11:
dni := 30 ; {lista}
1..12:
dni := 31 ; {zakres} {lub else dni := 31}
end ;
writeln ('Miesiac':8, miesiac:4, 'ma':3, dni:4, 'dni':4) ;
case dni mod 2 of
0: writeln ('Liczba dni jest parzysta') ;
1: writeln ('Liczba dni jest nieparzysta')
end ;
readln
end .
24
4. Schematy blokowe. Instrukcje warunkowe.
4.4. Instrukcja złoŜona (sekwencji)
Przy konieczności wykonania więcej niŜ jednej instrukcji wewnątrz dowolnej
instrukcji strukturalnej stosujemy tzw. instrukcję złoŜoną (sekwencji):
begin
ciąg instrukcji
end
Przykład:
if x >= 0 then
begin
y := y+5 ;
writeln(y:10:3)
end
else writeln('x jest ujemne') ;
W powyŜszym przykładzie obie instrukcje pomiędzy słowami kluczowymi begin i end zostaną wykonane jeŜeli zajdzie warunek x>=0, w przeciwnym przypadku zostanie wykonana instrukcja wyprowadzająca komunikat, Ŝe x jest ujemne.
W celu uzyskania przejrzystości programów w instrukcji złoŜonej i innych instrukcjach strukturalnych wykonujemy odpowiednie wcięcia wierszy tekstu programu źródłowego.
5. Instrukcje iteracyjne
25
5. Instrukcje iteracyjne
5.1. Zasada iteracji
Instrukcje iteracyjne (zwane popularnie „pętlami”) słuŜą do wielokrotnego
wykonywania jednej lub wielu instrukcji. W języku Turbo Pascal wyróŜniamy
trzy typy instrukcji iteracyjnych: for..do.., repeat..until.. i while..do..
5.2. Instrukcja for.. do.. (dla.. wykonuj..)
Wersja z to
Wersja z downto
Z:= W1
Z:= W1
TAK
TAK
Z> W2
NIE
Z< W2
NIE
Instrukcja
Z:= następne Z
Instrukcja
Z:= poprzednie Z
Rys. 5.1 Schemat blokowy działania instrukcji for..do..
Postać instrukcji for..do.. jest następująca:
26
5. Instrukcje iteracyjne
 to 
 W2 do Instrukcja ;
downto 
for Z := W1 
gdzie:
Z
– zmienna sterująca, typu porządkowego (całkowitego, znakowego, wyliczeniowego),
W1 i W2 – wyraŜenia tego samego typu.
Wartość zmiennej sterującej zmienia się od W1 do W2 narastająco (to) lub malejąco (downto), z krokiem 1 w przypadku zmiennej całkowitej lub co znak
w przypadku zmiennej typu char.
Np. x := 0 ; i1:=1 ; i2:=3 ;
for i := i1 to i2 do
x := x+5 ;
{po wykonanej iteracji x przyjmie wartość 15}
Instrukcja for..do.. jest stosowana gdy z góry znana jest liczba powtórzeń. Wewnątrz iteracji nie wolno zmieniać wartości zmiennej sterującej lecz wolno
(i często się to robi) wykorzystywać zmienną sterującą w wyraŜeniach.
Instrukcją wykonawczą iteracji moŜe być dowolna instrukcja, takŜe inna instrukcja for..do.. (zagnieŜdŜanie iteracji) lub instrukcja złoŜona. Wewnętrzna iteracja moŜe oczywiście zawierać ograniczenia licznika, będące wyraŜeniami związanymi z licznikiem pętli zewnętrznej.
Przykład:
program p5_1 ;
var
i, j : integer ;
begin
for i := 1 to 10 do
begin
for j := i+2 to 3*i do write('∗') ;
writeln
end
end .
Zmienna sterująca i przyjmuje wartość 1 i wykonywane są instrukcje wewnętrzne (w tym wewnętrzne for..do..), następnie wartość i zwiększana jest o 1 i
ponownie są wykonywane instrukcje wewnętrzne.
Drugi przykład ilustruje uŜycie zmiennej sterującej w wyraŜeniach:
program p5_2 ;
5. Instrukcje iteracyjne
var
i
z
27
: integer ;
: real ;
begin
z := 2 ;
for i := 1 to 3 do
begin
z := z + 3 * i ;
writeln (z :5*i :2)
end
end .
Efektem programu będzie wyprowadzenie wartości:
5.00
(na 5-ciu pozycjach)
11.00
(na 10-ciu pozycjach)
20.00 (na 15-tu pozycjach)
5.3. Instrukcja repeat..until.. (powtarzaj .. aŜ..)
Postać ogólna instrukcji:
repeat
„powtarzaj”
ciąg instrukcji
until WB ;
„aŜ”
Ciąg instrukcji wewnętrznych w instrukcji repeat..until.. jest powtarzany dopóty, dopóki wyraŜenie logiczne WB posiada wartość false, zmiana na true powoduje zakończenie pętli. Sprawdzanie warunku odbywa się kaŜdorazowo po wykonaniu ciągu instrukcji, stąd iteracja ma zawsze co najmniej jeden przebieg.
Jedna z instrukcji powinna mieć wpływ na wartość wyraŜenia logicznego,
w przeciwnym przypadku iteracja nigdy się nie skończy. Jeśli błędny warunek
spowoduje nieskończoną pętlę moŜemy przerwać wykonywanie programu kombinacją klawiszy CTRL+Break.
Rysunek 5.2 przedstawia schemat blokowy działania iteracji repeat.. until.. .
28
5. Instrukcje iteracyjne
ciąg instrukcji
WB
TAK
NIE
Rys.5.2 Schemat blokowy instrukcji repeat.. until..
Przykład:
program p5_3 ;
var x : integer ;
begin
x := 3 ;
repeat
x := x + 5 ;
writeln(x:10)
until x > 100 ;
end .
Program wydrukuje w wierszach kolejne wartości 8, 13.... 103.
Iterację repeat.. until.. uŜywa się często do sprawdzania poprawności wprowadzanych danych:
program p5_4 ;
var znak : char ;
begin
repeat
write ('Wprowadź małą literę : ') ;
readln(znak)
until (znak>='a') and (znak<='z')
{ dalsza część programu }
end.
5. Instrukcje iteracyjne
29
5.4. Instrukcja while..do.. (dopóki.. wykonuj..)
Postać ogólna instrukcji while..do..:
while WB do Instrukcja ;
"dopóki" "wykonuj"
Działanie instrukcji while..do.. polega na powtarzaniu wykonywania wewnętrznej instrukcji, dopóki wyraŜenie logiczne WB posiada wartość true. Wartość ta jest sprawdzana kaŜdorazowo przed wykonaniem instrukcji wewnętrznej. Instrukcja wewnętrzna iteracji moŜe być instrukcją złoŜoną (begin.....instrukcje... end) jeśli zamierzamy wykonać więcej instrukcji wewnątrz
iteracji.
Podobnie jak w iteracji repeat..until.. istnieje konieczność wykonania
w instrukcji (takŜe złoŜonej) takiej operacji, która wpływa na wartość wyraŜenia
logicznego, aby iteracja mogła się kiedyś skończyć.
Rysunek 5.3 przedstawia schemat blokowy działania iteracji while.. do.. .
WB
NIE
TAK
Instrukcja
Rys.5.3 Schemat blokowy instrukcji while.. do..
Przykładowo w iteracji:
while a>0 do x := 5 ;
30
5. Instrukcje iteracyjne
instrukcja przypisania albo nigdy nie będzie wykonana albo iteracja będzie nieskończona, natomiast w instrukcji:
while x>=0 do x := x – 2 ;
pomniejszanie wartości zmiennej x daje gwarancję zakończenia iteracji po osiągnięciu przez zmienną wartości ujemnej.
Jeśli błędny warunek spowoduje nieskończoną pętlę moŜemy przerwać program kombinacją klawiszy CTRL+Break.
Przykładowy program oblicza sumę liczb parzystych od 2 do 100:
program p5_5 ;
var i, suma : integer ;
begin
i := 2 ;
suma := 0 ;
while i <= 100 do
begin
suma := suma + i ;
i := i + 2 ;
end ;
writeln('Suma =', suma:5)
end .
Instrukcje iteracyjne są instrukcjami strukturalnymi (w ich skład wchodzi inna,
dowolna instrukcja), zatem mogą się dowolnie wzajemnie zagnieŜdŜać, np.:
program p5_6 ;
var k, x : integer ;
begin
k :=5 ;
repeat
x :=10 ;
while x>0 do
x := x–1 ;
k := k–1 ;
until k=0 ;
end.
6. Typ tablicowy array
31
6. Typ tablicowy - array
Typ tablicowy jest typem strukturalnym (złoŜonym) stanowiącym skończony
zbiór elementów tego samego typu, o połoŜeniu określanym przez indeksy.
Zmienna typu tablicowego odpowiada w sensie matematycznym macierzy.
Opis typu:
array[ lista typów indeksów ] of typ składowych
⇓
typ porządkowy
⇓
typ dowolny (bez plikowego)
Przykład:
var
tab1: array [ 0..50 ] of integer ; {tablica 1-wymiarowa, 51 elementów typu całkowitego}
tab2, tab3: array [1..20, 1..30] of real ; {tablice 2-wymiarowe, 600 elementów
typu rzeczywistego}
tab4: array [ boolean, zakres, dzien_tyg] of char ; {tablica 3-wymiarowa, zakres
i dzien_tyg to wcześniej opisane typy porządkowe}
Tablice posiadają wymiar zaleŜny od liczby indeksów (1, 2, 3–wymiarowe)
oraz rozmiar zaleŜny od zakresu określoności indeksu w kaŜdym wymiarze (np.
rozmiar – 10 kolumn, 15 wierszy). Wektor jest tablicą 1–wymiarową (kolumnową lub wierszową).
Zmienne tablicowe całościowe mogą być wykorzystane jedynie w operacji
przypisania (przy zgodności typów), np.:
var
tab1, tab2 : array [1..10, 1..20] of real ;
begin
{ ... wypełnienie tablicy tab2 }
tab1 := tab2 ;
{ tab1 takie jak tab2 }
{... dalsza część programu }
end .
Inne operacje wykonywane być mogą tylko na składowych - jeśli są dozwolone dla ich typu.
Odwołanie do elementu tablicy zapisuje się w postaci:
nazwa_zmiennej [ indeks1, .... ]
Do nadawania wartości poszczególnym elementom tablicy stosuje się instrukcje wprowadzania danych (read) i instrukcje przypisania. Często wykorzystuje się
instrukcje for..do.., gdy poprzez zmienną sterującą iteracji moŜemy określić
zmienność indeksu (lub indeksów dla tablic wielowymiarowych) oraz uŜyć
32
6. Typ tablicowy array
zmiennej sterującej w wyraŜeniu, którego wartość jest przypisywana elementowi
tablicy (jeśli typ elementów tablicy jest typem liczbowym).
W tablicy dwuwymiarowej trudno jest określić, który wymiar opisuje wiersze,
a który kolumny, gdyŜ wartości w pamięci operacyjnej układane są "liniowo".
Wszystko zaleŜy od "umowy programowej" i odpowiednio dobierając zmienne
sterujące zagnieŜdŜanych iteracji for..do.. moŜna wyprowadzić tablicę na ekran
wierszami lub kolumnami.
Przykład 1:
program p6_1 ;
var
tab1 : array [1..5, 1..5] of real ;
{lub
type
t55 = array [1..5, 1..5] of real ;
var
tab1 : t55 ; }
i, k : 1..5 ;
begin
tab1[2, 3] := 0.1 ; {nadanie wartości elementowi tablicy}
for i := 1 to 5 do tab1[1, i] := 0.0 ; {wypełnianie pierwszego wiersza zerami}
for i := 1 to 5 do tab1[2, i] := 2 * i ; {wypełnianie drugiego wiersza kolejnymi
liczbami parzystymi}
for i := 1 to 5 do tab1[3, i] := 2 * i – 1 ; {wypełnianie trzeciego wiersza kolejnymi liczbami nieparzystymi}
for i := 1 to 5 do tab1[i, i] := i / 2 ; {wypełnianie przekątnej głównej wartościami 0.5 1 1.5 itd.}
for i := 1 to 5 do
for k := 1 to 5 do tab1[i, k] := i+2*k ; {wypełnianie całej tablicy, zagnieŜdŜanie iteracji}
for i := 1 to 5 do
begin
for k := 1 to 5 do write (tab1[i, k]:4:0) ;
writeln
end ; {wyświetlenie na ekranie całej tablicy}
writeln ;
for k := 1 to 5 do
begin
for i := 1 to 5 do write(tab1[i ,k]:4:0) ;
writeln
end ; { wyświetlenie na ekranie całej tablicy transponowanej – zamiana
wierszy i kolumn}
readln
end .
Przykład 2:
program p6_2 ;
type dni_tyg = (po, wt, sr, cz, pi, so, ni) ;
6. Typ tablicowy array
33
wek = array[dni_tyg, boolean] of real ;
var x : wek ;
begin
{...}
x[po, true] := 10.2 ;
x[wt, false] := 34.0 ;
writeln(x[wt, false]/100:20:5) ;
if x[sr, false] > 3e2 then writeln('W środę za duŜo') ;
{...}
end .
Oczywiście zmienna typu wek jest tablicą dwuwymiarową o rozmiarach 7x2.
Przykład 3:
program p6_3 ;
type opis= (nazw, imie) ; {wyliczeniowy}
var grupa : array[1..100, opis] of string[30] ;
i : integer ;
begin
{...}
grupa[1, nazw] := 'Kowalski' ;
if grupa[i, imie] = 'Stanislaw' then
writeln(grupa[i, nazw]:30, grupa[i, imie]:20) ;
{...}
end .
Typ łańcuchowy string[N] moŜna przedstawić jako wektor znaków o deklaracji:
type lancuch = array[0..N] of char ;
W elemencie o indeksie 0 przechowywany jest znak, którego kod ASCII jest
długością łańcucha. Dla dowolnej zmiennej łańcuchowej x określić moŜemy jej
długość przez uŜycie wyraŜenia ord(x[0]) lub length(x).
34
7. Typ rekordowy - record
7. Typ rekordowy - record
7.1. Definicja typu rekordowego
Typ rekordowy jest typem strukturalnym o strukturze jednowymiarowej
i o składowych dowolnych typów zwanych polami, które posiadają swoje własne
nazwy, unikalne w ramach jednego typu rekordowego. Zmiennych tego typu
uŜywamy w przypadku konieczności utworzenia obiektu opisywanego zbiorem
danych róŜnego typu.
Opis typu:
record
lista_nazw_pól_1: typ1 ;
lista_nazw_pól_2: typ2 ;
........
end ;
Przykład:
program p7_1 ;
type
data = record
rok : 1900..2100 ;
mies : 1..12 ;
dzien : 1..31
end ;
osoba = record
nazw
: string[20] ;
imie1, imie2 : string[15] ;
data_ur
: data ; {typ rekordowy wcześniej
zdefiniowany}
mezczyzna : boolean ;
rodzenstwo : array[1..5] of string[15]
end ;
var student : osoba ;
begin
{....instrukcje...}
end .
Pola rekordu mogą być tego samego lub róŜnego typu, takŜe rekordowego, tablicowego itp. Do pól rekordu istnieje dostęp bezpośredni, odwołanie do pola
zmiennej odbywa się przez nazwę zmiennej rekordowej i nazwę pola (tzw. dostęp
kwalifikowany), oddzielonych kropką:
7. Typ rekordowy - record
35
nazwa_zmiennej . nazwa_pola {. ewentualna_nazwa_pola_składowego ...}
Przykład:
student . nazw := 'Kowalski' ;
if student .data_ur.rok<1975 then ...{pole data_ur jest typu rekordowego}
UWAGI:
• w jednym typie rekordowym wszystkie pola muszą mieć róŜne nazwy,
• dopuszczalne jest całościowe przypisanie jednej zmiennej rekordowej wartości innej zmiennej rekordowej pod warunkiem, Ŝe są tego samego typu,
• na zmiennych składowych moŜna dokonywać operacji dopuszczalnych dla
ich typu.
Tworzenie wielu zmiennych rekordowych dla zapamiętywania danych strukturalnych w trakcie przebiegu programu jest niewygodne, dlatego teŜ często dane
tego typu gromadzi się w tablicy (najczęściej jednowymiarowej).
JeŜeli rekordy znajdują się w tablicy, np.:
type osoba : record
nazwisko
: string ;
imie
: string ;
wiek
: 0..100
end ;
var grupa : array [1..30] of osoba ;
to dostęp do pola pojedynczego rekordu, będącego elementem tej tablicy moŜe się
odbyć w przykładowej postaci:
writeln (grupa[5].nazwisko) {wczytanie tekstu do pola nazwisko w 5-tym
elemencie tablicy}
lub
grupa[5].nazwisko= 'Kowalski' ; {przypisanie}
Przykład:
program p7_2 ;
type osoba= record
nazwisko, imie : string[20] ;
data_ur : record
dzien, miesiac, rok : integer ;
end ;
l_dzieci :
0..15 ;
end ;
var grupa : array[1..30] of osoba ;
var i
: 1..30 ;
begin
for i :=1 to 30 do
begin
36
7. Typ rekordowy - record
writeln ('Podaj dane ', i , '-ego studenta :') ;
write ('Nazwisko:') ;
readln (grupa[i].nazwisko) ;
write ('Rok urodzenia:') ;
readln (grupa[i]. data_ur.rok) ;
{....itd. wypełnienie tablicy}
end ;
{wypisanie liczby dzieci dla osób urodzonych przed 1975 rokiem}
for i :=1 to 30 do
if grupa[ i]. data_ur. rok<1975 then
writeln(grupa[i].nazwisko:30,grupa[i]. l_dzieci:4) ;
end .
7.2. Instrukcja wiąŜąca - with.. do..
Instrukcja with upraszcza zapis dostępu do pól rekordu. Jej ogólna postać to:
with lista_zmiennych_rekordowych do Istrukcja ;
W instrukcji wewnętrznej (takŜe złoŜonej) moŜe nastąpić odwołanie bezpośrednio do nazw pól rekordów wymienionych w liście zmiennych, bez wyspecyfikowanych nazw zmiennych całościowych z listy.
Przykład 1:
program p7_3 ;
var zespolona : record
rzecz, uroj : real
end ;
begin
with zespolona do
begin
rzecz := 2.5 ;
uroj := 1.0
end ;
{... dalsza część programu}
end .
Przykład 2:
program p7_4 ;
type osoba = record
nr
nazw
end ;
var j
: 1..10 ;
: integer ;
: string[30] ;
7. Typ rekordowy - record
student : osoba ;
grupa
: array[1..10] of osoba ;
begin
writeln(' Wczytanie danych do tablicy') ;
for j := 1 to 10 do
with student do
begin
write('Podaj numer:') ;
readln(nr) ;
write('Podaj nazwisko:') ;
readln(nazw) ;
grupa[ j ] := student
end ;
{...dalsza część programu..}
end .
37
38
8. Sortowanie
8. Sortowanie
8.1. Prosty algorytm sortowania
Algorytm polega na porównywaniu pierwszego elementu z kolejnymi, w następnym przebiegu iteracji drugiego elementu z kolejnymi itd., aŜ do porównania
dwóch ostatnich elementów. W przypadku niewłaściwej kolejności następuje
zamiana elementów miejscami. Dla przykładowego ciągu liczb, podlegającego
sortowaniu (12, 5, 11, 4, 7, 2) kolejne analizy przebiegają następująco:
1 przebieg
12
5
5
12
5
12
4
12
4
12
2
12
2 przebieg
2
12
2
11
2
5
2
5
2
4
11
11
11
11
11
11
4
4
4
5
5
5
7
7
7
7
7
7
2
2
2
2
2
4
11
12
12
12
12
5
5
11
11
11
7
7
7
7
7
4
4
4
4
5
zamiana 4
zamiana 5
3 przebieg
2
4
2
4
2
4
2
4
12
11
7
5
11
12
12
12
7
7
11
11
5
5
5
7
zamiana 7
zamiana 8
zamiana 9
4 przebieg
2
4
2
4
2
4
5
5
5
12
11
7
11
12
12
7
7
11
zamiana 10
zamiana 11
5 przebieg
2
4
2
4
5
5
7
7
12
11
11
12
zamiana 12
Liczba analiz:
n
(n − 1), gdzie n - liczba elementów.
2
zamiana 1
zamiana 2
zamiana 3
zamiana 6
8. Sortowanie
39
8.2. Sortowanie bąbelkowe
Algorytm polega na n-krotnym (gdzie n jest liczbą elementów zbioru) porównywaniu kolejnych par elementów sąsiadujących i zamianie miejscami w przypadku niewłaściwej kolejności:
1 przebieg
12
5
5
12
5
11
5
11
5
11
5
11
2 przebieg
5
11
5
11
5
4
5
4
5
4
5
4
3 przebieg
5
4
4
5
4
5
4
5
4
5
4
5
4 przebieg
4
5
4
5
4
2
4
2
4
2
4
2
5 przebieg
4
2
2
4
2
4
2
4
2
4
11
11
12
4
4
4
4
4
4
12
7
7
7
7
7
7
12
2
2
zamiana 1
2
zamiana 2
2
zamiana 3
2
zamiana 4
2
zamiana 5
12 efekt ostatniej zamiany
4
4
11
7
7
7
7
7
7
11
2
2
2
2
2
2
11
11
12
12
12
12
12
12
7
7
7
2
2
2
2
2
2
7
7
7
11
11
11
11
11
11
12
12
12
12
12
12
2
2
5
5
5
5
7
7
7
7
7
7
11
11
11
11
11
11
12
12
12
12
12
12
5
5
5
5
5
7
7
7
7
7
11
11
11
11
11
12
12
12
12
12
zmiana 6
zmiana 7
zmiana 8
zamiana 9
zamiana 10
zamiana 11
zmiana 12
40
8. Sortowanie
2
4
6 przebieg
2
4
2
4
2
4
2
4
2
4
5
7
11
12
5
5
5
5
5
7
7
7
7
7
11
11
11
11
11
12
12
12
12
12
8.3. Sortowanie bąbelkowe skrócone
Algorytm polega na (n–1)-krotnym porównywaniu kolejnych par elementów
sąsiadujących, z tym, Ŝe w kaŜdym kolejnym przebiegu liczba analizowanych par
jest zmniejszana o 1:
1 przebieg
12
5
5
12
5
11
5
11
5
11
5
11
2 przebieg
5
11
5
11
5
4
5
4
5
4
3 przebieg
5
4
4
5
4
5
4
5
4 przebieg
4
5
4
5
4
2
5 przebieg
4
2
2
4
11
11
12
4
4
4
4
4
4
12
7
7
7
7
7
7
12
2
2
2
2
2
2
12
4
4
11
7
7
7
7
7
11
2
2
2
2
2
11
12
12
12
12
12
7
7
7
2
2
2
2
7
11
11
11
11
12
12
12
12
2
2
5
7
7
7
11
11
11
12
12
12
5
5
7
7
11
11
12
12
zamiana 1
zamiana 2
zamiana 3
zamiana 4
zamiana 5
zamiana 6
zamiana 7
zamiana 8
zamiana 9
zamiana 10
zamiana 11
zamiana 12
9. Podprogramy - funkcje
41
9. Podprogramy - funkcje
Stosowanie procedur i funkcji (podprogramów) umoŜliwia rozbicie złoŜonego ciągu operacji na mniejsze struktury. Zwiększa to czytelność programu,
poprawia kontrolę nad rozbudowanym programem i umoŜliwia wielokrotne
wykorzystanie bloków instrukcji ze zmienionymi danymi wejściowymi. Podprogramy mogą mieć strukturę hierarchiczną, a zatem kolejna procedura lub
funkcja moŜe być definiowana wewnątrz innej.
Podstawowym zadaniem funkcji jest obliczenie i zwrot do miejsca wywołania (przez nazwę funkcji) pojedynczej wartości zaś procedura wykonuje sekwencję działań i moŜe wyprowadzać wiele obliczonych wartości.
Definicja procedury lub/i funkcji umieszczana jest w części deklaracyjnej
programu głównego (takŜe innej procedury lub funkcji), jej struktura jest podobna do struktury programu głównego:
function nazwa (lista parametrów formalnych): typ funkcji ;
definicje, deklaracje
begin
....
nazwa := wyraŜenie ;
end ;
W nagłówku definicji funkcji muszą się znaleźć identyfikatory parametrów
słuŜących do przekazania danych do wnętrza funkcji z określeniem ich typów
(elementy listy oddzielane są średnikami) oraz typ funkcji (prosty). Parametry
te zwane są formalnymi.
Funkcja zapewnia w zasadzie zwrot pojedynczej wartości poprzez jej nazwę
(obiekt określonego typu prostego), chociaŜ moŜna równieŜ stosować przekazanie przez zmienną (jak w procedurze - patrz następne ćwiczenie). W sekcji
wykonawczej funkcji musi zatem znaleźć się instrukcja nadająca wartości funkcji (np. instrukcja przypisania dla nazwy funkcji).
Przykładowe nagłówki definicji funkcji:
function suma (x1, x2: real): real ;
function sprawdzaj (x1, x2: real ; y1, y2: integer): boolean ;
Wykonanie (wywołanie) funkcji odbyć się moŜe:
• w wyraŜeniu odpowiedniego typu (funkcje typów liczbowych w wyraŜeniach arytmetycznych, funkcje logiczne w wyraŜeniach logicznych),
• w procedurze wyprowadzenia write(writeln),
42
9. Podprogramy - funkcje
• jako parametr innej funkcji lub procedury (w tym standardowej) z zachowaniem zgodności typu.
Parametry wywołania (wykonania) funkcji, zwane parametrami aktualnymi lub argumentami, mogą być stałymi, zmiennymi lub wyraŜeniami,
oddzielane są przecinkami. Liczba, typ i kolejność parametrów aktualnych
musi być zgodna z parametrami formalnymi w deklaracji funkcji.
Przykładowy program ilustruje moŜliwe sposoby wywołania funkcji:
program p9_1 ;
var a, b,c : real ;
function iloczyn (x1, x2: real): real ; {definicja funkcji}
begin
iloczyn := x1*x2 ; {nadanie wartości funkcji}
end ; {koniec definicji funkcji}
begin {program główny}
a := 3.4 ;
b := 5.6 ;
writeln (iloczyn(a, b)) ; {uŜycie funkcji jako parametru instrukcji writeln}
c := 3 ∗ iloczyn (a, b) ;
writeln (c:10:5) ;
c := 2 ∗ iloczyn (b, 1– a)/ iloczyn (a, 2*b +1) ; {uŜycie funkcji w wyraŜeniu}
writeln(c:10:5) ;
c := 1/iloczyn (c–1, a) ;
writeln(c:10:5) ;
if iloczyn(a*a, b-3) > 0 then writeln('dodatni');
readln;
end .
Wywołanie (wykonanie) funkcji w programie dokonywane jest zatem tak
jak uŜycie zmiennej (podobnie jak funkcje standardowe). Wartości parametrów
aktualnych (lub obliczonych wyraŜeń) przekazywane są do funkcji (kopiowane
na parametry formalne), następnie wykonywane są instrukcje funkcji i wartość
obliczona zwracana jest pod identyfikatorem (nazwą) funkcji do miejsca wywołania.
Wykonanie funkcji moŜe być teŜ osobną instrukcją, jeśli zwrot wartości
funkcji nie jest potrzebny, a instrukcje funkcji wykonują teŜ inne, niezbędne
działania, na przykład wyświetla na ekranie pewne informacje.
PoniŜszy program tabelaryzuje wartości funkcji opisanej przedziałami,
w 21 punktach zakresu (0.0, 2.0):
program p9_2 ;
var i : 0..20 ;
9. Podprogramy - funkcje
function fun(x: real): real ; {definicja funkcji}
var xkw : real ;
begin
xkw := x∗x ;
if x <= 0.5 then fun := 0.2∗xkw-x+0.1
else fun := xkw/(xkw–0.1)
end ;
{koniec definicji funkcji}
begin
{początek programu głównego}
writeln ;
writeln ('Tabela wartości funkcji':45) ;
writeln ;
writeln ('x':30, 'f(x)':20) ;
for i := 0 to 20 do
begin
writeln(i:12, i∗0.1:20:3, fun(i∗0.1):20:5)
end ;
readln;
end .
43
44
10. Podprogramy - procedury
10. Podprogramy - procedury
Procedury mogą wykonać sekwencję działań na wartościach wprowadzonych do jej wnętrza i wyprowadzać wiele obliczonych wartości.
Definicja procedury, podobnie jak definicja funkcji umieszczana jest w części deklaracyjnej programu głównego (takŜe innej procedury lub funkcji):
procedure nazwa (parametry formalne) ;
definicje, deklaracje
begin
....
instrukcje
....
end ;
Parametry formalne słuŜą do przekazywania danych pomiędzy sekcją,
w której wykonywana jest procedura, a samą procedurą. Niektóre z nich przekazują dane wejściowe do funkcji lub procedury, inne mogą zwrócić wyliczone
w podprogramie wartości do programu głównego lub nadrzędnego podprogramu. Deklaracje parametrów formalnych są oddzielane średnikami, kaŜda
deklaracja składa się z listy zmiennych i nazwy typu.
Przykładowe nagłówki deklaracji procedury:
procedure drukuj (x1, x2: real) ;
procedure suma (liczba1, liczba2: real ; var wynik: real) ;
Poprzedzające zmienną (lub listę zmiennych) słowo kluczowe var określa
przekazanie danych przez zmienną, jego brak przekazanie danych przez wartość.
Wykonanie procedury jest odrębną instrukcją. Parametry aktualne odpowiadające pozycji wywołania przez wartość mogą być stałymi, zmiennymi lub
wyraŜeniami, natomiast parametry aktualne, odpowiadające przekazaniu przez
zmienną, muszą być identyfikatorami (nazwami) zmiennych.
Przykładowe instrukcje wykonania powyŜszych procedur:
drukuj (5, 2*y);
suma (7.8, 8.0, rez);
Przekazanie przez wartość stosuje się w celu wniesienia danych wejściowych
do podprogramu, natomiast przekazanie przez zmienną ma na celu zwrot wyników działania procedury do miejsca wywołania. Przekazanie przez wartość
traktowane jest jako nadanie wartości początkowej zmiennej lokalnej, istnieją-
10. Podprogramy - procedury
45
cej tylko w trakcie wykonywania podprogramu, a usuwanych z pamięci w momencie jego zakończenia.
Przekazanie przez zmienną moŜe przenieść wartość do procedury (wejście),
po jej zakończeniu moŜe (lecz nie musi) spowodować zwrot nowej wartości do
programu wywołującego procedurę. Przekazanie przez zmienną daje teŜ oszczędności pamięci, np. duŜe tablice przekazuje się do podprogramów zwykle
przez zmienną.
PoniŜej prosty przykład uŜycia procedury sumującej dwie liczby rzeczywiste:
program p10_1 ;
var a, b, c : real ;
{definicja procedury}
procedure suma (liczba1, liczba2 : real ; var wynik : real) ;
begin
wynik := liczba1 + liczba2 ;
end ; {koniec definicji procedury}
begin {początek programu głównego}
a := 2 ;
b := 2 ;
{przykładowe wykonania procedury}
suma (6.7, 2*a, c) ; {trzeci parametr aktualny musi być zmienną}
writeln(c:10:3) ; {c jest równe 6.7+2*2=10.7}
suma (a, b, c) ;
writeln(c:10:3) ; {c jest równe 2+2=4}
suma (c, c, c) ;
writeln(c:10:3) ; {c jest równe 4+4=8}
suma (c, b, a) ;
writeln(a:10:3) ; {a jest równe 8+2=10}
readln;
end .
Zasięg deklaracji zmiennych
Deklaracje obiektów w programie głównym zwane są globalnymi, "widoczne" są w całym programie, takŜe i w podprogramach (czasami mogą być tam
"przesłonięte" czyli ponownie deklarowane). Deklaracje obiektów w definicji
podprogramu to deklaracje lokalne dla podprogramu, nie będą "widoczne"
w programie wywołującym. Jeśli w ciele definicji podprogramu jest definicja
zagnieŜdŜonego podprogramu to obiekty lokalne stają się dla niego zewnętrznymi.
Zasięg deklaracji ilustruje rys.10.1.
46
10. Podprogramy - procedury
program A
deklaracje A
procedure B
deklaracje B
procedure C
deklaracje C
begin
deklaracje globalne – zmienne
„widoczne” w całym programie
(chyba Ŝe „przesłonięte” w B, C
lub D)
deklaracje lokalne w B (zewnętrzne dla C)
deklaracje lokalne w C (zmienne
z deklaracji A i B moŜna „przesłaniać”)
end
begin
tu moŜna wykorzystać
procedurę C
end
procedure D
deklaracje D
begin
end
begin
deklaracje lokalne w D (zmienne
z deklaracji A moŜna
„przesłaniać”, procedura C
„niewidoczna”)
sekcja główna programu, tu moŜna wywołać procedury B i D, nie
moŜna procedury C
end .
Rys 10.1. Zasięg deklaracji w Turbo Pascalu.
11. Pliki
47
11. Pliki
11.1. Typ plikowy
Plik w pojęciu Turbo Pascala jest ciągiem elementów tego samego typu, odwzorowującym zbiór danych gromadzonych w pliku fizycznym, umieszczonym
w pamięci zewnętrznej. Dostęp do pliku jest sekwencyjny, tzn. po jego otwarciu
dostępny jest pierwszy zapisany w nim element, zaś inne elementy mogą być
udostępniane tylko po wykonaniu pewnych operacji (czytanie kolejnych elementów, przesunięcie pozycji czytania itp.).
Aby uzyskać dostęp do pliku fizycznego naleŜy zadeklarować w programie
zmienną lub zmienne typu plikowego, które trzeba skojarzyć z plikami dyskowymi. Zmienne te moŜna kojarzyć kolejno z róŜnymi plikami.
Plik moŜe mieć dowolny typ składowych (oprócz typu plikowego).
Definicja typu plikowego ma jedną z postaci:
type nazwa = file of typ ; plik elementowy (zdefiniowany)
type nazwa = file ;
plik blokowy (niezdefiniowany)
type nazwa = text ;
plik tekstowy (typ predefiniowany)
Przykład uŜycia pliku elementowego:
type
osoba = record
nazw : string [30] ;
imie
: string [30]
end ;
grupa = file of osoba ; {typ plikowy}
var
student
: osoba ;
gr1, gr2, gr3 : grupa ; {zmienne typu plikowego}
begin
{...operacje na pliku...}
end .
Dla całościowych zmiennych plikowych dopuszczalne są jedynie niektóre
operacje systemu plików, natomiast na składowych, po ich przeczytaniu i przypisaniu zmiennym odpowiedniego typu, moŜemy wykonywać operacje w zaleŜności od tego typu.
W pliku elementowym zapis dokonuje się w postaci binarnej, a w tekstowym
nawet elementy liczbowe zapisywane są jako tekst ASCII.
Obsługa plików wymaga następujących operacji:
48
11. Pliki
• opisu zmiennej plikowej w części deklaracyjnej,
• skojarzenia zmiennej plikowej z plikiem fizycznym,
• otwarcia pliku (do zapisu lub do odczytu),
• wykonania niezbędnych operacji (czytanie, zapis i inne),
• zamknięcia pliku.
11.2. Operacje plikowe
W poniŜszej tabeli przedstawiono podstawowe operacje plikowe z uŜyciem
standardowych procedur i funkcji plikowych, w których uŜyto określeń:
f - nazwa zmiennej typu plikowego,
Wt - wyraŜenie tekstowe,
W - wyraŜenie odpowiedniego typu,
Z - nazwa zmiennej.
Tabela 11.1 Podstawowe operacje plikowe
Operacja
Skojarzenie zmiennej plikowej z plikiem fizycznym
Otwarcie do odczytu i zapisu (istniejący plik)
Otwarcie do zapisu
(nowy plik lub istniejący lecz zapisywany od nowa)
Otwarcie do dopisania (na końcu
pliku tekstowego)
Zamknięcie pliku
Detekcja końca
pliku
Odczyt
Zapis
Zapis (tylko plik
typu tekstowego!)
Typ
Zapis
Przykłady
procedura assign (f , Wt)
assign(p1,'C:\DANE\gr1.dan')
;
assign(p2,'C:\DANE\gr2.ele') ;
procedura reset (f)
reset (p1) ;
procedura rewrite (f)
rewrite (p2) ;
procedura append (f)
append (p2) ;
procedura
funkcja
logiczna
procedura
procedura
close (p2) ;
if eof (p1) then .... ;
while not eof(p1) do ....;
read (p1, student);
write (p2, student);
close (f)
eof (f)
read (f, Z1,..,Zn)
write(f, W)
procedura writeln(f, W)
writeln (p1, student);
UWAGI:
• po otwarciu do odczytu wskaźnik czytania ustawia się na początku pliku,
• po przeczytaniu elementu następuje przesunięcie wskaźnika odczytu do
następnego elementu, aby przeczytać dowolny element wewnątrz pliku naleŜy uprzednio przeczytać elementy poprzedzające,
11. Pliki
•
•
•
•
•
•
•
49
otwarcie nowego pliku procedurą rewrite powoduje utworzenie pustego
pliku, jeśli plik istnieje zostanie wyzerowany,
gdy eof(f) = true - wskaźnik odczytu (zapisu) znajduje się na końcu pliku,
gdy po wykonaniu procedury reset okaŜe się Ŝe eof(file) = true to plik jest
pusty,
instrukcja writeln istnieje tylko dla pliku typu tekstowego,
zapis dopuszczalny jest tylko na końcu pliku (niemoŜliwy zapis „w środku” pliku),
kaŜdy zapis przesuwa wskaźnik o jedną pozycję,
dopisanie „w środku” pliku wykonuje się przez etapowe przepisywanie do
innego pliku.
PoniŜszy program zawiera modyfikację przykładu p9.2 z uŜyciem procedury
oraz zapisem tabeli obliczanych wartości do pliku tekstowego:
program p11_1 ;
uses crt ;
var i
: 0..20 ;
y
: real ;
w
: char ;
plik : text ;
procedure oblicz (x: real ; var f: real ; var wsk: char) ;
{definicja procedury}
var xkw : real ;
begin
xkw := x∗x ;
if x <= 0.5 then f := 0.2∗xkw–x+0.1
else f := xkw/(xkw–0.1) ;
if f < 0 then wsk := '−' else wsk := '+'
end ;
begin
{ początek sekcji wykonawczej}
assign(plik, 'c:\tp\moje\fun.txt') ; { skojarzenie pliku }
rewrite(plik) ;
{ otwarcie pliku do zapisu }
clrscr ;
writeln('Tabela wartości funkcji':45) ;
writeln('x':30, 'f(x)': 20) ;
for i := 0 to 20 do
begin
oblicz(i∗0.1, y, w) ;
{wywołanie procedury}
writeln(i:12, i∗0.1:20:3, y:20:5, w:3) ;
writeln(plik, i:12, i∗0.1:20:3, y:20:5) ;{zapis do pliku}
end ;
close(plik) ;
{zamknięcie pliku}
50
11. Pliki
repeat until keypressed
end .
PoniŜszy przykład ilustruje wykorzystanie bardziej złoŜonych struktur i algorytmów. Jest to ilustracja uŜycia typu rekordowego wraz z zapisem/odczytem
danych do/z pliku. Program wczytuje wprowadzane dane i zapisuje do tablicy
rekordów, a następnie wyświetla listę danych posortowaną według zadanego
pola.
program p11_2 ;
type
tosoba = record { rekord zawierający dane osobowe }
imie
: string[ 20 ] ;
nazwisko
: string[ 15 ] ;
adres
: string[ 40 ] ;
wiek
: integer ;
plec
: (k,m) ;
end ;
const
maxosob = 30 ; { maksymalny rozmiar tablicy z danymi osobowymi }
var
lista_osob
: array [ 1..maxosob ] of tosoba ;
ilosc_osob
: integer ;
nastepna
: boolean ;
znak
: char ;
i, n
: integer ;
zamienic
: boolean ;
pom
: tosoba ; {zmienna pomocnicza do sortowania
tablicy }
f
: file of tosoba ;
nazwa
: string ;
begin {początek programu}
repeat
writeln('0 - wprowadzanie danych') ;
writeln('1 - odczyt danych z dysku') ;
write('Twój wybór [ 0/1 ]:') ;
readln(znak) ;
until (znak = '0') or (znak = '1') ;
if znak = '0' then
begin { wprowadzanie danych}
nastepna := true ;
ilosc_osob := 0 ;
while nastepna and (ilosc_osob <= maxosob) do
begin
inc(ilosc_osob) ; {procedura zwiększająca ilosc_osob o 1}
with lista_osob[ ilosc_osob ] do
11. Pliki
51
begin
write('Imię:':12) ; readln(imie) ;
write('Nazwisko:':12) ; readln(nazwisko) ;
write('Adres: ':12) ; readln(adres) ;
write('Wiek:
':12) ; readln(wiek) ;
write('Płeć [ k/m ]:':12) ;
repeat
readln(znak) ;
znak := upcase(znak) ; {funkcja upcase zamienia
literę małą na duŜą}
until (znak = 'K') or (znak = 'M') ;
case znak of
'K': plec := k
else plec := m
end ;
end ; {koniec with}
if ilosc_osob < maxosob then
begin
writeln ;
writeln('Wprowadziłeś do tej pory ', ilosc_osob,' osób') ;
write('Czy chcesz podać następną osobę? [ t/n]') ;
repeat
readln(znak) ;
znak := upcase(znak) ;
until (znak = 'T') or (znak = 'N') ;
nastepna := znak = 'T' ;
end ;
end ; {koniec while}
writeln ;
write('Zapisać wprowadzone osoby na dysku [ t/n ]?') ;
repeat
readln(znak) ;
znak := upcase(znak) ;
until (znak = 'T') or (znak = 'N') ;
if znak = 'T' then
begin{ zapis listy na dysk }
write('Podaj ścieŜkę i nazwę pliku:') ;
readln(nazwa) ;
if nazwa <> '' {dwa apostrofy - pusty łańcuch} then
begin
assign(f , nazwa) ;
rewrite(f) ;
for i := 1 to ilosc_osob do write(f, lista_osob[ i ]) ;
close(f) ;
end ;
52
11. Pliki
end ;
end { koniec wprowadzania danych }
else { odczyt z dysku }
begin
ilosc_osob := 0;
repeat
write('Podaj ścieŜkę i nazwę pliku:') ;
readln(nazwa) ;
until nazwa < > '' ; {dwa apostrofy}
assign(f, nazwa) ; {przypisanie zmiennej plikowej do pliku
dyskowego}
reset(f) ;
{otwarcie pliku do odczytu}
while not eof(f) and (ilosc_osob < maxosob) do
begin
inc(ilosc_osob) ; {powiększenie ilosc_osob o 1}
read(f, lista_osob [ilosc_osob ]) ;
end ;
close(f) ;
{zamknięcie pliku}
end ; { koniec odczytu z dysku }
{sortowanie i wyświetlanie listy }
repeat {pętla róŜnego sposobu sortowania}
{wybór sposobu sortowania }
writeln('Wybierz porządek sortowania:') ;
writeln('I - imię') ;
writeln('N - nazwisko') ;
writeln('W – wiek') ;
writeln('P – płeć') ;
readln(znak) ;
znak := upcase(znak) ;
case znak of
'I' :
writeln('Lista posortowana według imion') ;
'N' :
writeln('Lista posortowana według nazwisk') ;
'W' :
writeln('Lista posortowana według wieku') ;
'P' :
writeln('Lista posortowana według płci') ;
else
writeln('Lista nieposortowana') ;
end ;
{sortowanie }
for i := 2 to ilosc_osob do
begin
n := i ;
repeat
case znak of
'I' : zamienic := lista_osob[ n ].imie<
lista_osob[ n –1 ].imie ;
11. Pliki
'N' : zamienic := lista_osob[ n ].nazwisko<
lista_osob[n –1].nazwisko ;
'W' : zamienic := lista_osob[ n ].wiek <
lista_osob[ n–1 ].wiek ;
'P' : zamienic := lista_osob[ n ].plec <
lista_osob[ n –1 ].plec ;
end ;
if zamienic then
begin
pom := lista_osob[ n ] ;
lista_osob[ n ] := lista_osob[ n –1 ] ;
lista_osob[ n -1 ] := pom ;
end ;
dec(n) ; {procedura zmniejszająca n o 1}
until (n = 1) or (not zamienic) ;
end ; {koniec sortowania}
{ wyświetlenie listy }
for i := 1 to ilosc_osob do
begin
with lista_osob[i] do
begin
write(i:2, imie:22, nazwisko:17, ' lat ', wiek :5) ;
if plec= k then writeln('Kobieta':12)
else writeln(' MęŜczyzna':12) ;
writeln('Adres: ', adres:40)
end
end ;
writeln ;
write('Wyświetlić powtórnie [ t/n ]: ') ;
readln(znak) ;
until upcase(znak) = 'N' ; {koniec pętli róŜnego sposobu sortowania}
end .
53
54
12. Algorytmy rekurencyjne
12. Algorytmy rekurencyjne
Wiele problemów obliczeniowych moŜna zdefiniować rekurencyjnie. Rekurencja oznacza takie zdefiniowanie zagadnienia, gdzie w trakcie formułowania
definicji odwołujemy się do niej samej. Przykładem definicji rekurencyjnej moŜe być zapis całkowitej, nieujemnej potęgi rzędu n liczby rzeczywistej x:
xn-1*x
dla n > 0
1
dla n = 0
(tu uŜycie definiowanej potęgi)
n
x =
Rekurencja w językach programowania jest realizowana za pomocą podprogramów wywołujących kolejno same siebie ze zmienianymi parametrami
wywołania. Aby podprogramy rekurencyjne działały poprawnie powinny zawierać warunek zakończenia rekurencji aby wywołanie wykonywane było
skończoną liczbę razy.
Rekurencja daje proste programy lecz ma takŜe wadę: kaŜde wywołanie podprogramu wymaga wykonania przez procesor dodatkowych czynności, co spowalnia działanie programu oraz powoduje odłoŜenie na stos systemowy duŜej
liczby danych.
Przykłady:
program p12_1;
{wyznaczanie całkowitej nieujemnej n-tej potęgi liczby x
metodą rekurencyjną}
function potega_n (x:real ; n:integer):real ;
{ funkcja wyznacza potęgę n dla liczby x }
begin
if n=0 then potega_n := 1
else potega_n := potega_n (x, n – 1)*x ;
{w definicji funkcji wykorzystanie tejŜe funkcji}
end ;
begin {program główny}
10
writeln('2^10=', potega_n (2,10):0:0) ; {obliczenie 2 }
end .
Kolejny przykład to wyznaczanie metodą rekurencyjną silni liczby x:
program p12_2 ;
var alfa : integer ;
function silnia_x (x: integer): longint ; {zastosowano typ longint ze
względu na duŜe wartości funkcji silnia}
begin
12. Algorytmy rekurencyjne
if x = 1 then silnia_x := 1
else silnia_x := silnia_x (x-1)*x ;
end ;
begin
write ('Podaj liczbę całkowitą : ') ;
readln(alfa) ;
writeln ('Silnia z liczby ', alfa:5, '=' , silnia_x(alfa):10) ;
readln
end .
55
56
14. Typ zbiorowy
13. Typ zbiorowy
Typ zbiorowy to zbiór potęgowy danego typu porządkowego, czyli zbiór
wszystkich podzbiorów tego typu. Zmienna tego typu moŜe zatem zawierać
zbiór pusty, jedno- lub wieloelementowy.
Definicja typu zbiorowego:
type nazwa_typu = set of typ_porządkowy ;
⇑
⇑
typ zbiorowy
typ bazowy
Liczba elementów nie moŜe przekraczać 256 – czyli typ bazowy moŜe być
tylko typem Byte, okrojonym całkowitym, znakowym (w tym okrojonym) wyliczeniowym i logicznym. Zmienna typu zbiorowego zawierać moŜe dowolny
podzbiór elementów typu bazowego, od zbioru pustego do zbioru zawierającego wszystkie elementy.
Przykłady definicji typu zbiorowego:
type
dni = set of (pon,wto,sro,czw,pia,sob,nie) ;
znaki = set of 'a'..'z' ;
miesiac = (sty,lut,mar,kwi,maj,cze,lip,sie,wrz,paz,lis,gru) ;
zbior_miesiecy = set of miesiac ;
var nazwa_miesiaca : miesiac ;
zbior_nazw : zbior_miesiecy ;
UWAGA: nazwa_miesiaca moŜe przyjąć wartość tylko jednej z nazw;
zbior_nazw moŜe przyjąć wartość dowolnego podzbioru z nazw bazowych.
Zmiennych typu zbiorowego nie wolno uŜywać w instrukcjach czytania i wyprowadzania wyników, uŜywa się ich jedynie w operacjach wykonawczych, testujących itp.
Operacje logiczne wykonywane na zbiorach to relacje (porównania):
a=b
a<>b
a <= b
a >= b
c in a
równość zbiorów, te same elementy w obu zbiorach,
róŜność zbiorów, róŜne elementy w obu zbiorach (chociaŜ niektóre
mogą się powtarzać)
zawieranie zbioru a w zbiorze b (true jeśli kaŜdy element zbioru a
jest w zbiorze b)
zawieranie zbioru b w zbiorze a (true jeśli kaŜdy element zbioru b
jest w zbiorze a)
czy element c jest w zbiorze a.
14. Typ zbiorowy
57
Wartości stałych typu zbiorowego zapisujemy w nawiasach kwadratowych
w postaciach:
[lista wartości podzbioru]
[okrojenie ze zbioru]
lub łącznie:
np. [1, 5, 7],
np. [1..3],
np. [1..3, 5, 7],
jak na przykład w programie:
program p14_1 ;
type x=(alfa, beta, gamma, delta) ; {typ wyliczeniowy}
var z : set of x ;
begin
z := [alfa, beta] ; {lista - wybór podzbioru alfa, beta}
z := [alfa..gamma] ; {okrojenie - wybór podzbioru alfa, beta, gamma}
end.
Inny przykład:
program p14_2 ;
type miesiace = set of 1..12 ;
var v, x, y, z : miesiace ;
lit
: char ;
begin
x :=[1..12] ; {cały rok}
y := [1..6] ; {pierwsze półrocze}
z := [1, 3, 5 , 7 , 8, 10, 12] ; {miesiące posiadające 31 dni}
lit := 'a' ;
if x< >y then writeln ('tak') else writeln ('nie') ;
if x< =y then writeln ('tak') else writeln ('nie') ;
if x> =y then writeln ('tak') else writeln('nie') ;
if x = y then writeln ('tak') else writeln ('nie') ;
if 1 in x then writeln ('tak') else writeln ('nie') ;
if 9 in z then writeln ('tak') else writeln ('nie') ;
if lit in ['a'..'z'] then writeln ('tak') else writeln ('nie') ;
readln
end .
{tak}
{nie}
{tak}
{nie}
{tak}
{nie}
{tak}
Operatory działań na zmiennych typu zbiorowego (znaczenie jak w teorii
mnogości):
+
–
∗
suma zbiorów
róŜnica zbiorów
iloczyn zbiorów
58
14. Typ zbiorowy
Przykład:
program p15_3 ;
type zbiorowy = set of 1..6 ;
var x , y, v : zbiorowy ;
begin
x :=[2, 3, 4] + [4, 5, 6] ;
y := [2, 3, 4] - [4, 5, 6] ;
v := [2, 3, 4] * [4, 5, 6] ;
y := v * x ;
end .
{wynik
[2,3,4,5,6] }
{wynik
[2,3] }
{wynik
[4]
(część wspólna) }
{ przeanalizować wynik}