Podstawy Programowania – wersja rozszerzona
strona 1 z 32
/
Podstawy
Programowania
Na przykładach w języku Turbo Pascal
Szybki kurs podstaw programowania w oparciu o programowanie strukturalne
w języku Turbo Pascal. Zawiera proste i klarowne wyjaśnienia podstawowych
poleceń spotykanych we wszystkich językach oraz przykładowe kody i zadania.
Kurs programowania obiektowego w przygotowaniu.
2012
M.Woliński
KAZA© Corp.
2012-07-05
Spis Treści
Rolą wstępu, czyli co to jest program ....................................................... 5
Jak rozmawiać z kompilatorem? .............................................................. 6
Tworzymy nowy program ........................................................................ 7
Zmienne i typy zmiennych ........................................................................ 8
…oraz polecenia Or, And, Not .................................................................10
Instrukcja wyboru CASE .......................................................................... 12
Pętle FOR/REPEAT/WHILE ....................................................................... 13
Funkcje Rekurencyjne .............................................................................18
Przykładowe Programy ........................................................................... 25
Tworzenie Ścieżki (Katalogów) ................................................................25
Podstawy Programowania – wersja rozszerzona
strona 5 z 32
Rolą wstępu, czyli co to jest program
Wiele osób chcąc nie chcąc zetknęło się i to nie raz z programami. Czy to w pracy, w
domu czy w szkole, kontakt z komputerem jest nie unikniony, a co za tym idzie i z
programami. W niniejszej książce pokażę Państwu jak skutecznie tworzyć własne programy,
dzięki czemu będą mogli państwo dostosować świat komputera do siebie a nie na odwrót.
Program jest to zestaw poleceń (instrukcji) dla procesora wykonywanych w celu
uzyskania jakiegoś efektu. Aby program mógł zaistnieć w komputerze musi być zrozumiały
dla procesora, a co za tym idzie komunikować się w formie zer i jedynek. Pisanie programów
w ten sposób jest uciążliwe i wyjątkowo nieefektywne, dlatego przydaje się kompilator.
Kompilatory są to pewnego rodzaju tłumacze pośredniczące pomiędzy użytkownikiem, a
komputerem. Większość kompilatorów zostało zrobionych w języku angielskim i rozpoznaje
podstawowe słowa takie jak IF (jeżeli), END (koniec), EXIT (wyjście), itp. Dzięki kompilatorowi
możliwe jest szybkie przekształcenie języka pisanego na system zer i jedynek. Każdy
kompilator posługuje się jednym (bądź kilkoma) dialektami nazywanymi językami
programowania. Tak jak Brytyjczycy piszą „cannot”, a amerykanie „can’t” mając na myśli to
samo, tak samo języki programowania różnią się poleceniami dającymi ten sam efekt. Wybór
odpowiedniego języka oraz kompilatora jest bardzo ważny, dlatego warto poświęcić mu
nieco czasu. Z uwagi na prostotę języka wszelkie przykłady zostaną napisane w języku Turbo
Pascal. Jeśli nie wiesz jaki wybrać język i kompilator, lub dopiero zaczynasz przygodę z
programowaniem proponuję również zacząć od najprostszego. Kompilator Turbo Pascala
można pobrać ze strony:
www.darmoweprogramy.org/394/Dev-Pascal
Zawansowany użytkownikom polecam Delphi 7
umożliwiające poza standardowym
tworzeniem aplikacji konsolowych, również tych pojawiających się w trybie okienkowym.
1
Delphi 7 wyszło ze sprzedaży w roku 2012. Licencja nie zezwala na odsprzedanie, jednak proces sądowy
z tym związany wciąż jest w toku.
Podstawy Programowania – wersja rozszerzona
strona 6 z 32
Jak rozmawiać z kompilatorem?
Komunikacja z kompilatorem wykorzystuje kilka podstawowych zwrotów podzielonych
na kategorie. Pewne polecenia są wykonywane jako pierwsze inne jako ostatnie, ale
wszystkie składają się ze znaków. Oto podstawowy zestaw poleceń:
Rodzaj
Opis
Polecenie
Arytmetyczne
Dodawanie
+
Odejmowanie
-
Mnożenie
*
Dzielenie
/
Reszta z dzielenia
mod
Dzielenie całkowite
div
Logiczne
Albo
or
Oraz
and
Nie
not
Tylko jedno z
xor
Relacyjne
Większe
>
Mniejsze
<
Równe
=
Różne
<>
Większe lub równe
>=
Mniejsze lub równe
<=
Orientacyjne
Początek
begin
Koniec
end
Komentarz
Komentarz dla
programisty/beta-testera
//
{
}
Każde z powyższych poleceń jest poleceniem podstawowym i nie wynika z niego żadna
akcja. Jednakże tworząc każde polecenie złożone potrzebna będzie znajomość poleceń
podstawowych, które będą wchodzić w skład innych poleceń. Zauważ, że polecenia
opatrzone znakami komentarzy będą ignorowane. Są one jednak bardzo pomocne jeśli nad
projektem pracuje więcej osób.
Podstawy Programowania – wersja rozszerzona
strona 7 z 32
Tworzymy nowy program
Aby utworzyć nowy program wystarczy wykonać kilka prostych kroków. Po
uruchomieniu programu Dev-Pas.exe tworzymy nowy projekt klikając na ikonę w
lewym górnym rogu. Wyświetli się okno komunikatu z zapytaniem o rodzaj
projektu. Na początek wybieramy „konsole aplication”, wybieramy miejsce
zapisu i już mamy gotowy program. Na razie nie wykonuje on jeszcze żadnych poleceń, ale
dzięki kompilatorowi zaczął on już istnieć. Przyjrzyjmy się z czego składa się nasz program.
Treść naszego programu składa się z trzech linijek. W pierwszej linii znalazło się
polecenie „program untitiled1;”. Polecenie to będzie otwierało każdy program, gdyż
najzwyczajniej informuje kompilator, że od tego miejsca zaczyna się treść programu, oraz
nadaje mu nazwę. W tym wypadku jest to „untitiled1”. W to miejsce można wpisać własną
nazwę. Należy tylko pamiętać aby zakończyć znakiem „;” [średnik]. Średnik informuje
kompilator o końcu polecenia. Niemal wszystkie polecenia kończą się średnikiem. Wyjątek
stanowi koniec programu oznaczony znakiem „.” [kropka].
Drugą linię stanowi słowo Begin. Oznacza on początek pewnego rozdziału. Wszystkie
następujące po nim polecenia kompilator będzie traktował jako nierozerwalną całość, aż do
słowa end. Jako że jest to pierwsze takie polecenie w naszym programie kompilator uzna
wszystko pomiędzy słowami „Begin”, a „end” za główną treść naszego programu. To tutaj
znajdą się polecenia, które będą miały dać jakiś widoczny efekt. Spróbujmy go wywołać
używając poleceń writeln oraz readln
. Zaraz za słowem Begin wpiszmy:
writeln(‘Hello World’);
readln();
Polecenie writeln spowoduje wyświetlenie zawartości nawiasu. W tym wypadku jest to tekst
Hello World. Warto zwrócić uwagę na fakt, że tekst, który nie jest poleceniem w turbo
pascal’u umieszcza się pomiędzy apostrofami. Natomiast polecenie readln każe programowi
czekać na sygnał z klawiatury. Nawias za tym polecenie pozostawiamy pusty, ponieważ to co
zostanie wpisane nas zwyczajnie nie interesuje. Teraz w zakładce „execute” wybieramy opcję
„Compie”. To samo polecenie można znaleźć na pasku narzędzi. Teraz kompilator
wprowadził zmiany do naszego programu. Aby zobaczyć efekty wybieramy przycisk execute.
Powinniśmy zobaczyć okno z czarnym tłem i białym napisem „Hello World”. Napisaliśmy nasz
pierwszy program.
2
Procedury writeln i readln mają również wersję bez zmiany wiersza – write i read.
Podstawy Programowania – wersja rozszerzona
strona 8 z 32
Zmienne i typy zmiennych
Zmienne w języku Turbo Pascal zapisuje się po słowie kluczowym VAR. Zmienna jest to
reprezentacja pamięci w programie. Innymi słowy, jeśli program to biurko, to zmienne są
kartkami na biurku. Każda zmienna musi mieć nazwę poprzez którą kompilator będzie ją
identyfikował, oraz mieć przypisany typ. Istnieje kilka podstawowych typów. Są to:
integer(liczba całkowita), Real(liczba rzeczywista), string(łańcuch znaków) oraz
boolean(prawda lub fałsz). Deklaracja zmiennych wygląda następująco:
VAR
imie,nazwisko: string;
wiek:integer;
srednia:Real;
W ten właśnie sposób zadeklarowane zostały cztery zmienne. Deklaracja zmiennych
nie jest poleceniem, ale informacją więc musi nastąpić przed pierwszym słowem Begin, i
opisane w ten sposób zmienne będą rozpoznawalne aż do końca programu. Jeśli chcemy
zadeklarować kilka zmiennych posiadających ten sam typ możemy wymienić je po przecinku,
tak jak imie i nazwisko. Ogólny schemat deklaracji wygląda następująco:
<<nazwa1>>,<<nazwa2>>,..,<<ostatnia_nazwa>>:<<typ>>;
Korzystając ze zmiennej możemy zapisać na niej pewne informacje, tak by program pamiętał
o nich. W tym celu używa się dwuznaku „:=”. Takie polecenie nazywa się przypisaniem. Oto
kilka przykładów przypisania:
wiek:=3;
imie:=’Jan’;
nazwisko:=imie;
Błędem byłoby jednak przypisanie „imie:=3”. Z uwagi na brak apostrofów kompilator uznałby
3 liczbą i nie pozwoliłby na zapisanie jej na zmiennej przechowującej łańcuch znaków. Teraz
znając już zasady operacji na zmiennych możemy użyć procedury readln(); . Aby program
zapamiętał to co użytkownik wpisuje na klawiaturze wystarczy wpisać polecenie
readln(<<zmienna>>); przykładowo readln(imie);. Od tego momentu za każdym razem gdy
wpiszemy imie program użyje otrzymanych wtedy od użytkownika danych. Aby wyświetlić je
na ekranie wystarczy wpisać polecenie writeln();. Na przykład Writeln(Imie);.
Dodatkowo zmienne typu string traktowane są w sposób specjalny. Możliwe jest
odwołanie się do poszczególnych znaków w łańcuchu. W naszym przypadku: imie[2] = ‘a’.
Można to wykorzystać przy tworzeniu podpisów. Jeśli użyjemy przypisania:
Imie:=’Jan’;
Nazwisko:=’Nowak’;
Podpis:=imie[1]+’. ‘+nazwisko;
Writeln(Podpis);
Na ekranie otrzymamy „J. Nowak”.
Odwołania do znaków można składać w słowa za pomocą zmiennych tymczasowych,
tak aby złożyć kawałki tekstu w większą całość. Przykładowo nasz podpis może widnieć za
cytatem, albo zostać zakodowany poprzez zmianę szyku znaków(!). Szyfrowanie w trybie
Podstawy Programowania – wersja rozszerzona
strona 9 z 32
tekstowym opiera się na zmianie znaków w szyfrowanym ciągu z jednego wzoru na drugi.
Korzysta się wtedy zazwyczaj ze słowa klucza i uzupełnia alfabetem: kodabcefghi… W tym
wypadku słowem kluczem jest „kod”.
Zadania
Zad1
Program zagadka;
var
imie:string;
Begin
imie:=’2’;
imie:=’Kasia’;
imie:=imie + ‘+’ +
’Michał’;
writeln(imie);
readln();
end.
Jaki napis pojawi się na ekranie po skompilowaniu takiego programu?
Zad2
Napisz program „echo”, który będzie powtarzał to co wpisze użytkownik.
Zad3
program mat;
var
a:integer;
begin
a:=1;
a:=a+1;
writeln(a+1);
readln();
end.
Sprawdź jaka liczba wyświetli się po wykonaniu tego programu, a jaką wartość ma
zmienna a.
Podstawy Programowania – wersja rozszerzona
strona 10 z 32
Warunek if….
Warunki są podstawą działania programów. Za każdym razem, gdy rodzaj działanie
będzie wymagał podjęcia decyzji będziemy używać polecenia IF. Ma ono następującą
składnię:
IF (warunek) then polecenie else polecenie;
Warunek musi być jasno określony, tzn. musi jednoznacznie być prawdą albo fałszem.
Warunkiem nie może być np. 2, ale 2=3 to już sensowny warunek, ponieważ można określić
go jako fałsz. Po słowie kluczowym then wpisujemy polecenie, które ma być wykonane w
przypadku prawdziwości warunku, a po słowie else polecenie na wypadek fałszu. Przykłady:
if (2=2) then a:=2; znaczy „jeżeli 2=2 to wtedy niech a stanie się 2”
if (a=2) then a:=3 else a:=2; znaczy „jeżeli a=2 to wtedy niech a stanie się 3, a jeśli nie to
niech a stanie się 2”
Aby jeszcze trochę rozjaśnić sytuację napiszmy program, który się z nami przywita.
Zaczynamy, a więc:
program witaj;
var
s:string;
Begin
readln(s);
if (s=’Witaj.’) then writeln(‘Witaj.’);
readln();
end.
Ten program odpowie nam jeśli tylko napiszemy do niego „Witaj.”, ale gdy będziemy
do niego pisać cokolwiek innego (np. cześć) już nie. Warto go więc ulepszyć.
…oraz polecenia Or, And, Not
Zamieńmy polecenie „if…” na „if (s=’Witaj.’) OR (s=’Witaj’) then writeln(‘Witaj.’);”
dzięki temu nasz program odpowie, nawet gdy ominiemy kropkę. Spróbuj teraz samemu
dodać kilka warunków, tak aby program odpowiadał także na np. Dzień dobry.
Polecenia Or, And, Not są poleceniami ustalającymi zależność pomiędzy warunkami.
Dzięki nim kompilator wie jaka jest waga każdego z nich. Jeśli zapiszę „2=2 and not 2=3”
znaczy to, że program musi sprawdzić obydwa warunki. My jednak wiemy, że nie ma takiej
potrzeby więc wystarczy wpisać „2=2 or not 2=3”. W takim układzie program wie, że
wystarczy mu sprawdzić poprawność dowolnego z warunków, i gdy prawdziwe będzie, że
2=2 nie będzie już się zastanawiał czy 2 nie jest równe czasem 3. Czasem używanie tych
poleceń wymaga użycia dodatkowych nawiasów, dlatego zaleca się aby w jednym nawiasie
nie było więcej niż 2 warunków. Bezpieczniej zapisać jest
(a=2 and b=2) Or (a=b) niż (a=2 and b=2 Or a=b).Spróbujmy w oparciu o polecenia if napisać
prosty kalkulator. Jako zmiennych będziemy potrzebować dwóch liczb, oraz zmiennej
tekstowej jako działania. (znak „+” nie jest liczbą). W pierwszej kolejności odczytujemy
działanie, a następnie 2 liczby. I co dalej? Dalej 4x IF. Dla działań +,-,*,/.
If (dzialanie=’+’) then writeln(a+b);
Podstawy Programowania – wersja rozszerzona
strona 11 z 32
If (dzialanie=’-‘) then writeln(a-b);
itd.
Wyjątkiem będzie działanie dzielenia, które będzie wymakało polecenia AND. Działanie
dzielenia ma na klawiaturze 3 znaki: /, \, /. Należy pamiętać, że kompilator rozróżnia znaki z
klawiatury alfa-numerycznej i numerycznej. Dlatego też znak ‘/’ ma dwie wersje.
Polecenia warunkowe stanowią rdzeń każdego programu, dlatego też warto poświęcić
im większą uwagę. Skupmy się teraz na praktycznym zastosowaniu poznanych poleceń. Poza
najprostszym kalkulatorem polecenia warunkowe mają szerokie zastosowanie w różnego
rodzaju interpretatorach
. Spróbujmy napisać taki program.
Program Konsola;
Var
tag,val,s: string;
Begin
Readln(s);
tag:=s[1]+s[2]+s[3]+s[4];
val:=s[6]+s[7]+s[8];
If tag = ‘echo’ then writeln(val);
If tag = ‘reve’ then writeln(val[3]+val[2]+val[1]);
readln();
end;
Jak zapewne widzisz, program ten odpowiada typ samym przy poleceniu „echo”, a
odwrotnością dla „reve”. W tak zapisanym programie, użytkownik może sam wybrać akcję
programu. Taki program nazywamy właśnie interpretatorem.
Zadania
Zad1
Napisz program który będzie dzielił przez 2 tylko liczby parzyste, a nieparzyste mnożył.
Zad2
Napisz program który będzie zamieniał wszystkie liczby na dodatnie.
Zad3
Popraw poniższy kod tak, aby powstało jedno zagnieżdżone polecenie if.
Program Zadanie;
Var
x,y:integer;
Begin
Readln(x);
Readln(y);
If x>y then writeln(‘X jest większe’);
If x<y then writeln(‘X jest mniejsze’);
If x=y then writeln(‘X jest równe Y‘);
end.
3
W dużym uproszczeniu każdy system operacyjny składa się głównie z poleceń typu if.
Podstawy Programowania – wersja rozszerzona
strona 12 z 32
Instrukcja wyboru CASE
Instrukcja case jest to zestaw odpowiednio skonstruowanych warunków typu if. Ma
ona jednak pewne ograniczenie. Mianowicie działa tylko w oparci u zależność równości. Jej
ogólny schemat wygląda następująco:
case zmienna of
wartość1:polecenie;
wartość2:polecenie;
wartość3:polecenie;
end;
Jest to o wiele prostszy sposób zapisu kilku warunków według tego samego schematu
if-then. Dodatkowo tak sformatowany kod może lepiej odzwierciedlać np. menu. Niestety
przy jej pomocy nie sprawdzimy np. która z 3 liczb jest największa.
Zadania
Zad 1
Zamień poniższe warunki if na jedną instrukcję case.
If d=’+’ then a:=a+b;
If d=’-‘ then a:=a-b;
If d=’*’ then a:=a*b;
If d=’/’ then a:=a/b;
Zad 2
Korzystając z zapisanej instrukcji napisz prosty kalkulator.
Podstawy Programowania – wersja rozszerzona
strona 13 z 32
Pętle FOR/REPEAT/WHILE
Pętle jak sama nazwa wskazuje zawierają polecenia, które zapętlają się czyli są
wykonywane aż do jakiegoś warunku. Najprostszą i najczęściej używaną jest pętla FOR. Pętla
ta wykonuje pewne poleceni w oparciu o jakąś liczbę zwiększając jej wartość. Polecenie For
i:=1 to 10 do writeln(i); będzie wypisywać liczby zaczynając od 1 i zwiększając ją o 1 po
każdym wypisaniu. Pętla zakończy działanie gdy liczba ta wyniesie 10. Przyjrzyjmy się
konstrukcji. Pierwszym słowem kluczowym jest słowo FOR. Polecenie to informuje
kompilator o początku pętli. Następnie następuje polecenie przypisania i:=1, która wskazuje
od jakiej wartości pętla zaczyna. Jako aktualnie wykorzystywaną liczbę kompilator będzie
używał zmienną i. Następnie pojawia się jedno z dwóch poleceń. TO albo DOWNTO.
Określają one kierunek pętli, tzn. czy zmienna i ma się zwiększać czy zmniejszać.
Jak już pewnie zauważyłeś przydatna jest tu znajomość języka angielskiego. Ponieważ
większość firm informatycznych ma swoje korzenie w stanach pomoce to tworzenia
produktów (czyli także programów) są w języku angielskim. Zwrot downto tłumaczymy jako
„w dół do”. Tak więc pętla For i:=1 downto 5 do; nigdy się nie zakończy, ponieważ idąc w dół
od jeden nigdy nie natrafimy na 5.
Jeżeli koniec pętli nie zależy od liczby najlepiej użyć pętli warunkowej repeat albo
while. Pętla repeat powtarza daną czynność aż do spełnienia warunku umieszczonego na
końcu. Pętla while wykonuje czynności jeżeli warunek zawarty na początku jest spełniony.
Widzisz różnicę? Pętla repeat zostanie wykonana co najmniej raz, bez względu na
prawdziwość warunku, pętla while najpierw sprawdzi poprawność warunku. A teraz
przykłady:
i:=0;
Repeat
i:=1;
until (i<>1);
i:=0;
while (i=1) doi:=1;
Jak zapewne widzisz pierwsza pętla będzie wykonywana w nieskończoność, natomiast
druga nie zostanie wykonana nigdy. Różnica ta jest bardzo przydatna w czasie komunikacji z
użytkownikiem. Pętli while używa się gdy chce się od użytkownika pobierać dane
określonego typu, np. liczby. Pętli repeat używa się np. w oczekiwaniu na konkretne
zdarzenie.
Powróćmy jeszcze do poruszonego już tutaj tematu kodowania. Przy pomocy pętli for
wygenerujmy klucz kodowy. Niech słowem kluczem będzie ‘Alicja’. Pozbawiamy go
podwójnych liter (‘alicj’). A więc:
program kodowanie;
var
abc:string;
key:string;
tmp:string;
i,j,k:byte;
Podstawy Programowania – wersja rozszerzona
strona 14 z 32
begin
abc:=’abcdefghijklmnopqrstuvwxyz’;
key:=’alicj’;
tmp:=key;
for i:=1 to 26 do
begin
for j:=1 to 5 do
if abc[i]=tmp[j] then k:=j;
if k=0 then key:=key+abc[i] else k:=0;
end;
end;
Po wykonaniu takiego programu otrzymamy zestaw alfabetu (abc) wraz z jego
zakodowaną wersją (key). Teraz wystarczy przy kodowaniu wiadomości podmieniać znaki z
tekstu niezakodowanego na te z kodowanego alfabetu. Spróbuj to zrobić.
Zadania
Zad1.
Napisz program który będzie mnożył podaną liczbę przez 2 aż nie przekroczy ona 26.
Spróbuj użyć różnych pętli.
Zad2.
Napisz program który będzie odczytywał znaki z klawiatury, tak długo aż nie zostanie
podana cyfra.
4
Zaawansowane programy kodujące uwzględniają wielkość liter oraz znaki specjalne. Niekiedy działają
nawet w trybie binarnym łącząc kilka znaków w jeden.
Podstawy Programowania – wersja rozszerzona
strona 15 z 32
Procedury
Procedury są to elementy kodu, które mogą działać niezależnie od całościprogramu.
Podstawową ideą jest możliwość kopiowania całych sekcji bez konieczności sprawdzana
zgodności zmiennych. Najprostszym przykładem jest procedura writeln. Można ją zapisać
jako zbitek procedury write oraz zakończenia linii. Ogólny schemat zapisu procedury wygląda
następująco:
Procedure nazwa (par1: typ; par2: typ);
begin
lista poleceń
end;
Tak zapisaną procedurę należy wstawić przed początkiem kodu programu (pomiędzy
sekcją var a głównym begin. Od tego momentu za każdym razem kiedy wpiszemy jako
polecenie nazwę naszej procedury, zostaną wykonane polecenia w niej zawarte. Procedur
mogą składać się z dowolnej ilości poleceń, które nie wymagają korzystania ze zmiennych
globalnych, czyli głównych zmiennych programu. Zmienne zadeklarowane wewnątrz
procedur nazywamy lokalnymi i są one rozpoznawane tylko wewnątrz procedury. Czas na
wykorzystanie teorii w praktyce. Stwórzmy procedurę wyświetlającą podpis pewnej osoby.
Procedure Podpis(imie: string; nazwisko: string);
Var
Temp: string;
Begin
Temp:=imie[1]+’. ‘+nazwisko;
Write(Temp);
end;
Tak skonstruowana procedura może być użyta dla różnych danych. Przykładowo:
• A. Nowak
• K. Janda
• M. Wiśniewski
Może też być używana wielokrotnie co znacznie skraca ilość kodu potrzebną do
zapisania programu. Dzięki takim zabiegom można znacznie uprościć i skrócić pisanie
programów. Dodatkowo wewnątrz procedur mogą być umieszczane kolejne pod warunkiem,
że ich deklaracja już wcześniej wystąpiła. Przykładowo:
Procedure Linia();
Var
i:byte;
Begin
For i:=1 to 20 do Write(‘–‘);
Writeln();
End;
Podstawy Programowania – wersja rozszerzona
strona 16 z 32
Procedure Podpis(imie: string; nazwisko: string);
Var
Temp: string;
Begin
Temp:=imie[1]+’. ‘+nazwisko;
Linia();
Write(Temp);
Linia();
end;
W ten sposób dzielimy program na podprogramy, które działając niezależnie mogą być
modyfikowane i ulepszane bez znajomości całości kodu, co jest szczególnie przydatne
podczas dużych projektów. Kiedy kilka osób pracuje nad jednym programem może tworzyć
takie właśnie procedury, które potem składa się w gotowy program.
Aby zachować zmiany dokonywane na parametrach procedury należy zadeklarować
taką możliwość. W takim przypadku przed deklaracją parametru należy wpisać słowo
kluczowe var. Informuje to kompilator o tym, że w przypadku poprawnego wykonania
funkcji, powinien nadpisać zmienne globalne, parametrami procedury. Przykładowo:
procedure test(var a:integer);
Begin
a:=2;
end;
begin
c:=3;
test(c);
writeln(c);
end.
Po wykonaniu takiego programu na ekranie otrzymamy „2” zamiast spodziewanego
„3”. W ten sposób po wykonaniu procedury możemy zwrócić dowolną ilość danych. Jest to
wykorzystywane w momentach gdy zwracana wartość składa się z dwóch różnych
elementów. W takim wypadku nie opłaca się tworzyć nowego typu danych. Należy także
pamiętać, że każdy nowy typ deklarowany w programie musi być dostarczony wszystkim
pracującym nad nim osobom.
Zadania
Zad 1.
Przy pomocy procedur napisz kalkulator. Postaraj się wykorzystać pętle, tak aby nie
trzeba było uruchamiać go kilkakrotnie.
Zad 2
Napisz program, który będzie wyświetlał dowolny tekst w ramce. Użyj co najmniej
dwóch procedur.
Zad 3
Popraw poniższy kod, tak aby powtarzające się elementy były procedurami.
Program Kalkulator
Var
x,y,z,i: integer;
d: char;
Podstawy Programowania – wersja rozszerzona
strona 17 z 32
Begin
Write(‘Wtaj. Podaj pierwsza liczbe.’); Readln(x);
Write(‘Podaj druga liczbe.’); Readln(y);
Write(‘Podaj trzecia liczbe.’); Readln(z);
Repeat
Write(‘Podaj pierwsze dzialanie (+/-)’); Readln(d);
Until((d=’+’) OR (d=’-‘));
If d=’+’ then x:=x+y;
If d=’-’ then x:=x-y;
Repeat
Write(‘Podaj drugie dzialanie (+/-)’); Readln(d);
Until((d=’+’) OR (d=’-‘));
If d=’+’ then x:=x+z;
If d=’-’ then x:=x-z;
Write (‘Wynik to: ‘, x);
End.
Podstawy Programowania – wersja rozszerzona
strona 18 z 32
Funkcje
Idea funkcji opiera się na założeniu, że każde zadanie musi dać jakiś wynik. Dlatego też
większość programistów zamienia procedury na funkcje, tak aby po ich wykonaniu otrzymać
potwierdzenie typu boolean (logicznego).
Funkcje Proste
Funkcje, jest to rozbudowana forma procedur. Ogólny schemat deklaracji funkcji
wygląda następująco:
Function Nazwa(Par1: typ; Par2: typ):typ
begin
ciąg poleceń
end;
Jak można łatwo zauważyć, funkcje mają pewien typ. Typ funkcji jest to rodzaj wartości
oddanej do systemu po zakończeniu jej działania. Może on być dowolny, choć najczęściej
spotykany to boolean (logiczny). Funkcje, w przeciwieństwie do procedur, mogą być
używane jako parametry innych funkcji (albo procedur). W ten sposób można łączyć
działanie kilku funkcji według schematu: Jeżeli pierwsza funkcja wykonała się poprawnie,
rozpocznij następną, inaczej wyświetl komunikat błędu. Funkcje są szeroko wykorzystywane
ze względu na możliwość zwracania wartości, bez użycia dodatkowych zmiennych.
Oto kilka przykładów użycia funkcji:
Program Przyklad;
Var
x:string;
Function Podpis(imie: string; nazwisko: string):string;
Var
Temp: string;
Begin
Temp:=imie[1]+’. ‘+nazwisko;
Podpis:=Temp;
end;
Begin
Writeln(‘“B
yć albo nie być” ’,Podpis(‘Wiliam’,’Shakespeare’);
x:=Podpis(‘Jan’,’Nowak’);
Writeln(‘Przekład: ‘,x);
End.
Funkcje Rekurencyjne
Funkcje rekurencyjne są to takie funkcje, które odwołują się do samych siebie.
Najprostszym i najczęściej podawanym przykładem jest silnia. Wyrażenie 5! Oznacza tyle co
5x4x3x2x1. Aby jak najprościej przedstawić to językiem programowania należy zauważyć
pewną zależność. 4x3x2x1=4!, a więc 5!=5x4!, czyli inaczej 5x(5-1)!. W ten sposób opisuje się
funkcje rekurencyjne:
Podstawy Programowania – wersja rozszerzona
strona 19 z 32
A!=
Ax(A-1)!
dla
A>0;
1
dla
A=0;
W języku programowania wyglądałoby to następująco:
Function Silnia(x:integer):integer;
Var
temp:integer;
Begin
If x=0 then temp:=1 else temp:=Silnia(x-1);
Silnia:=temp;
End;
W ten prosty sposób działanie, które należałoby zapisać w pięciu bądź więcej liniach
zmieściliśmy w dwóch poleceniach. Funkcje rekurencyjne z uwagi na krótki kod często
optymalizują (przyspieszają) pracę programu, co przy dużych i skomplikowanych obliczeniach
daje realne korzyści.
Zadania
Zad 1
Napisz kalkulator z wykorzystaniem funkcji. Porównaj kod z kalkulatorem opartym na
procedurach.
Zad 2
Spróbuj opracować funkcję rekurencyjną dla potęgowania.
Podstawy Programowania – wersja rozszerzona
strona 20 z 32
Biblioteki
Biblioteki są to zestawy komend związane z konkretnym rodzajem programu. Do
najpopularniejszych należą DOS oraz CRT. Biblioteka CRT zawiera procedury i funkcje
związane z wyświetlaniem (prezentacją) danych, natomiast biblioteka DOS zawiera wybrane
polecenia MS-DOS.
Aby dołączyć wybraną bibliotekę do swojego programu należy wpisać jej deklarację na
początku programu. Np.:
Program
Przykład;
uses crt;
CRT
Najczęściej używane polecenia biblioteki crt to:
• TextColor(cl: byte)
• TextBackground(cl: byte)
• clrcsr
Polecenie TextColor zmienia kolor wyświetlanego tekstu na jeden z 16 dostępnych.
Jako wartość podaje się liczbę od 0 do 15. Polecenie TextBackground zmienia kolor tła pod
wyświetlanym tekstem. Procedura clrscr czyści ekran z tekstu. No dobrze. Ale jak zmienić
kolor tła na całym ekranie? Jest na to pewien prosty sposób. Najpierw używamy procedury
TextBackground, a następnie polecenia clrscr. W ten sposób cały ekran pokryje nam się
wybranym kolorem. Obydwie procedury są bardzo przydatne ze względu na kontakt z
użytkownikiem. Komunikaty ostrzeżeń mogą być wyświetlane na żółto, a komunikaty błędów
na czerwono.
Dodatkowo dochodzi też funkcja readkey sczytująca znak bezpośrednio z klawiatury,
do daje możliwość tworzenia menu opartego na skrótach klawiszowych. Przykładowo:
procedure menu();
Begin
repeat
writeln(‘NEW [n]’);
writeln(‘Exit [x]’);
c:=readkey;
until(c = ‘x’ OR c = ‘n’);
if c = ‘n’ then New();
end;
Poprzez wykorzystanie funkcji readkey w połączeniu z procedurami koloru oraz ClrScr
można stworzyć przyzwoicie działający program działający dynamicznie. Inną bardzo
przydatną funkcją jest GoToXY(x,y:byte). Przenosi ona kursor na wskazaną pozycję na ekranie
(ekran ma wymiary 80x50). Na takiej właśnie funkcji opiera się słynny arkanoid. Latająca
piłeczka to nic innego niż koło generowane na konkretnej pozycji. W trybie tekstowym
można do tego użyć znaku ‘*’. Jeśli masz pomysł na opracowanie takiego programu jest to
dobry sposób na przećwiczenie tego.
Podstawy Programowania – wersja rozszerzona
strona 21 z 32
DOS
Biblioteka DOS zawiera głównie polecenia związanie z zarządzaniem katalogami jak na
przykład: mkdir – tworzy katalog oraz rmdir – usuwa katalog. Pełna lista dostępnych poleceń
dla różnych bibliotek dostępna jest w Internecie.
Podstawy Programowania – wersja rozszerzona
strona 22 z 32
DLL
Rozszerzenia programów (dll) zawierają funkcje pogrupowane według pewnego
schematu. Można z nich korzystać bez znajomości wszystkich procesów, które w nich
zachodzą. Aby wywołać jakąś funkcję z rozszerzenia należy ją najpierw zadeklarować przed
głównym blokiem programu.
Function My_Func1(); external ‘roz1.dll’;
W ten sposób funkcja ta zostanie zaczerpnięta z rozszerzenia o nazwie roz1.dll w
głównym katalogu programu.
Kod biblioteki DLL różni się niewiele od kodu zwykłego programu. Mianowicie nie
posiada poleceń między właściwym begin - end. Tak więc wszystkie elementy pozostają bez
zmian:
library
uses crt;
var
i:integer;
func_1 (x,y:string):Boolean; export;
begin
…
end;
func_1 (x,y:string):Boolean; export;
begin
…
end;
begin
end.
exports
func1;
func2;
end;
Jak pewnie zauważyłeś po słowie kluczowym end. następuje wylistowanie wszystkich
funkcji eksportowanych poza bibliotekę. Dzieje się tak ponieważ eksportowane funkcje nie
muszą być rozpoznawane po nazwie, ale np. po numerach.
Należy zauważyć, że najbardziej istotną rolę będzie odgrywać to co znajduje się przed
pierwszym begin. Są to przede wszystkim typy i stałe, które muszą być identyczne we
wszystkich komponentach programu. Jeżeli stałym kolorem tła programu jest zielony, musi
on być zapisany także w bibliotece DLL, inaczej wyświetlane elementy będą białe na czarnym
tle. To samo dotyczy wykorzystywanych typów. Biblioteka nie może użyć typu
„Imie = string[20]” jeżeli nie został on zadeklarowany w nagłówku.
5
Nagłówek zaczyna się słowem library (biblioteka), ponieważ nie jest to samodzielny program tylko jego
rozszerzenie.
Podstawy Programowania – wersja rozszerzona
strona 23 z 32
Rekordy i wskaźniki
Rekordy oraz wskaźniki są pewnego rodzaju wprowadzeniem do programowania
obiektowego. Ich ideą jest zastąpienie wielu zmiennych przez jedną złożoną. Różnią się
jednak one sposobem działania oraz deklaracją. Razem dają potężne narzędzie
umożliwiające wykorzystywanie nawet bardzo złożonego oprogramowania na komputerach
o niewielkiej mocy.
Rekordy
Rekordy służą do tworzenia baz danych wewnątrz programów. Typ rekordowy
gromadzi pod sobą kilka zmiennych różnych typów łącząc je z w zestawienie. Takie właśnie
zestawienie nazywamy rekordem. Deklaracja typu rekordowego wygląda następująco:
type
Osoba = record
imie: string[20];
nazwisko: string[20];
wiek: byte;
end;
W ten sposób generujemy sobie nowy typ „osoba”. Każda zmienna typu „osoba”
będzie teraz rekordem zawierającym 3 pola: imie, nazwisko, wiek. Zmienne wewnątrz
rekordu są ze sobą powiązane dzięki czemu mamy pewność, że np. kopiując dane
skopiujemy wszystkie powiązane zmienne. Dodatkowo upraszcza to proces wyszukiwania,
ponieważ nie trzeba porównywać trzech par zmiennych tylko jedną.
Typy rekordowe jako podstawowy element baz danych daje nieograniczone
możliwości. Dzięki nim można tworzyć własne tabele (lista rekordów) oraz kwerendy
(funkcje wyszukująco-sortujące) i raporty w prosty i przejrzysty sposób.
Co ciekawe nic nie stoi na przeszkodzie by typ rekordowy miał pod sobą także typ
rekordowy. Można w ten sposób generować nieskończenie długie listy.
type
Address = record
ul: string[50];
num_dom: btyte;
num_lok: byte;
end;
Osoba = record
imie: string[20];
nazwisko: string[20;
adres_zam: address;
end
W ten sposób można łączyć dane z różnych tabel, tworząc zaawansowaną bazę danych.
Spróbuj w ramach treningu napisać prosty skoroszyt do przechowywania danych
kontaktowych.
6
Jeśli chcesz wiedzieć więcej o kwerendach, poszukaj informacji na temat języka SQL lub MS SQL.
Podstawy Programowania – wersja rozszerzona
strona 24 z 32
Wskaźniki
Idea wskaźników wzięła się z branży rozrywkowej. W tym sektorze istnieje duży nacisk
na jakość graficzną, a przez to na dużą ilość skomplikowanych obliczeń. Wskaźniki mimo iż są
deklarowane tak jak pozostałe zmienne (wyjątkiem jest symbol ^ poprzedzający typ) nie są
fizycznie zalokowane w pamięci. Poza oczywistą deklaracją wskaźnika, dochodzą jeszcze dwa
polecenia: new i disposse. Pomagają one w znaczący sposób obniżyć wymagania sprzętowe
dla danego oprogramowania.
W momencie gdy potrzebujemy jakiejś zmiennej tymczasowej używamy polecenia
new(wskaźnik) i otrzymujemy zmienną pod nazwą wskaźnika. Gdy zmienna przestaje być
potrzebna wydajemy polecenie disposse i przestaje nam ona zajmować pamięć.
Dodatkowym atutem jest fakt, że wskaźniki mogą wskazywać na ten sam obszar
pamięci, co oznacza w praktyce, że zmiana na jednym z nich, od razu daje efekt na
pozostałych. Bardzo często wykorzystuje się tą możliwość w formie pętli. Jeśli chcemy
utworzyć jakąś tabelę, a nie wiemy jak długa będzie używamy wskaźników w połączeniu z
rekordami.
lista = record
val: byte;
next: ^lista
end;
Otrzymujemy tak zapętloną deklarację. W każdym momencie lista może zostać
wydłużona poprzez new(current.next). Oczywiście taka lista nie ma indeksów numerycznych
więc trzeba się po niej poruszać także wskaźnikami: current := current.next
; Warto mieć
jeden dodatkowy wskaźnik na początek listy, jako że jest to lista jednokierunkowa.
7
Wskaźnik currnet wskazuje na obecny obiekt na liście.
Podstawy Programowania – wersja rozszerzona
strona 25 z 32
Przykładowe Programy
Poniżej zamieszczono przykłady rozwiązań niektórych problemów oraz jeden duży
program jako przykład wykorzystania możliwości rozszerzeń DLL.
Kalkulator
Program Kalkulator
Uses crt
Var
x,y,i: integer;
d: char;
Begin
TextColor(10);
ClrScr;
Write(‘Wtaj. Podaj pierwsza liczbe.’); Readln(x);
Write(‘Podaj druga liczbe.’); Readln(y);
Repeat
Write(‘Podaj dzialanie (+/-)’); Readln(d);
Until((d=’+’) OR (d=’-‘));
If d=’+’ then x:=x+y;
If d=’-’ then x:=x-y;
Write (‘Wynik to: ‘, x);
End.
Tworzenie Ścieżki (Katalogów)
function DirCreate(path:string):boolean;
var
tmp:boolean;
s,Stmp:string;
i:integer;
begin
tmp:=false;
s:=path;
tmp:=DirectoryExists(s);
repeat
if s[length(s)] = '\' then
begin
for i:=1 to length(s)-1 do Stmp:=Stmp+s[i];
tmp:=DirectoryExists(s);
end
else
for i:=1 to length(s)-1 do Stmp:=Stmp+s[i];
s:=Stmp;
Stmp:='';
until(tmp = true);
i:=length(s)+1;
s:=s+'\';
Podstawy Programowania – wersja rozszerzona
strona 26 z 32
repeat
while ((path[i+1]<>'\') AND (s<>path)) do
begin
s:=s+path[i+1];
i:=i+1;
end;
if path[i+1]='\' then
begin
mkdir(s);
s:=s+'\';
end;
i:=i+1;
until (s=path);
mkdir(s);
DirCreate:=True;
end;
Menu Główne
procedure MENU(var c:char); export;
begin
clrscr;
writeln('MENU: ');
writeln('Draw (d) ');
writeln('Print (p) ');
writeln('Load (l) ');
writeln('Save (s) ');
writeln('Help (h) ');
writeln('New (n) ');
writeln('Exit (x) ');
writeln;
writeln('Press the choosen key...');
c:=readkey;
end;
Kalkulator Kredytowy
program Kalkulator;
uses crt,dos;
const
//text and titles
headline_text = 'PLAN SPLATY KREDYTU';
//positions and colors
back_defoult = 3;
back_choice = 6;
back_alert = 4;
text_defoult = 11;
text_choice = 14;
text_alert = 12;
hotkey = 15;
pos_alertX = 12;
pos_alertY = 6;
//time menager values
speed = 50;
type
Podstawy Programowania – wersja rozszerzona
strona 27 z 32
kredyt = object
value:double;
time:word;
height:double;
procedure raty(); forward;
procedure malej(); forward;
procedure f(var a:double); forward;
end;
var
tmp:string;
ans:char;
TheCredit:kredyt;
i,j:word;
TableD:array [1..1000] of double;
suma:^double;
function p(a:double; b:word):double;
external '.\liebe.dll';
procedure ramka(x,y:word);
external '.\liebe.dll';
function input(s:string):string;
external '.\liebe.dll';
procedure alert;
external '.\liebe.dll';
procedure kredyt.f(var a:double);
var q:real;
begin
q:=1+height/1200;
a:=value*p(q,time)*(q-1)/(p(q,time)-1);
end;
procedure kredyt.raty();
var total:double;
begin
f(total);
writeln('Wysokosc raty to: ',total:0:2);
TableD[1]:=total;
new(suma);
suma^:=0;
suma^:=TableD[1]*time;
writeln('suma: ',suma^:0:2);
writeln('koszt: ',suma^-value:0:2);
readkey;
end;
procedure kredyt.malej();
var total,may:double;
i:word;
begin
f(total);
for i:=1 to time do
TableD[i]:=total;
may:=total-value/time;
may:=may/time;
for i:=1 to time do
begin
TableD[i]:=TableD[i]+may*((time div 2) - i);
Podstawy Programowania – wersja rozszerzona
strona 28 z 32
end;
gotoxy(1,1);
for i:=1 to time do
begin
writeln(i,': ',TableD[i]:0:2);
delay(speed);
if (i mod 20 = 0) then
begin
writeln('Press any key...');
readkey;
end;
end;
new(suma);
suma^:=0;
for i:=1 to time do
suma^:=suma^+TableD[i];
for i:=1 to 20 do write('=');
writeln;
writeln('suma: ',suma^:0:2);
writeln('koszt: ',suma^-value:0:2);
readkey;
end;
function choose(s:string):char;
external '.\liebe.dll';
function to_value(tmp:string; var d:double):boolean;
var kod:word;
begin
kod:=0;
val(tmp,d,kod);
if kod<>0 then
begin
if tmp[kod]=',' then tmp[kod]:='.';
end
else
begin
to_value:=true;
exit;
end;
kod:=0;
val(tmp,d,kod);
if (kod = 0) and (d<>0) then
to_value:=true
else
to_value:=false;
end;
function to_noumber(tmp:string; var b:word):boolean;
var kod:word;
begin
kod:=0;
val(tmp,b,kod);
if kod<>0 then
begin
if tmp[kod]=',' then tmp[kod]:='.';
end
else
begin
to_noumber:=true;
exit;
Podstawy Programowania – wersja rozszerzona
strona 29 z 32
end;
kod:=0;
val(tmp,b,kod);
if (kod = 0) and (b<>0) then
to_noumber:=true
else
to_noumber:=false;
end;
function month(a:word):word;
begin
if a = 0 then month:=12 else month:=a;
end;
procedure doc();
var plik:text;
dd,mm,rr,h,m,s,ss,WTF,i,kod:word;
tmp,tmp2:string;
name:string;
data:text;
procedure linia;
var i:word;
begin
for i:=1 to 45 do write(plik,'-'); writeln(plik,''); //Linia poprzeczna
end;
begin
getdate(rr,mm,dd,WTF);
gettime(h,m,s,ss);
str(dd,tmp);
name:=tmp;
str(mm,tmp);
name:=name+'.'+tmp;
str(rr,tmp);
name:=name+'.'+tmp;
assign(data,'.\data.ini');
reset(data);
read(data,tmp);
if tmp='nodir' then mkdir('.\Dokumenty');
if tmp<>name then
begin
mkdir('.\Dokumenty\'+name);
rewrite(data);
write(data,name);
close(data);
end;
Podstawy Programowania – wersja rozszerzona
strona 30 z 32
str(h,tmp);
name:=name+'\'+tmp;
str(m,tmp);
name:=name+'.'+tmp;
str(s,tmp);
name:=name+'.'+tmp+'.txt';
assign(plik,'.\Dokumenty\'+name);
rewrite(plik);
tmp2:=input('Podaj poczatek:');
tmp:=tmp2[1]+tmp2[2];
val(tmp,dd,kod);
tmp:=tmp2[4]+tmp[5];
val(tmp,mm,kod);
tmp:=tmp2[7]+tmp[8];
val(tmp,rr,kod);
linia;
begin //TYLKO RAZEM!!
write(plik,'|',headline_text:((43+length(headline_text)) div 2));
for i:=1 to (45-((43+length(headline_text)) div 2)-2) do
write(plik,' ');
writeln(plik,'|');
end;
linia;
if TableD[2]>0 then
for i:=1 to TheCredit.time do
begin
str(i,tmp);
writeln(plik,'|',tmp+' rata:
':15,'|',TableD[i]:14:2,'|',dd:4,'-',month(mm+i mod 12):2,'-',rr:2,'|');
//Dane tabeli
end
else
for i:=1 to TheCredit.time do
begin
str(i,tmp);
writeln(plik,'|',tmp+' rata:
':15,'|',TableD[1]:14:2,'|',dd:4,'-',month(mm+i mod 12):2,'-',rr:2,'|');
end;
linia;
writeln(plik,'|','Suma:':30,'|',suma^:10:2,'|');
linia;
writeln(plik,'|','Calkowity koszt:':30,'|',suma^-
TheCredit.value:10:2,'|');
linia;
writeln(plik,'|','Wygenerowano na dzien:':30,'|',dd:4,'-',mm:2,'-',rr:2,'|');
linia;
writeln(plik,'|','Powered by Michal Wolinski':43,'|');
linia;
close(plik);
{repeat
ans:=choose('Wydrukować?');
until(ans in ['t','n']);
if ans='t' then print(plik);}
end;
Podstawy Programowania – wersja rozszerzona
strona 31 z 32
begin
textcolor(text_defoult);
textbackground(back_defoult);
clrscr;
writeln('Program wylicza system splaty rat(ich wysokosc w kolejnych
miesiacach).');
REPEAT
clrscr;
writeln('Wcisnij "x" aby zakoäczy†.');
writeln('Wcisnij "s" aby rozpocza†.');
repeat
ans:=readkey;
until(ans in ['s','x']);
if ans='x' then exit;
gotoxy(1,1);
writeln('':40);
write('':40);
repeat
gotoxy(1,1);
write('Podaj wysokos† kredytu: ');
readln(tmp);
if NOT to_value(tmp,TheCredit.value) then
begin
alert();
clrscr;
end;
until(to_value(tmp,TheCredit.value));
repeat
gotoxy(1,2);
write('Podaj czas(w miesiacach): ');
readln(tmp);
if NOT to_noumber(tmp,TheCredit.time) then
begin
alert();
clrscr;
gotoxy(1,1);
write('Podaj wysokosc kredytu: ',TheCredit.value:0:2);
end;
until(to_noumber(tmp,TheCredit.time));
repeat
gotoxy(1,3);
write('Podaj oprocentowanie: ');
readln(tmp);
if NOT to_value(tmp,TheCredit.height) then
begin
alert();
clrscr;
gotoxy(1,1);
writeln('Podaj wysokosc kredytu: ',TheCredit.value:0:2);
write('Podaj czas(w miesiacach): ',TheCredit.time);
end;
until(to_value(tmp,TheCredit.height));
repeat
ans:=choose('Czy raty sa stale?');
until(ans in ['n','x','t']);
clrscr;
if ans='t' then
TheCredit.raty
else if ans='n' then
TheCredit.malej;
delay(1000);
Podstawy Programowania – wersja rozszerzona
strona 32 z 32
ans:=choose('Czy przygotowac dokument?');
if ans='t' then doc();
dispose(suma);
UNTIL(ans='x');
end.