Języki i metody programowania
2. Struktura programu w języku Pascal
Program sekwencyjny
Elementy języka
Typy danych
Definiowanie stałych i deklarowanie zmiennych
Modyfikowanie zawartości zmiennych
Standardowe wejście i wyjście
2. Struktura programu w języku Pascal
2.1. Program sekwencyjny
Działania określone w algorytmie są zapisywane za pomocą instrukcji języka programowania (np. writeln, readln). Każda instrukcja języka ma określone znaczenie i sposób użycia (np. wypisanie tekstu na ekranie writeln('To jest tekst')). Instrukcje są budowane z elementów leksykalnych, do których należą:
słowa kluczowe (słowa angielskie o określonym znaczeniu w języku programowania, np. begin, end, procedure, const, var),
identyfikatory (np. nazwy zmiennych),
liczby (np. całkowite, rzeczywiste),
napisy (np. 'To jest napis'),
komentarze (np. { to jest komentarz } ),
separatory (np. średnik, kropka, dwukropek, spacja).
Elementy leksykalne są budowane ze zbioru symboli podstawowych języka Pascal, na który składają się: litery, cyfry, znaki specjalne.
Program w języku Pascal składa się z:
części deklaracyjnej (deklaracje modułów, definicje stałych, deklaracje zmiennych, procedur i funkcji),
części wykonawczej (zawiera instrukcje realizujące określony algorytm).
Program może być poprzedzony nagłówkiem, który składa się ze słowa kluczowego Program, nazwy programu i średnika.
Najprostszy program nie wykonuje żadnego zadania, a jedynie zawiera informacje o miejscu rozpoczęcia programu (begin) i miejscu jego zakończenia (end).
Przykład 2.1. Najprostszy program.
BEGIN {początek programu}
{ komentarz - najprostszy program w języku Pascal }
END. { koniec programu }
Program ten można uzupełnić o nagłówek zawierający nazwę programu.
Program M1; { nagłówek }
BEGIN
{ program z nagłówkiem }
END.
Do programu można wprowadzać dane wejściowe z urządzeń wejścia
(np. z klawiatury) lub z plików dyskowych oraz można wyprowadzać wyniki do urządzeń wyjścia (np. monitor, drukarka) lub do plików dyskowych.
W praktyce urządzenia wejścia / wyjścia są traktowane jak pliki o unikalnych nazwach, np. 'CON' - monitor (dla wyjścia), klawiatura (dla wejścia), 'LPT1' - drukarka. Do wyprowadzania danych z programu (domyślnie na ekran) służą procedury write, writeln, natomiast do wczytywania danych do programu (domyślnie z klawiatury) służą procedury read i readln.
Przykład 2.2. Wyprowadzenie napisu na ekran i zatrzymanie programu
w oczekiwaniu na Enter.
Begin {początek programu}
writeln('To jest tekst!');
readln; { czekaj na enter }
End. { koniec programu }
Przykład 2.3. Obliczanie sumy dwóch liczb całkowitych a i b.
Schemat blokowy
Podczas pisania programów należy pamiętać o tym, że na danym etapie programu można używać tylko tych elementów, które wcześniej zostały zdefiniowane lub są elementami standardowymi języka. W kolejnym przykładzie w celu wykorzystania procedury umożliwiającej czyszczenie ekranu dołączono moduł crt zawierający deklarację procedury clrscr.
Program dodawania dwóch liczb całkowitych
uses crt; { modul definiujacy procedure clrscr }
{ obliczanie sumy liczb całkowitych}
Var a, b: integer; { zmienne calkowite od -32768.. 32767 }
suma1, suma2: longint;
{ suma1,suma2 - zmienne calkowite o wiekszym }
{ zakresie od -2147483648..2147483647 }
Begin {początek programu}
clrscr; { czyszczenie ekranu }
write('Podaj liczbe calkowita a = '); readln(a);
write('Podaj liczbe calkowita b = '); readln(b);
suma1:=a+b; {obliczenie suma1 - możliwość przepełnienia }
{zakresu integer dla a = b = 20000 }
suma2:=longint(a)+b; { obliczenie suma2 }
writeln('Suma_1 liczb = ', suma1);
writeln('Suma_2 liczb = ', suma2);
readln; { czekaj na enter }
End. { koniec programu }
W niniejszym programie zadeklarowano dwie zmienne całkowite a i b typu integer oraz zmienne suma1 i suma2 typu longint. W przypadku, gdy wprowadzone zostaną wartości a=20000 oraz b=20000, które są dopuszczalne dla zmiennych typu integer, uzyskane wyniki będą następujące: suma1=a+b=-25536 (wynik błędny) oraz suma2=longint(a)+b=40000 (wynik poprawny).
W przypadku sumowania dwóch liczb typu integer wynik jest składowany w zmiennej pomocniczej, której typ jest typem składnika o większym zakresie. W rozpatrywanym przypadku wynik dodawania 40000 jest składowany w zmiennej pomocniczej typu integer, której zakres wartości należy do przedziału -32768...32767. Zmienne typu integer są pamiętane na dwóch bajtach, gdzie najstarszy bit jest bitem znaku. W zapisie szesnastkowym i binarnym pom = 40000 = 9C40 hex = 1001 1100 0100 0000 bin. Ustawiony najstarszy bit oznacza, że jest to liczba ujemna. Wartość modułu liczby wyznacza się dokonując negacji bitów i dodając jeden. Stąd, wartość zmiennej suma1 = - (0110 0011 1100 0000 bin) = - (63C0 hex) = -25536 (wynik sumowania jest błędny).
W drugim przypadku dokonano konwersji (rzutowania) typu zmiennej a do typu longint. Wynik dodawania jest składowany w zmiennej pomocniczej typu longint. Stąd, wartość zmiennej suma2 = 40000 (wynik sumowania jest poprawny).
Wniosek: podczas wykonywania operacji na zmiennych należy pamiętać, aby właściwie dobrać ich typy, tak aby nie dochodziło do przekroczenia zakresu.
Przykład 2.4. Zmienne całkowite można wyprowadzać na określonej liczbie pozycji ekranowych. W tym celu należy w procedurze writeln podać po dwukropku liczbę pozycji dla zmiennej, np. writeln('Zmienna x = ', x:5). Zmienna całkowita x zostanie wyprowadzona na 5 polach ekranowych. Puste pola zostaną wypełnione spacjami. Jeśli liczba zajmuje więcej niż 5 pól, to zostanie ona wyprowadzona w całości.
W przypadku liczb rzeczywistych można podać liczbę pozycji przeznaczonych dla zmiennej (łącznie z kropką dziesiętną i znakiem) oraz liczbę uwzględnianych cyfr po przecinku (ostatnia cyfra liczby będzie zaokrąglona na podstawie cyfry poprzedniej), np. writeln('Zmienna y = ', y:9:2). Zmienna rzeczywista y zostanie wyprowadzona na 9 polach z uwzględnieniem 2 miejsc po przecinku.
uses crt;
var x: integer; { zmienna typu całkowitego }
y: real; { zmienna typu rzeczywistego }
Begin {początek programu}
x:=200;
clrscr; { czyszczenie ekranu }
writeln(`Zmienna x = `, x:1); {200 }
writeln(`Zmienna x = `, x:2); {200 }
writeln(`Zmienna x = `, x:3); {200 }
writeln(`Zmienna x = `, x:4); { 200 }
writeln(`Zmienna x = `, x:5); { 200}
readln;
y:=1.235;
writeln(y:2:2); { 1.24 }
writeln(y:3:2); { 1.24 }
writeln(y:4:2); { 1.24 }
writeln(y:5:2); { 1.24 }
writeln(y:6:2); { 1.24 }
writeln(y:7:2); { 1.24 }
writeln(y:8:2); { 1.24}
readln;
End.
Ogólna struktura programu w języku Pascal
program nazwa_programu; {Nagłówek programu - opcjonalny}
{ SEKCJA DEKLARACJI }
uses lista_nazw_modułów ;
const sekwencja_definicji_stałych ; {Definicje stałych}
type sekwencja_definicji_typów ; {Definicje typów}
label lista_etykiet ; {Deklaracja etykiet}
var sekwencja_deklaracji_zmiennych ; {Deklaracje zmiennych}
procedure nazwa_procedury_1 ; {Definicje procedur}
begin { Definicje składowych procedury_1 - kod procedury } end;
procedure nazwa_procedury_2 ( lista_parametrów ) ;
begin { Definicje składowych procedury_2 - kod procedury } end;
. . .
function nazwa_funkcji_1 : typ_wartosci ; {Definicje funkcji}
begin
{ Definicje składowych funkcji_1 - kod funkcji }
nazwa_funkcji_1:= wynik; { przekazanie wyniku funkcji na zewnątrz }
end;
function nazwa_funkcji_2( lista_parametrów ) : typ_wartości ;
begin
{ Definicje składowych funkcji_2 - kod funkcji }
nazwa_funkcji_2:= wynik; { przekazanie wyniku funkcji na zewnątrz }
end;
. . .
{ SEKCJA INSTRUKCJI }
begin
instrukcja_1 ;
instrukcja_2 ;
. . .
instrukcja_N ;
end .
Struktura programu wykonywalnego w języku Pascal
Program wykonywalny przeznaczony dla systemu DOS rezerwuje w pamięci operacyjnej obszar przeznaczony na segment kodu programu, segment danych programu, segment stosu programu i stertę.
Segment kodu programu - fragment pamięci, w której umieszczone są instrukcje realizowane w programie (może być kilka modułów po 64 KB).
Segment danych programu - fragment pamięci, w której znajdują się zmienne globalne umieszczone w części deklaracyjnej programu; są to zmienne statyczne istniejące przez cały czas działania programu; obszar ten zajmuje 64 KB.
Segment stosu (stos) - fragment pamięci, w której przechowywane są zmienne lokalne i adresy powrotów z procedur i funkcji; obszar ten może zajmować maksymalnie 64KB.
Sterta - fragment pamięci, w której tworzone i przechowywane są zmienne dynamiczne; dla tych zmiennych pamięć może być alokowana i zwalniana na bieżąco w trakcie działania programu; obszar ten może zajmować całą dostępną pamięć do 640KB.
Uwaga: pamięć jest rezerwowana zawsze w kierunku rosnących adresów.
Model pamięci programu wykonywalnego w trybie rzeczywistym DOS
Elementy języka
Elementy leksykalne języka, tj. słowa kluczowe, identyfikatory, liczby, napisy, komentarze i separatory są budowane ze zbioru symboli języka.
Zbiór symboli języka: małe i wielkie litery, cyfry, symbole operatorów arytmetycznych (np. +, -), symbole operatorów relacji (np. <, <=, <>), symbole nawiasów, symbole znaków przestankowych (np. kropka, średnik, dwukropek) oraz symbole innych znaków mających specjalne znaczenie.
Symbole leksykalne:
słowa kluczowe: słowa w języku angielskim mające określone znaczenie w języku programowania, np. begin, end, const, type, do, else, procedure, function i inne; nie mogą być przedefiniowywane;
identyfikatory: ciąg liter, cyfr lub znaków pokreślenia, zaczynający się od litery lub podkreślenia (np. x, y_1, wynik, _a34); reprezentują nazwy elementów programu, tj. nazwy zmiennych i stałych, nazwy typów danych, nazwy procedur i funkcji, oraz inne nazwy; nie mogą zawierać znaku spacji; małe i wielkie litery nie są rozróżniane; maksymalna długość identyfikatora zależy od kompilatora, np. dla systemu Turbo Pascal wynosi ona 63 znaki;
niektóre identyfikatory mogą być standardowo zdefiniowane w danej
implementacji języka; są to wówczas słowa zastrzeżone języka reprezentujące nazwy typów zmiennych (np. char, integer, real), nazwy stałych (np. Maxint) lub nazwy procedur i funkcji (np. cos, sin, dec, readln, writeln, sqrt, sqr, round, abs, ord, chr, inc, true, false); słowa zastrzeżone mogą być przedefiniowywane w przez programistę, ale wówczas tracą swoje znaczenie, np. można zadeklarować zmienną o nazwie char typu real (char: real; gdzie char jest nazwą typu znakowego służącego do przechowywania znaków kodu ASCII - znaki o kodach od #0 .. #255) i potem dokonać podstawienia char:=5;
liczby: ciąg znaków będących cyframi (np. 124, -12, +34, 1.23, 1E-2); mogą być poprzedzone znakiem (+) lub (-), który określa znak liczby; liczby rzeczywiste mogą być zapisywane w postaci wykładniczej, jako potęgi 10 (np. 3e2, 9.0e-2); przed kropką dziesiętną muszą zawierać co najmniej jeden znak (.1e2 - błąd); liczby w kodzie szesnastkowym są poprzedzone znakiem $ (np. $41 = 65; x:=$30);
napisy (łancuchy): ciągi znaków umieszczone pomiędzy dwoma apostrofami, np. 'To jest napis', 'Tekst na ekran'; w celu wyprowadzenia apostrofu należy poprzedzić go apostrofem, np. 'To jest ”Turbo Pascal'' i to też'; maksymalna długość tekstu zależy od implementacji; w systemie Turbo Pascal wynosi ona 255; w systemie tym istnieje typ string, który umożliwia deklarowanie zmiennych typu łańcuchowego o podanej długości (np. var nap: string[20] - długość 20 znaków; d: string - długość 255 znaków);
komentarze: ciągi znaków umieszczane pomiędzy parą nawiasów klamrowych { } lub (* *), np. { komentarz }, (* komentarz *); treść komentarza nie podlega kompilacji;
separatory: symbole służące do oddzielenia elementów i symboli leksykalnych; są to najczęściej: spacja, symbole operatorów arytmetycznych, logicznych i relacji, znaki przestankowe, dwukropek; dwa dowolne identyfikatory muszą być rozdzielone separatorem; każda deklaracja lub instrukcja kończy się średnikiem; znak kropki kończy program (np. end.).
Za pomocą elementów leksykalnych języka kodowane są określone działania.
Przykład 2.5. Wyprowadzanie tekstu na zadanej pozycji ekranu. Wykorzystanie procedury GotoXY(a,b), która ustawia kursor na pozycji (a,b) ekranu i jest standardową procedurą systemu Turbo Pascal 7.0.
uses crt;
Begin {początek programu}
clrscr; { czyszczenie ekranu }
gotoxy(20,5); write('***********************');
gotoxy(20,6); write('* *');
gotoxy(20,7); write('* To jest wyklad *');
gotoxy(20,8); write('* *');
gotoxy(20,9); write('***********************');
readln;
End.
Słowa kluczowe: uses, Begin, End.
Identyfikatory: clrscr, gotoxy, write, readln (słowa zastrzeżone).
Liczby: 20, 5, 6, 7, 8, 9.
Napisy: '* To jest wyklad *', '***********************', itd.
Typy danych
Typ definiuje zakres lub zbiór dopuszczalnych wartości zmiennych, stałych i funkcji, zbiór dopuszczalnych operacji wykonywanych na tych wartościach oraz sposób zapisu zmiennej danego typu w pamięci. Na przykład zmienne typu integer służą do przechowywania liczb całkowitych z przedziału -32768 .. 32767. Są one reprezentowane w pamięci na 2 bajtach w kodzie U2 - liczby binarne ze znakiem. W języku programowania Turbo Pascal 7.0 istnieją:
typy predefiniowane, które można wykorzystywać bez ich wcześniejszego definiowania w deklaracjach zmiennych i funkcji, np.
typ całkowity: integer; { język wzorcowy Pascal }
typ rzeczywisty: real; { język wzorcowy Pascal }
typ znakowy: char; { język wzorcowy Pascal }
typ logiczny: boolean; { język wzorcowy Pascal }
typ napisowy: string;
typy definiowane przez użytkownika (za pomocą deklaracji type), np.
typ wyliczeniowy (lista nazw);
typ okrojony (podzbiór typu wyliczeniowego);
typy strukturalne (np. array - tablica, record - rekord, file - plik)
definiowane przez użytkownika w oparciu o typy standardowe.
Typy mogą być:
proste (niepodzielne; nie można wykonywać operacji na ich częściach; zmienne tego typu mogą być inicjowane jedną instrukcją podstawienia; np. var d :integer; d:=14;)
napisowe (inaczej typy łańcuchowe; ciągi znaków o znanej długości, ograniczonej do 255 znaków);
strukturalne (służą do opisu obiektów złożonych; składają się ze zbioru elementów typu prostego; możliwy jest dostęp do pojedynczych elementów za pomocą wspólnej nazwy; np. tablica liczb całkowitych złożona z N elementów: tab: array[1.. N] of integer; elementy tworzące typ strukturalny mogą być względem siebie w pewnej relacji; np. mogą być zorganizowane w dynamiczne struktury informacyjne: listy, drzewa, grafy);
wskaźnikowe (przechowują programowe adresy zmiennych);
proceduralne (przechowują adresy procedur lub funkcji);
obiektowe (integrują dane i funkcje zarządzania danymi).
Typy porządkowe reprezentują skończoną liczbę uporządkowanych wartości. Mogą one być predefiniowane (całkowite, logiczne, znakowe) lub definiowane przez użytkownika (typ wyliczeniowy, typ okrojony).
Klasyfikacja typów danych
Typy całkowite
Należą do typów porządkowych, składających się ze skończonego i uporządkowanego zbioru wartości. Są przeznaczone do przechowywania danych całkowitych. W zależności od przewidywanego zakresu danych należy je przechowywać w zmiennych całkowitych odpowiednich typów. Za zmienne nie można podstawiać wartości spoza zakresu ich typów.
Nazwa Zakres Liczba bajtów
ShortInt -128 .. 127 1
Integer -32768 .. 32767 2
LongInt -2147483648 .. 2147483647 4
Byte 0 .. 255 1
Word 0 .. 65535 2
Typy rzeczywiste
Należą do typów prostych, które są przeznaczone do przechowywania wartości rzeczywistych. Liczby rzeczywiste są zapisywane w postaci z kropką dziesiętną, np. 231.47, lub z wykorzystaniem formatu z wykładnikiem dziesiętnym, np. 2.3147E+02, gdzie E - oznacza podstawę systemu dziesiętnego.
Nazwa Zakres Liczba bajtów
Real ± 2.9E-39; ±1.7E38 6
Single ± 1.5E-45; ±3.4E38 4
Double ± 5.0E-324; ±1.7E308 8
Extended ± 3.4E-4932; ±1.1E4932 10
Comp -263 +1 (-9.2E18); 263 -1 (9.2E18) 8
Typy Single, Double, Extended i Comp wymagają użycia koprocesora lub jego emulacji programowej. Sposób działania kompilatora można ustawić za pomocą menu Options-Compiler lub przez włączenie opcji kompilatora na początku kodu źródłowego programu {$N+, E+}.
Typ rzeczywisty Comp służy do przechowywania dużych liczb całkowitych.
Typ standardowy Real nie wymaga używania koprocesora ani jego emulacji programowej.
Każdy z typów rzeczywistych ma określoną dokładność wyznaczoną liczbą cyfr dokładnych po przecinku (liczba wyznaczana przy zerowej wartości części całkowitej liczby). W przypadku używania koprocesora liczby cyfr znaczących po przecinku dla każdego z typów rzeczywistych są następujące:
Real - 12 cyfr znaczących po przecinku,
Single - 8 cyfr znaczących po przecinku,
Double - 16 cyfr znaczących po przecinku,
Extended - 20 cyfr znaczących po przecinku.
W przypadku emulacji koprocesora dokładności są o jedną cyfrę znaczącą mniejsze i wynoszą odpowiednio 11, 7, 15 i 19 cyfr znaczących.
Typ znakowy
Typ porządkowy, wykorzystywany do przechowywania jednego znaku kodu ASCII. Kody ASCII są liczbami z przedziału od 0 do 255. Każdy znak ma unikalny kod. Wartości znaków kodu ASCII określa się za pomocą numerów od #0 do #255.
Nazwa Zakres Liczba bajtów
Char #0 .. #255 1
Typ logiczny
Typ porządkowy, wykorzystywany do przechowywania danych dwustanowych. Zbiór jego wartości stanowią dwie predefiniowane stałe: False (fałsz), True (prawda).
Nazwa Zakres Liczba bajtów
Boolean False, True 1
Typ napisowy
Typ napisowy (łańcuchowy) jest wykorzystywany do przechowywania danych alfanumerycznych (litery i znaki) zdefiniowanych jako ciąg znaków ujętych w apostrofy (np. 'To jest napis'). Struktura danych typu string zajmuje 256 bajtów pamięci, ponumerowanych od 0 do 255. Na pozycji zerowej zmiennej typu string automatycznie wpisywana jest aktualna długość zdefiniowanego tekstu. Jest ona zapisywana w postaci znaku o kodzie równym długości łańcucha. Można zdefiniować typ napisowy, który ma mniejszy rozmiar niż typ string, np. string[20]. Najkrótszy tekst nie zawiera żadnego znaku ' '.
Nazwa Zakres Liczba bajtów
String tekst pusty .. tekst do 255 znaków 256
Do typów porządkowych definiowanych przez użytkownika należą: typ wyliczeniowy oraz typ okrojony.
Typ wyliczeniowy
type ident_typu = (lista_nazw);
Pierwszy element na liście ma numer 0, kolejne 1, 2, ... , itd. Typ ten jest wykorzystywany do indeksowania tablic lub w instrukcjach decyzyjnych oraz iteracyjnych.
Np. type PRoku = (Wiosna, Lato, Jesień, Zima);
Dni = (Pon, Wt, Sr, Czw, Pt, Sob, Ndz);
Typ okrojony
Określa podzbiór jednego z innych typów porządkowych. W szczególnści może stanowić podzbiór typu wyliczeniowego.
type ident_typu = wartość1 .. wartość2;
gdzie wartość1 < wartość2.
Np. type TMies = 1..12;
Kolory = (White, Blue, Red, Green, Yellow, Black);
DwaKolory = (White, Blue);
Definiowanie stałych i deklarowanie zmiennych
Stałe należy definiować w sekcji definicji stałych natomiast zmienne w sekcji deklaracji zmiennych programu. Definicje stałych powinny poprzedzać deklaracje zmiennych. Deklaracje stałych i zmiennych powinny poprzedzać definicje procedur i funkcji.
Stałe i zmienne zadeklarowane w części deklaracyjnej programu, poza wszystkimi procedurami i funkcjami, mają charakter globalny, tj. są dostępne w całym programie.
W języku Turbo Pascal można umieszczać definicje stałych po deklaracjach zmiennych. Ponadto deklaracje stałych i zmiennych mogą występować po deklaracjach procedur i funkcji, przed rozpoczęciem części wykonawczej programu.
W definicjach stałych i deklaracjach zmiennych należy przestrzegać zasady, aby korzystać tylko z elementów, które zostały zdefiniowane lub zadeklarowane wcześniej.
Definiowanie stałych
Definicje stałych rozpoczynają się od słowa kluczowego const. Każda definicja stałej ma następującą postać:
nazwa_stałej = wartość_stałej;
Typ stałej jest określany na podstawie nadawanej jej wartości.
Definicja stałej globalnej może występować tylko raz w całym programie.
Wartości stałej nie można modyfikować w części wykonawczej programu.
Przykładowe definicje stałych:
Const
k = 15; { stała całkowita typu integer }
n = 40000; { stała całkowita typu word }
d = 500000; { stała całkowita typu longint }
x = -3.14; { stała rzeczywista typu real }
y = 0.3E2; { stała rzeczywista typu real }
c = 'K'; { stała znakowa typu char}
s = 'To jest napis'; { stała napisowa }
Wartość stałej można również zdefiniować za pomocą wyrażenia matematycznego, w którym są wykorzystywane standardowe operatory i stałe zdefiniowane wcześniej.
p = 10∗y + 5;
q = (k + n)∗2;
Podczas kompilacji stała liczbowa lub wyrażenie reprezentujące stałą są tłumaczone na wartość liczbową, która jest wpisywana w obszar pamięci przydzielony na stałą. Stała napisowa jest wpisywana znak po znaku w obszar pamięci przeznaczony na stałą.
Deklarowanie zmiennych
Zmienne globalne, tj. dostępne w całym programie, deklaruje się w sekcji deklaracji zmiennych programu. Deklaracje zmiennych rozpoczynają się od słowa kluczowego var. Każda deklaracja zmiennej ma następującą postać:
nazwa_zmiennej : typ_zmiennej;
Typ zmiennej musi być:
jednym z typów standardowych,
typem zdefiniowanym wcześniej przez użytkownika,
typem opisanym w deklaracji zmiennej.
Deklaracja zmiennej globalnej może występować tylko raz w całym programie. Użycie zmiennej, która nie została zadeklarowana lub ponowna deklaracja zmiennej powodują błąd kompilacji. Zmienne tego samego typu mogą być wymienione w jednej deklaracji.
nazwa_zmiennej1, nazwa_zmiennej2 : typ_zmiennej;
Przykładowe deklaracje zmiennych:
Var
a, b : integer; { zmienne typu integer }
c : char; { zmienna typu char }
d : boolean; { zmienna typu boolean }
e, h : longint; { zmienne typu longint }
x, y, z, w : real; { zmienne typu real }
s : string; { zmienna typu string }
W deklaracji zmiennej można użyć typu zdefiniowanego przez użytkownika.
type
Bajt = byte; { typ o nazwie Bajt - zgodny z bajt }
Tlicz = real; { typ o nazwie Tlicz - zgodny z real }
Var
p : Bajt; { zmienna typu Bajt }
q, r : Tlicz; { zmienne typu Tlicz }
Po deklaracji wartości zmiennych nie są określone. W przypadku zmiennych globalnych zdefiniowanych poza procedurami i funkcjami programu system Turbo Pascal 7.0 nadaje wartości początkowe zmiennym równe zero. Zaleca się jednak inicjowanie zmiennych przez programistę w części wykonawczej programu. Wyjątek stanowią jedynie zmienne inicjowane - definiowane jako stałe z określonym typem, którym nadaje się wartości początkowe w części deklaracji stałych. Zmienne inicjowane definiuje się w sposób następujący:
const
nazwa_zmiennej : typ_zmiennej = wartosc_zmiennej;
Na przykład:
const k : integer = 10; { zmienna inicjowana k }
r : real = 1.23; { zmienna inicjowana r }
Pamięć przeznaczona na przechowywanie wartości zmiennych, stałych oraz zmiennych inicjowanych jest rezerwowana podczas kompilacji. Zmienne i stałe są przechowywane w segmencie danych programu. Wartości początkowe zmiennych i stałych globalnych są odnawiane przy każdym uruchomieniu programu.
Zmienne i stałe globalne, definiowane w części deklaracyjnej programu, są przechowywane w pamięci operacyjnej przez cały czas działania programu. Zmienne takie są nazywane zmiennymi statycznymi.
W języku Pascal istnieje również możliwość deklarowania zmiennych, dla których pamięć może być przydzielana na bieżąco w trakcie działania programu. Zmienne tego typu są nazywane zmiennymi dynamicznymi, gdyż w części wykonawczej programu istnieje możliwość alokacji i zwolnienia wykorzystywanej przez te zmienne pamięci.
Modyfikowanie zawartości zmiennych
Wartości początkowe zmiennych oraz zmiennych inicjowanych mogą być modyfikowane przez operacje realizowane w programie. Sposób modyfikacji zależy od zastosowanego algorytmu. Wartości zmiennych można modyfikować w części wykonawczej programu za pomocą:
instrukcji przypisania (:=); np. a:=6; p:=2; k:= 5; r:= 1.23;
instrukcji wczytującej dane z klawiatury lub z pliku.
Wartości zmiennych można wczytywać ze standardowego pliku wejściowego, reprezentowanego przez zmienną plikową o nazwie input (zmienna typu text), lub z pliku dyskowego. Domyślnie ze standardowym plikiem wejściowym jest utożsamiana klawiatura. Operacja wczytywania wartości zmiennych ze standardowego pliku wejściowego może być zrealizowana za pomocą procedur read lub readln, np.: readln(input, p); readln(input, k); read(input, r). W instrukcjach wczytujących dane z pliku standardowego można pominąć nazwę zmiennej plikowej input i wykorzystywać instrukcje w postaci: readln(p); readln(k); read(r).
Wartości zmiennych i stałych można wyprowadzać do standardowego pliku wyjściowego, reprezentowanego przez zmienną plikową o nazwie output (zmienna typu text), lub do pliku dyskowego. Domyślnie ze standardowym plikiem wyjściowym jest utożsamiany ekran monitora. Operacja wyprowadzania zmiennych i stałych do standardowego pliku wyjściowego może być zrealizowana za pomocą procedur write lub writeln, np.: writeln(output, p); writeln(output, k); write(output, r). W instrukcjach wyprowadzających dane do pliku standardowego można pominąć nazwę zmiennej plikowej output i wykorzystywać instrukcje w postaci: writeln(p); writeln(k); write(r).
Po zakończeniu programu dane zapisane w zmiennych znikają z pamięci operacyjnej. W celu trwałego zapamiętania wartości zmiennych należy zapisać je do pliku dyskowego. Dzięki temu przy ponownym uruchomieniu programu możliwe będzie odczytanie danych z pliku i zainicjowanie nimi zmiennych. W języku Pascal do komunikacji z plikami są wykorzystywane zmienne plikowe następujących typów: text, file of i file.
Standardowe wejście i wyjście
W języku Pascal z każdym uruchamianym programem są automatycznie kojarzone dwa pliki: standardowy plik wejściowy - klawiatura oraz standardowy plik wyjściowy - ekran monitora. Komunikacja ze standardowym plikiem wejściowym jest realizowana za pośrednictwem zmiennej plikowej o nazwie input, natomiast komunikacja ze standardowym plikiem wyjściowym jest realizowana za pośrednictwem zmiennej plikowej o nazwie output.
Zmienne plikowe input i output są typu text. Umożliwiają one odczyt i zapis danych do plików tekstowych, w których kolejne bajty są interpretowane jako znaki kodu ASCII. Plik wejściowy (input) jest otwierany do odczytu danych z klawiatury a plik wyjściowy (output) jest otwierany do zapisu danych na ekran. Liczby wczytywane z klawiatury do zmiennych są automatycznie zamieniane z postaci znakowej na wartość liczbową. Podczas operacji wyprowadzania wartości zmiennych na ekran realizowana jest automatyczna konwersja danych liczbowych na postać znakową. Każda liczba jest zamieniana na ciąg bajtów reprezentujących kody ASCII jej cyfr składowych. W szczególności zmienna jednobajtowa x: byte=123 jest zapisywana do pliku tekstowego jako ciąg znaków o kodach: #49 #50 #51. W przypadku liczb rzeczywistych dodatkowo do pliku wpisywany jest znak kropki dziesiętnej.
Do wczytywania danych z klawiatury służą procedury readln i read. Argumentami procedur są zmienne, do których są wprowadzane dane z klawiatury. Sposoby wywoływania:
Readln(w); Read(w);
Readln(w1, w2, ... , wN); Read(w1, w2, ... , wN);
Readln;
Zmienne w, w1, w2, ... , wN mogą być różnych typów. Dane są wczytywane do zmiennych zgodnie z kolejnością ich występowania na liście argumentów. Nie można wczytywać z klawiatury zmiennych typu wyliczeniowego.
Po wywołaniu procedury readln lub read program zatrzymuje się oczekując na wprowadzenie danych z klawiatury. Wprowadzanie każdej danej należy zakończyć za pomocą klawisza Enter. Liczba wprowadzanych danych oraz ich typy muszą być zgodne z liczbą oraz typami parametrów procedur readln i read. W przypadku niezgodności wystąpi błąd i program zostanie przerwany. Wprowadzane dane są wyświetlane na ekranie począwszy od miejsca, w którym znajduje się kursor. Po wczytaniu danych za pomocą procedury readln następuje przejście kursora na początek następnego wiersza.
Bezparametrowa procedura readln powoduje wstrzymanie programu aż do wciśnięcia klawisza Enter. Może ona być wykorzystana do zatrzymania programu w celu odczytania zawartości ekranu.
Przykład 2.6. Wczytywanie liczb i znaków.
Var x,y,z: real;
k: integer;
z1, z2: char;
s: string[20];
Begin
writeln(' Podaj trzy liczby : ');
readln(x); readln(y); readln(z);
writeln(' Podaj trzy liczby : ' );
readln(x, y, z); { po każdej danej Enter }
write(' Podaj k = '); readln(k);
writeln(' Podaj z1 i z2 : '); readln(z1, z2);
write(' Podaj s = '); readln(s); readln;
End.
Do wyprowadzania danych na ekran monitora służą procedury writeln i write. Argumentami procedur mogą być zmienne i stałe, łańcuchy lub wyrażenia, których wartości są wyprowadzane na ekran. Sposoby wywoływania:
Writeln(w); Write(w);
Writeln(w1, w2, ... , wN); Write(w1, w2, ... , wN);
Writeln;
Zmienne w, w1, w2, ... , wN mogą być różnych typów. Dane są wyprowadzane na ekran zgodnie z kolejnością ich występowania na liście argumentów. Nie można wyprowadzać na ekran danych typu wyliczeniowego.
Po wywołaniu procedury writeln lub write dane są wyświetlane na ekranie począwszy od miejsca, w którym znajduje się kursor. Jeśli napis nie mieści się w jednej linii ekranu, to jest przenoszony do następnej linii. Po wyprowadzeniu danych za pomocą procedury writeln następuje przejście kursora na początek następnego wiersza. Po zakończeniu działania procedury write kursor ustawia się bezpośrednio za ostatnim wyprowadzonym znakiem.
Bezparametrowa procedura writeln powoduje przeniesienie kursora na początek następnego wiersza.
Dane można wyprowadzać w postaci sformatowanej. Dla liczb całkowitych i tekstów można podać szerokość pola przeznaczoną na wyprowadzaną daną, liczoną w znakach. W przypadku liczb rzeczywistych można dodatkowo podać precyzję określającą liczbę uwzględnianych miejsc po przecinku. W ramach szerokości pola jest liczona pozycja na znak liczby, kropkę dziesiętną oraz cyfry po przecinku. Puste pola są wypełniane spacjami. Na przykład w celu wydrukowania liczby rzeczywistej x na 9 polach z uwzględnieniem 2 miejsc po przecinku należy zastosować instrukcję writeln(x : 9 : 2). Jeśli liczba znaków danej przekracza szerokość pola, to zostanie ona wyprowadzona w całości z uwzględnieniem precyzji. Na przykład instrukcja writeln(x: 0 : 2) wyświetli liczbę x z uwzględnieniem dwóch cyfr po przecinku. Ostatnia cyfra po przecinku jest zaokrąglana na podstawie cyfry poprzedzającej. Jeżeli nie poda się formatu, to liczba rzeczywista zostanie wyprowadzona na ekran w postaci wykładniczej. W szczególności zmienna x = 3.14 typu real zostanie wyprowadzona z uwzględnieniem mantysy (3.1400000000) i cechy (+00) w postaci 3.1400000000E+00.
W ogólnym przypadku instrukcje umożliwiające wyprowadzenie liczb rzeczywistych w1, w2, ... , wk w zadanym formacie mają następującą postać:
writeln(w1: p1: n1, w2 : p2 : n2, ... , wk : pk : nk);
write(w1: p1: n1, w2 : p2 : n2, ... , wk : pk : nk); gdzie
p1, p2, ... , pk - liczby pozycji przeznaczonych dla danych w1, w2, ... , wk;
n1, n2, ... , nk - parametry określające liczby miejsc po przecinku.
Przykład 2.7. Wyprowadzanie danych na ekran.
Var a: integer;
x: real;
s: string;
Begin
x:=3.145;
writeln(x); { 3.1450000000E+00}
writeln(x:6:2); { 3.15}
writeln(x:0:2); {3.15}
a:=17;
writeln(a:5); { 17}
s:='To jest tekst'; { To jest tekst}
writeln(s: 15);
readln; { czekaj na enter }
End.
str. 1
Typ Prosty Porządkowy
Predefiniowany Predefiniowany
Rzeczywisty Całkowity
real shortint
integer
Predefiniowany longint
Napisowy (łańcuchowy) byte
string word
Logiczny
Strukturalny boolean
Tablicowy Znakowy
array char
Rekordowy Definiowany
record Wyliczeniowy
Zbiorowy (lista nazw)
set of Okrojony
Plikowy (podlista)
file
Wskaźnikowy
^typ_danej
Proceduralny
procedure
function
Obiektowy
object