Pascal7, Podstawy programowania


Konspekt wykładu „Podstawy programowania”

sem.3 i 4, WSAiZ, kier. Informatyka

opr. Tomasz Bajorek

  1. Wstęp:

Do 1954 roku - język maszynowy (Eniac, Mark I- USA)

Kodowanie instrukcji procesora w postaci ciągu liczb dwójkowych (elementarny rozkaz i dane)

lata 50-te - zastąpienie kodów operacji nazwami mnemotechnicznymi

np. mnożenie MPY (multiply)

język symboliczny - assembler

ASSEMBLER - także program tłumaczący na kod maszynowy (wewnętrzny) DISSASSEMBLER - tłumaczenie odwrotne, stosowany do dziś - np. oprogramowanie interfejsów pomiarowych, wprowadzanie danych z pomiarów i ich obróbka komputerowa

CECHY:

Etap przejściowy - tzw. systemy automatycznego programowania - „sztuczki” programistyczne pozwalające na prostsze wykonywanie operacji zmiennopozycyjnych, obliczanie funkcji itp., prostsze programowanie lecz spowolnienie ok. 5-krotne programów, zarzucone z uwagi na sprzętowe rozwiązanie problemów operacji zmiennoprzecinkowych

Języki wysokiego poziomu

1954 - FORTRAN - języki tzw. wysokiego poziomu Fortran (Formula Translator)

(kod maszynowy i assembler to niski poziom - bliższy procesorowi)

Zapis operacji w sposób łatwiejszy, zrozumiały i dobrze kontrolowany przez programistę

Po stworzeniu kodu programu w języku następuje proces translacji (tłumaczenia, kompilacji) na język wewnętrzny komputera.

Problemy:

Języki wysokiego poziomu po etapie początkowym stały się maszynowo niezależne z powodu wielu wersji translatorów (programów kompilujących) REWOLUCJA - wiele wersji FORTRANU (standard Fortran4, F77 Laheya)

W kolejnych latach - obfitość języków programowania Inne języki wysokiego poziomu

COBOL - dla przedsiębiorstw, język prawie naturalny (ang) MULTIPLY - mnożenie, ADD - dodawanie

Do dziś specjaliści potrzebni (w USA 500 $/godz za zmiany daty w 2000)

BASIC, LOGO - prostota, interpretacja w odróżnieniu od kompilacji, tłumaczenie „na bieżąco” każdej instrukcji a nie programu w całości

PASCAL, C, C+, C++ - języki strukturalne z elementami tzw. programowania obiektowego

OOP (Object Oriented Programming) - języki zorientowane obiektowo (PROLOG, Visual Basic, Turbo Vision dla Pascala, Delphi -Object Pascal, Java)

Klasyfikacja języków programowania:

CO TO JEST JĘZYK PROGRAMOWANIA ?

DANE - reprezentują świat rzeczywisty lub abstrakcyjny i opis jego obiektów

OBIEKTY mają przypisany zbiór operacji - działań na tych obiektach

Alfabet języka - skończony zbiór znaków.

Słowo - skończony ciąg znaków alfabetu

Język formalny- zbiór słów nad określonym alfabetem

Język programowania - zbiór konwencji i umów umożliwiających komunikatywność (zrozumiałość) umów (dla kompilatora).

Określa się przy tym:

syntaktykę (składnię) języka - zbiór reguł opisujących poprawne konstrukcje językowe

semantykę - zasady interpretacji tych konstrukcji

np.

Przykład:

CZERWONY JECHAŁEM BYŁEŚ. - zła składnia

KULISTA ŚCIANA PŁUCZE AUTOBUS. - poprawna składnia ale niepoprawna semantycznie (znaczeniowo)

Błędy składniowe - np. zapomnieć słowa kluczowego instrukcji lub je przekręcić

Błędy semantyczne - zły typ danych, licznik pętli nie jest typu całkowitego, j=0; k=1/j (dzielenie przez zero)

Jeżeli ponadto:

- syntaktyka pozwala na analizę poprawności konstrukcji językowych

- opis języka obejmuje pragmatykę (zalecenia do używania poprawnych struktur)

to język formalny może być językiem programowania.

Definicja algorytmu

ALGORYTM - skończony zbiór ściśle określonych zasad rozwiązywania pewnej klasy zadań

ALGORYTM - (przepis) - specyfikacja ciągu operacji, które w wyniku działania na wejściowy zbiór obiektów dają zbiór wynikowy

Opis algorytmu składa się z:

- opisu obiektów podlegających przetwarzaniu

- opisu czynności wykonywanych na tych obiektach

OBIEKTY - dane

dana = (nazwa danej, wartość danej)

deklaracje, definicje - opisy obiektów

instrukcje - czynności na obiektach

program - algorytm zapisany w języku programowania

podprogram - wyodrębniona część programu (ze względu na czytelność lub wielokrotne użycie) posiadająca wyodrębnioną nazwę i sposób wymiany informacji z pozostałymi jego częściami

deklaracja podprogramu - opis podprogramu

instrukcja wywołania podprogramu - wykonanie, zastosowanie podprogramu wewnątrz programu głównego lub innego podprogramu

kod źródłowy - tekst programu w języku programowania (plik tekstowy pas)

kompilacja - tłumaczenie kodu źródłowego na wykonywaną postać binarną, ładowalną (plik exe) - odrębny proces

interpretacja - tłumaczenie kolejnych instrukcji w trakcie procesu wykonywania

0x01 graphic

Przetwarzanie programu użytkowego

W przypadku przetwarzania programu, wymagającego wykorzystania programów bibliotecznych, uzyskany po procesie kompilacji kod wynikowy należy poddać procesowi łączenia, konsolidacji (linkowanie) z kodami dołączanymi a następnie wykonać kod ładowalny.

Sposoby pisania programu:

- program źródłowy utworzony dowolnym edytorem tekstu - kompilacja - konsolidacja (link - łączenie z podprogramami bibliotecznymi (modułami)

lub

Zatarcie granic między programowaniem a użytkowaniem- pakiet też jest programem i programując korzystamy z programu, podobnie EXCEL - programowanie arkusza to korzystane (wykonanie programu) a po części tworzenie pliku wynikowego metodami programistycznymi: (wyrażenia według konwencji EXCELA, makro w konwencji VBA itp.

Co świadczy o przydatności i skuteczności języka programowania

  1. Dobra notacja, przejrzystość, prostota (łatwość przyswojenia zasad)

  2. Jednoznaczność zapisu

  3. Funkcjonalność

- zbyt szeroka to też niedobrze bo niebezpieczeństwo dwuznaczności zapisów (grube dukumentacje)

- stąd dołączanie modułów 9ułatwia kontrolę błędów i wyłączenie wielorakości syntaktyki)

  1. Weryfikacyjność - test błędów, czasem te cechy w sprzeczności bo deklaracje explicite poszerzają strukturę programu ale ułatwiają kontrolę zmiennych, np. błąd literowy w nazwie obiektu bez deklaracji to nowa zmienna a za deklaracjami błąd braku deklaracji

  2. Elastyczna opisywalność obiektów: np. data to liczby, operacje liczbowe dopuszczalne ale dzielenie jest bezsensowne

  3. Czytelność struktury programu

  4. Dostępność

  5. Cena

  6. Efektywność - skuteczność kompilacji, szybkość programu wynikowego

  7. Dokumentacja

PASCAL (autor Nicklaus Wirth, lata 70-te)

Cechy:

2. ŚRODOWISKO zintegrowanego pakietu programowania języka TURBO PASCAL (7.0)

2.1. URUCHAMIANIE

turbo [plik.pas] wersja trybu rzeczywistego DOS

tpx [plik.pas] wersja trybu chronionego DOS

Menu operacji

ALT+wyróżniona litera nagłówka menu

Wybór okna edycyjnego

ALT+nr okna

Okno OUTPUT⇔ edytor

ALT+F5

Otwarcie pliku

F3

Zapis pliku

F2

Kompilacja

ALT+ F9 (F9)

Wykonanie

CRTL+F9

Step over (krokowo)

F8

Trace into

F7

Watch

śledzenie wartości wyszczególnionych zmiennych

Breakpoints

„pułapki” - miejsca chwilowego zatrzymania programu w celu

Pomoc

F1

2.2 BŁĘDY

Błędy procesu kompilacji

- zatrzymanie kompilacji i krótki opis błędu - ang.

Najczęstsze błędy:

Opis

Opis angielski

nieznany identyfikator

unknown identifier

zła składnia

syntax error

niezgodność typów

type mismatch

błąd w wyrażeniu

error in expression

nieoczekiwany koniec pliku

unexpected end of file

”;” oczekiwany

”;” expected

”)” oczekiwany

”)” expected

”do” oczekiwany

”DO” expected

itd....

Błędy wykonania polegają zazwyczaj na:

Kombinacja CTRL+Break umożliwia przerwanie „zawieszonego” programu

Błędy kompilacji :syntaktyczne (składniowe)

Błędy wykonania :semantyczne

2.3 EDYTOR TP

Stan­dardowo pliki pisane w języku TP mają rozszerzenie pas.

Operacje edytorskie mogą się odbywać:

- przez menu,

- przez klawisze nawigacyjne,

- CTRL+znak lub CTRL+znak1(Q lub K) a następnie znak2.

Operacja

Klawisze

przesunięcie kursora o znak lub wiersz

strzałki nawigacyjne

przewinięcie tekstu o stronę

PgUp, PgDn

skok kursora na początek, koniec wiersza

Home, End

skok na początek, koniec okna

CTRL+Home, CTRL+End

skok na początek, koniec tekstu

CTRL+PgUp, CTRL+PgDn

zmiana trybu: wstawianiezastępowanie

Insert

wstawienie pustego wiersza

CTRL+N

ENTER w trybie wstawiania

usunięcie znaku

Delete lub Backspace

usunięcie słowa

CTRL+T

usunięcie wiersza

CTRL+Y

usunięcie reszty wiersza

CTRL+Q,Y

zaznaczenie początku bloku

CTRL+K,B

zaznaczenie końca bloku

CTRL+K,K

zaznaczenie słowa jako bloku

CTRL+K,T

ukrycie bloku

CTRL+K,H

kopiowanie bloku w miejsce kursora

CTRL+K,C

przesunięcie bloku w miejsce kursora

CTRL+K,V

usuwanie bloku

CTRL+K,Y

wcięcie (indent) bloku

CTRL+K,I

cofanie wcięcia bloku

CTRL+K,U

zapis bloku do pliku

CTRL+K,W

wczytanie bloku z pliku

CTRL+K,R

szukanie ciągu znaków(find)

CRTL+Q,F

szukanie i zastąpienie(replace)

CTRL+Q,A

kontynuacja szukania lub zastępowania

CTRL+L

2.4 SKŁADOWE JĘZYKA

2.4.1. Struktura blokowa programu i podprogramów

PROGRAM nazwa (parametry);

0x08 graphic

0x08 graphic
0x08 graphic

USES ... deklaracje modułów ;

LABEL ... deklaracje etykiet ;

CONST ... definicje stałych ;

TYPE ... definicje typów ;

0x08 graphic
VAR ... deklaracje zmiennych ;

definicje funkcji i podprogramów

0x08 graphic

BEGIN

pierwsza instrukcja ;

druga instrukcja ;

....

....

ostatnia instrukcja ;

END.

Instrukcje wykonywane są kolejno od pierwszej do ostatniej, pod warunkiem, że charakter instrukcji nie stanowi inaczej (np. „pętle”, skoki, przekazanie wykonania do podprogramu itp.)

Nagłówek programu (opcjonalny- czyli nieobowiąkowy):

- słowo kluczowe PROGRAM i identyfikator (nazwa) do 255 znaków

- parametry programu - komunikacja z otoczeniem, nazwy plików wejścia i wyjścia (pliki standardowe INPUT oraz OUTPUT)

Sekcja deklaracji:

- 5 typów, czasami istotna kolejność, np. wcześniej deklaracja typu a potem zmiennej tego typu

BEGIN - początek sekcji instrukcji (wykonywalnej)

END - koniec sekcji instrukcji

kropka kończy program

INSTRUKCJE - oddzielane średnikami.

2.4.2 ALFABET JĘZYKA

- duże i małe litery alfabetu łacińskiego (rozróżnialne tylko dla stałych tekstowych)

- cyfry 0 do 9

- jednoznakowe symbole specjalne:

+ - * / = < > [ ] .
, : ; ( ) { } ^
# $ @

Wieloznakowe symbole specjalne:

dwuznakowe

< > < = > = := . .

- słowa kluczowe (nie wszystkie)

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

2.4.3. IDENTYFIKATORY (NAZWY)

Identyfikatory - nazwy złożone z ciągu znaków

Identyfikatory standardowe:

typów danych - Boolean, Char, Integer, Real, String i inne

stałych - False, True, Maxint

funkcji - Abs, Sin, Cos, Sqr, Sqrt, Exp i inne

procedur - Read, Readln, Reset, Rewrite, Write, Writeln

plików - Input, Output

Identyfikatory własne nadaje użytkownik dla:

programu, obiektów (zmiennych), typów, podprogramów, modułów.

Zasady tworzenia identyfikatorów własnych:

Ciąg znaków (liter, cyfr, znaku podkreślenia _ )

Nie wolno używać spacji wewnątrz nazwy

Pierwszym znakiem musi być litera

Długość w standardzie języka nieograniczona (255)

Nierozróżnialne małe i duże litery

Przykłady:

A, C5, XY20, cyfra, e22, delta, dzienD, IDENT1, ident1

To_jest_dlugi_identyfikator_lecz_poprawny

Uwaga1: IDENT1 i ident1 są traktowane jako ten sam obiekt.

Uwaga2: 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 sin.

2.4.4 SEPARATORY

Separator nagłówka programu, deklaracji i instrukcji

; {średnik}

Opcjonalne separatory symboli języka

spacja, 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.

2.4.5 KOMENTARZ

W programie komentarz (własne uwagi lub opis działań) ma postać ciągu znaków w nawiasach klamrowych

{ ............................. }

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 nadmiar powoduje zmniejszenie przejrzystości.

2.5 STAŁE (literały)

2.5.1 Stałe liczbowe

A. całkowite

ciąg cyfr bez spacji (ew. poprzedzony znakiem + lub -)

Przykłady: -1 23234 012 0 -1234

$F12A - liczba w zapisie szesnastkowym

zakres : -32768 do 32767 dla typu integer

-2.15 mld do 2.15 mld (dla typu Longint)

B. rzeczywiste

  1. Zapis stałopozycyjny

{±}m.n

gdzie m i n całkowite, dodatnie

UWAGA: kropka rodziela część całkowitą i ułamkową

Przykłady : 2.333 - 456.0

NIE WOLNO: .45 brak części całkowitej

WOLNO: 234.

  1. Zapis zmiennopozycyjny (wykładniczy)

[-]m[.n]0x01 graphic
[-]k

gdzie m,n,k całkowite dodatnie

Litera E (lub e) interpretuje pomnożenie liczby dziesiętnej m .n przez 10 do potęgi k.

Notacja wykładnicza przydatna dla liczb bardzo dużych i bardzo małych.

Przykłady:

0.1 -4.5 34.678 -1.5e-12 3.4E7 {tzn. 3.4.107=34000000}

UWAFA: Zakresy dla różnych podtypów różne !!!!

2.5.2 Stałe łańcuchowe

Przykłady: 'Turbo Pascal' 'a'

2.5.3 Stałe logiczne

- wartości logiczna nadawane zmiennym i wyrażeniom typu logicznego Boolean

True - prawda False - fałsz

3. DEKLARACJE I DEFINICJE

3.1. Deklaracja modułów.

Modułu są to biblioteki procedur i funkcji, które po zadeklarowaniu modułu można wykorzystać w programie.

uses lista_nazw_modułów ;

np. uses graph;

uses crt,printer;

3.2. Deklaracja etykiet.

Etykiety służą do zaindeksowania instrukcji programu w celu np. wykonania programowego skoku do instrukcji o danej etykiecie - rzadko stosowane.

label lista_etykiet ;

np. label 12, 45;

label alfa, beta, gamma;

3.3. Definicje stałych (nazw literałów) i ich wartości.

Stałe są obiektami o wartości niezmiennej w trakcie wykonywania programu.

const nazwa1=wartość1; nazwa2=wartość2 ; ....;

np. const e=2.71828;

prawda = true;

nazwisko = 'Kowalski';

3.4. Definicje typów.

Definicja typu jest nazwanym opisem typu (najczęściej niestandardowego), używanym potem w deklaracjach zmiennych.

type nazwa1 = opis_typu1 ; nazwa2 = opis_typu2 ; .....;

np. type

dni_tyg = (po,wt,sr,cz,pi,so,ni); {typ wyliczeniowy}

ck = 1..20; {typ okrojony}

napis = string[30];

........

3.5. Deklaracje zmiennych.

var lista nazw zmiennych: typ1;

lista nazw zmiennych: typ2; ....;

Przykładowe deklaracje:

var

x, suma, v15: integer;

wynik1: real;

znak: char;

nazwisko, imie: napis; {wcześniej opisany typ}

czy_jest: boolean;

var alfa : dni_tyg; {zdefiniowany wyżej}

x , y , z : ck; {jak wyżej}

3.6. Definicje procedur i funkcji.


Procedure nazwa (......);

.....

.....

end;

Function nazwa(....):typ;

........

.......

end;


Funkcje i procedury mają strukturę blokową identyczną jak program główny, ale o tym później.

4.TYP DANYCH

Każda stała, zmienna, wyrażenie lub funkcja jest pewnego typu - pozwala to uniezależnić się w pewnym stopniu od fizycznej reprezentacji obiektów w pamięci komputera.

Typ określa:

Typy oferowane przez język PASCAL:

Typ standardowy - zbiór wartości i operacje określone w języku.

Typy strukturalne (złożone) - wprowadzone w związku z praktycznymi potrzebami reprezentacji danych.

UWAGA:

W sekcji instrukcji wolno używać tylko takich identyfikatorów, których znaczenie określono w sekcji deklaracji

4.1 KLASYFIKACJA TYPÓW

0x01 graphic

4.2 TYPY PROSTE (porządkowe + rzeczywiste)

4.2.1 Typy porządkowe

A.Typy całkowite

Typ Integer

Używamy w deklaracji zmiennych:

var x,y:Integer;

zakres zależy od implementacji - dla IBM PC

stała Maxint = 215-1 = 32767

Inne typy całkowite:

Shortint

-128 do 127

Word

0 do 65535

Byte

0 do 255

Longint

-2.15 mld do 2.15 mld

B. Typ znakowy Char

Zmienne tego typu mogą przyjmować wartości pojedynczego znaku

Przykład:

var znak:char;

begin

znak:='c'; {operacja przypisania - nadania wartosci}

.....

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)

np. var

forma: (prostokat, kwadrat, elipsa, okrag);

dzien: (po, wt, sr, cz, pi, so, ni);

Dopuszcza się wykonywania na obiektach typu wyliczeniowego operacji przypisania, np.:

forma := elipsa;

dzien := po;

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) po

ord(wt) 1

Dla obiektów tego typu nie wolno stosować operacji arytmetycznych oraz wykorzystywać zmiennych tego typu w instrukcjach read/write.

E. Typ okrojony

Typ okrojony wyznacza podzbiór dowolnego typu porządkowego (boolean, char, integer, wyliczeniowy) zwanego typem bazowym:

w1 .. w2

gdzie w1 w2

np. var

zakres: 1..10;

cyfra: '0'..'9';

dni_wolne: so .. ni;

Operacje i funkcje obowiązują jak dla typu bazowego.

4.2.2 Typy rzeczywiste

Typy rzeczywiste - używane dla zmiennych przyjmujących wartość liczbową rzeczywistą

Typ Real - podstawowy

Tabela typów rzeczywistych:

Nazwa

Najmn. wart.dod.

Najw.wartość

Real

2.9e-39

1.7e38

Single

1.5e-45

3.4e38

Double

5.0e-324

1.7e308

Extended

3.4e-4932

1.1e4932

UWAGA na zakresy: opcje pakietu dopuszczają brak sprawdzania zakresów - Options - Compiler - Runtime errors - Range checking - włączone lub nie.

4.3 TYP ŁAŃCUCHOWY String

Typ łańcuchowy zmiennej umożliwia przechowywanie wartości typu tekstowego (do 255 znaków)

STRING - do 255 znaków

STRING[20] - deklaracja max. długości

Przykład:

....

var nazwisko:String[20];

begin

nazwisko:='Kowalski'; {przypisanie wartości tekstowej do zmiennej}

writeln(nazwisko:15); {wydruk na ekranie w polu o szerokości 15 z wyrównaniem do prawej}

....

4.4 TYPY STRUKTURALNE - zmienne mogące zawierać wiele wartości (tablice, rekordy, obiekty, zbiory) - omówione zastaną później

UWAGA: PAMIĘĆ: Char - 1 bajt, Integer - 2 bajty, Real - 6 bajtów inne więcej.

Przykład:

PROGRAM DEKLARACJE;

TYPE

nasz = (a,b,c,d,e);

napis_krotki: string [5];

VAR

litera: char;

godzina, minuta, sekunda: integer;

ilosc, suma: real;

napis_tytulowy : string;

etykieta: napis_krotki;

litera : nasz;

BEGIN

Jeszcze nie umiemy wykonywać akcji

END.

5. INSTRUKCJE

5.1 Klasyfikacja instrukcji

0x01 graphic

5.2 Instrukcja przypisania

Zmiennym nadawane są wartości w trakcie wykonywania programu przy pomocy instrukcji przypisania:

identyfikator zmiennej := wyrażenie;

:= dwuznakowy operator przypisania

W instrukcji przypisania zmiennej o identyfikatorze z lewej strony znaku przypisania nadawana jest wartość obliczonego wyrażenia.

UWAGA2: obowiązek zgodności typów zmiennej i wyrażenia (z wyjątkami: np. zmiennej typu real można przypisać wartość wyrażenia typu integer)

Przykład:

Program wartosci;

const

EXP = 2.71828;

PI = 3.1415926;

FRAZA = 'Koniec danych';

SYMBOL = ':=' ;

var

Litera: Char;

Godzina, Minuta, Sekunda: Integer;

Ilosc, Suma: Real;

Napis_Tytulowy: String;

begin

Godzina := 12 ;

Minuta := 23 ;

Litera := 'C' ;

Ilosc := 56.87E4;

Napis_Tytulowy := FRAZA ;

Minuta := 24

end.

W powyższym przykładzie zmiennym nadano wartości stałe, brak operacji matematycznych, brak wprowadzania danych i wyprowadzania wyników. Aby nadać zmiennym wartości obliczane na podstawie innych zmiennych należy użyć po prawej stronie instrukcji przypisania wyrażeń odpowiedniego typu.

5.3 Wyrażenia

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 i nawiasów (okrągłych).

Najprostsza postać wyrażenia to stała lub zmienna

W stała

W zmienna

Bardziej skomplikowane wyrażenia zawierają operatory i funkcje.

Definicja rekurencyjna (czyli definiowanie przez samą siebie):

W W operator W

Ponadto używamy nawiasów w celu zmiany hierarchii działań

5.3.1 Operatory

Operatory arytmetyczne:

- jednoargumentowe

zmiana znaku,

+ powielenie znaku,

- dwuargumentowe

- multiplikatywne

mnożenie,

/ dzielenie (rzeczywiste),

ƒdivƒ dzielenie całkowite (oba operatory całkowite)

ƒmodƒ reszta z dzielenia całkowitego

- addytywne

+ dodawanie

- odejmowanie.

Przykłady:

7/2   3.5

4/2  2.0

6.5/2    3.75

7  div  2  3

17 mod -5  2

3.5*x-6/(4-x)+5

Kolejność wykonywania operacji określają następujące reguły:

- nawiasy są najważniejsze (od najbardziej wewnętrznych),

- ważność operatorów:

1. jednoargumentowe,

2. multiplikatywne,

3. addytywne.

- dla operatorów tej samej wagi - kolejność od lewej do prawej,

- jeżeli w wyrażeniu są tylko argumenty całkowite i nie ma dzielenia rzeczy­wistego 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 +,

Np:

nazwisko := 'Kowalski';

tekst_1 := 'Pan ' + nazwisko ;

w rezultacie zmienna tekst_1 przyjmie wartość tekstową 'Pan Kowalski '.

5.3.2 Funkcje standardowe

Istnieje możliwość użycia w wyrażeniu funkcji standardowych (kontekst identyczny jak zmienne proste) w postaci:

nazwa_funkcji (argument)

Argumentem może być wyrażenie odpowiedniego typu. Zestaw funkcji standar­dowych przedstawia tabela 9.1.

TABELA Funkcje standardowe

Znaczenie

Nazwa funkcji

Typ funkcji

Typ argumentu

Przykład

Wartość bezwzględna

abs

całkowity

rzeczywisty

całkowity

rzeczywisty

abs(-2) 2

Pierwiastek kwadratowy

sqrt

rzeczywisty

rzeczywisty

sqrt(5.45)

Kwadrat

sqr

rzeczywisty

rzeczywisty

sqr(x-5)

ex

exp

rzeczywisty

rzeczywisty

exp(-x/2)

Logarytm naturalny

ln

rzeczywisty

rzeczywisty

ln(2x-4)

Sinus

sin

rzeczywisty

rzecz. (radiany)

sin(3alfa)

Cosinus

cos

rzeczywisty

rzecz. (radiany)

cos(beta/2)

Arcus tangens

arctan

rzeczywisty

rzeczywisty

arctan(fi)

Liczba =3.1415...

pi

rzeczywisty

brak

sin(30*pi/180)

Część całkowita

int

rzecz.

Całkowity

Rzeczywisty

int(2.5) 2.0

Część ułamkowa

frac

rzecz.

Całkowity

Rzeczywisty

frac(3.6) 3.0

Zaokrąglenie

Round

całkowity

Rzeczywisty

round(3.6) 4

Obcięcie

Trunc

całkowity

Rzeczywisty

trunc(3.6) 3

Znak następny

Succ

znakowy

znakowy

succ ('g') 'h'

Znak poprzedni

pred

znakowy

znakowy

pred(' j ') ' i '

znak o podanym kodzie ASCII

chr

znakowy

całkowity

chr(49) '1'

kod znaku

ord

całkowity

znakowy

ord('1') 49

Długość tekstu

length

łańcuchowy

całkowity

length(`alfa') 4

W wyrażeniach istotne są wszelkie ograniczenia obszaru określoności, np. użycie ln(-3), sqrt(-5.0) spowoduje błędy wykonania.

Brak w języku funkcji standardowej potęgowania, stąd stosuje się :

x4 xxxx lub sqr (x)sqr (x) lub sqr (sqr (x))

xy exp (yln (x))

Należy zwrócić uwagę na możliwość wystąpienia przekroczenia dopuszczalnych zakresów przy obliczeniach.

Przykład prawidłowo zapisanego wyrażenia:

(5xx-2sin (x)+1.5e-5)/(abs (sqrt (x+2)-2)+exp (1.5ln (y)))

W przypadku zastosowania instrukcji:

zmienna := funkcja(zmienna);

obliczana jest wartość funkcji a następnie uaktualniana wartość zmiennej, np.

...

x := 5;

x := 2+sqr(x);

x:=x+5; {

...

w wyniku uzyskuje się x = 27.

Możliwe jest stosowanie także funkcji, które umieszczone są w innych modułach, np. Crt, Graph i in.. Ich użycie wymaga odpowiedniej deklaracji modułu, np.:

uses crt ;

Użyteczne są funkcje biblioteczne modułu crt:

- cls procedura czyszczenia ekranu

bezparametrowa funkcja readkey, która służy do wczytania z klawiatury jednego znaku,

- funkcja logiczna keypressed, która służy do sprawdzenia naciśnięcia dowolnego klawisza.

UWAGA

2*x a nie 2x

5.3.3 Wyrażenia logiczne

Wyrażeniem logicznym może być:

1. stała

true prawda 1 - logiczne

false fałsz 0 - logiczne

2. zmienna - typ boolean

3. relacja - porównanie w sensie liczbowym lub tekstowym (wg kolejności alfabetycznej) wg schematu:

wyrażenie1  operator arytmetyczny  wyrażenie2

Relacja ma wartość logiczną true lub false. Operatorami relacji są:

                      (różny)

Przykładowo: x12 2

(4x+1.5) 30.7

nazwisko 'F' nazwiska od F do końca alfabetu

Uwaga: Operatory , , należy używać ostrożnie 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:

- jednoargumentowym

not (negacja) np. not (i < 5) not obecny

- dwuargumentowymi

and (iloczyn logiczny -„i”) np. (x > 0) and (x < 3)

or (suma logiczna -„lub”) np. (x < 0) or (x > 100)

xor (różnica symetryczna - suma modulo2)

argument 1

argument 2

and

or

xor

0

0

0

0

0

1

0

0

1

1

0

1

0

1

1

1

1

1

1

0

W operacji przypisania wartości zmienej logicznej musi zachodzić zgodność typów.

Przykład:

var

zwolniony, obecny: boolean;

ocena: real;

begin

...

zwolniony := (ocena >= 4.5) and obecny;

...

end.

5.4 Instrukcje czytania i wyprowadzania danych

Do wprowadzenia (standardowo z klawiatury) wartości zmiennej w trakcie wykonania programu służy procedura:

0x01 graphic
[(lista zmiennych)];

Uwaga: w nawiasach klamrowych { } -elementy do wyboru, w nawiasach kwadratowych [ ] - elementy opcjonalne

Np. readln (x1, x2, x3, y);

read(x);

Liczby podajemy polami oddzielonymi co najmniej jedną spacją, przecinkiem lub w osobnych wierszach.

Jeżeli wpiszemy za dużo liczb to nadwyżka jest pamiętana dla następnej instrukcji read, natomiast w instrukcji readln czytane jest tyle ile potrzeba 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).

Procedurą wyprowadzania danych (standardowo na ekran) jest:

0x01 graphic
[ (lista elementów) ];

Po wykonaniu instrukcji write kursor pozostaje na końcu wiersza zaś po writeln następuje zmiana wiersza. Elementami listy są stałe, zmienne i wyrażenia wraz z opcjonalnym określeniem formatu wyprowadzenia o postaci:

  W:m   wyrażenie całkowite określające szerokość pola (liczba znaków), dla liczb typu real m 8,

  W:m:n     m - jak wyżej, n - liczba cyfr po kropce dziesiętnej (tylko typ real).

Przykłady:

begin

x := -21.546;

y := 'Napis=';

writeln(x); -2.154600000E+01

writeln(x:8); -2.2E+01

writeln(x:10:3); -21.546

writeln(y:10, 'TurboPascal':12); Napis= TurboPascal

end.

5.5 Reguły graficzne tworzenia schematów blokowych

Start i stop

0x01 graphic

Operacje wejścia i wyjścia

0x01 graphic

Instrukcja wykonawcza (proces) Blok decyzyjny

0x01 graphic

Łącznik stronicowy

0x01 graphic

6. Turbo Pascal instrukcje warunkowe, instrukcje iteracyjne

6.1. Instrukcje warunkowe

6.1.1 Instrukcja if ( jeśli)

Postać skrócona:

if WB then Instrukcja;

„jeśli” „to”

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śli” „to” „w przeciwnym przypadku”

postać skrócona postać pełna

0x01 graphic

Wykonywane jest badanie warunku:

- jeśli WB = true to wykonywana jest Instrukcja_1,

- jeśli WB = false to wykonywana jest Instrukcja_2.

Instrukcja może być tzw. instrukcją złożoną (sekwencji):

begin

ciąg instrukcji

end;

Instrukcje wewnętrzne if mogą także być innymi instrukcjami if.

Przykład:

if (x = 0) then begin

y := y+5;

writeln(y:10:3)

end

else writeln('x jest ujemne');

6.1.2 Instrukcja wyboru - case

Postać instrukcji:

case w of

s1,...,sn : Instrukcja_1;

sn+1,...,sm : Instrukcja_2;

....

[ else Instrukcja_k ]

end;

w - wyrażenie selektor typu porządkowego (całkowitego, znakowego),

s - stałe wyboru (etykiety wyboru) w możliwej postaci:

s; - pojedyncza wartość,

s1,...,sn - lista wartości,

s1 .. s2 - zakres wartości.

Działanie instrukcji polega na obliczeniu wartości wyrażenia w i w zależności od wyniku wykonywana jest instrukcja (także złożona) odpowiadająca wartości (wartościom, zakresowi) stałej wyboru.

Instrukcja w opcjonalym bloku po else wykonywana jest dla wartości niewystępującej wcześniej. W listach wyboru można powtarzać te same wartości.

Przykład:

case miesiac of

2: dni := 28;

4, 6 , 9, 10: dni := 30;

1..12: dni := 31; {lub else dni := 31}

end ;

6.2. Instrukcje iteracyjne

6.2.1 Instrukcja for (dla)

for Z := Wi1 0x01 graphic
Wi2 do Instrukcja;

Z - zmienna sterująca (prosta lub indeksowana), typu porządkowego (np. całkowitego lub znakowego).

Wi1 i Wi2 - wyrażenia tego samego typu

Wersja z to Wersja z downto

0x01 graphic

Wartość zmiennej sterującej zmienia się od Wi1 do Wi2 narastająco (to) lub malejąco (downto), z krokiem 1 w przypadku zmiennej całkowitej lub co znak w wypadku zmiennej typu char.

Np. x := 0;

for i := 1 to 3 do x := x+5; {po trzykrotnie wykonanej iteracji
x 15}

Instrukcja for jest stosowana gdy z góry znana jest liczba powtórzeń. Wewnątrz iteracji nie wolno zmieniać wartości zmiennej sterującej.

Instrukcją wewnętrzną może być inna instrukcja for (zagnieżdżanie iteracji), także instrukcja złożona. Poniżej przykład programu wyprowadzającego 10 wierszy po 4 gwiazdki w wierszu.

var i: integer;

j: char;

begin

for i := 1 to 10 do

begin

writeln;

for j := 'a' to 'd' do write('')

end

end .

6.2.2 Instrukcja while (dopóki)

while  WB  do  Instrukcja;

Działanie instrukcji polega na powtarzaniu wykonywania instrukcji dopóki wyrażenie logiczne WB posiada wartość true. Wartość ta jest sprawdzana każ­dorazowo przed wykonaniem instrukcji.

Istnieje zatem konieczność wykonania w instrukcji (także złożonej) operacji wpływającej na wartość wyrażenia logicznego. Jeśli błędny warunek spowoduje nieskończoną pętlę możemy przerwać program kombinacją klawiszy CTRL+Break.

0x01 graphic

Rys. Schemat blokowy instrukcji WHILE

Przykładowy fragment programu oblicza sumę liczb parzystych od 2 do 100:

i := 2;

suma := 0;

while i <= 100 do

begin

suma := suma + i;

i := i + 2;

end;

6.2.3 Instrukcja repeat / until (powtarzaj .. aż)

repeat

ciąg instrukcji

until WB ;

Ciąg instrukcji wewnętrznych 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ę na końcu pętli, stąd jest ona conajmniej raz wykonywana. Podobnie jak w iteracji while jedna z instrukcji powinna mieć wpływ na wartość wyrażenia logicznego.

0x01 graphic

Rys. Schemat blokowy instrukcji REPEAT / UNTIL

Przykład: x := 3;

repeat

x := x + 5;

until x 100;

Przykład:

program p6a;

uses crt;

var

a, b, c, delta, x1, x2: real;

begin

clrscr;

writeln('Podaj wspolczynniki rownania kwadratowego');

write('a=');

readln(a);

write('b=');

readln(b);

write('c=');

readln(c);

delta := b*b-4*a*c;

if delta < 0 then writeln('Brak pierwiastkow rzeczywistych')

else

if delta = 0 then writeln('Pierwiastek pojedynczy x1=x2=', -b/2/a)

else

begin

delta := sqrt(delta);

x1 := (-b-delta)/2/a;

x2 := (-b+delta)/2/a;

writeln('Pierwiastki rownania kwadratowego');

writeln('x1=':20,x1:10:2);

writeln('x2=':20,x2:10:2)

end;

readln;

end .

program p6b;

var x: 1..7;

begin

writeln('WHILE');

x := 1;

while x = 7 do

begin

write('witaj');

x := x+1;

end;

writeln;

writeln('FOR');

for x := 1 to 7 do write('witaj');

writeln;

writeln ('REPEAT');

x := 1;

repeat

write('witaj');

x := x+1;

until x 7;

readln;

end .

program p6c;{Przydzielenie do grup wiekowych}

uses crt;

var

wiek: integer;

begin

ClrScr;

repeat

write( 'Podaj wiek:' );

readln(wiek);

case wiek of

0..20 : writeln('GRUPA I');

21..40 : writeln('GRUPA II');

41..60 : writeln('GRUPA III')

else writeln('GRUPA IV')

end;

until wiek = 0;

write('Nacisnij ENTER');

readln

end .

7. Typ tablicowy

7.1 Definicja typu

Typy standardowe mają swoje nazwy (boolean, real, integer, char...), istnieje też możliwość wprowadzenia unikalnych nazw dla własnych typów i ich definiowania:

nazwa typu = opis typu

np. type

dni_tyg = (po,wt,sr,cz,pi,so,ni);

ck = integer;

ck1 = 1..20;

nap = string[30];

var

dzien, dn: dni_tyg;

i, j, k: ck;

l, m, n: ck1;

nazw, imie: nap;

Na nazwach typów nie wolno przeprowadzać operacji. Definicja typu musi poprzedzać użycie go w deklaracji zmiennej.

7.2 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 tablicy (macierzy) w sensie matematycznym.

array[ lista typów indeksów ] of typ składowych

typ porządkowy typ dowolny

np. var

tab1: array [ 0..50 ] of integer;

tab2,tab3: array [1..20, 1..30] of real;

tablica: array [ boolean, zakres, dzien_tyg] of char;

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).

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

...

tab1 := tab2;

...

end.

natomiast inne operacje dokonywane być mogą tylko na składowych jeśli są dozwolone dla ich typu.

Przykład 1:

...

tab1[2,3] := 0.1; {nadanie wartości elementowi tablicy}

for i := 1 to 20 do tab2[1, i]:= 0.0; {wypełnianie pierwszego wiersza zerami}

for i := 1 to 20 do tab2[i, i]:= i/2; {wypełnianie przekątnej głównej wartościami 0.5 1 1.5 itd.}

for i := 1 to 20 do

for k:= 1 to 20 do tab2[i, k]:=1 {wypełnianie całej tablicy stałą wartością}

for i := 1 to 20 do

begin

for k:= 1 to 20 do write(tab2[i,k]:4:2);

writeln

end; {wydruk na ekranie całej tablicy}

...

Przykład 2:

type dni_tyg = (po, wt, sr, cz, pi, so, ni);

wek = array[dni_tyg, boolean] of real;

var x: wek;

begin

...

x[po, true] := 10.2;

writeln(x[wt, false]/100:20:5);

if x[sr,false] > 3e2 then writeln(' W srode za duzo ');

...

end .

Przykład 3:

type opis= (nazw, imie);

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 .

7.3 Typ rekordowy - record

Typ rekordowy jest typem strukturalnym o strukturze jednowymiarowej i o skła­dowych dowolnych typów, które nazywają się polami:

Opis typu:

record

lista_nazw_pól_1: typ1;

lista_nazw_pól_2: typ2;

........

end;

np.

type

data = record

rok: 1900..2100;

mies: 1..12;

dzien: 1..31;

end;

type student = record

nazw: string[20];

imie1, imie2: string[15];

data_ur: data;

mezczyzna: boolean;

rodzenstwo: array[1..5] of string[15]

end;

Do pól rekordu istnieje dostęp bezpośredni, odwołanie do pola zmiennej odbywa się przez nazwę zmiennej rekordowej i nazwę pola, oddzielonych kropką:

nazwa_zmiennej . nazwa_pola [. ew_nazwa_pola_składowego ...]

np.

student . nazw := 'Kowalski';

if student . data_ur . rok < 1975 then ...

UWAGI:

W jednym typie rekordowym wszystkie pola muszą mieć różne nazwy.

Na zmiennych całościowych jedyną dopuszczalną operacją jest przypisanie, na zmiennych składowych można dokonywać operacji dopuszczalnych dla ich typu.

Zmienne rekordowe można zgromadzić w tablicy, np.:

var grupa: array[1..30] of student; {wcześniej zdefiniowany typ}

lub

var grupa: array[1..30] of record

pole1: typ1;

pole2: typ2;

...

end;

begin

...

grupa[1]. nazw := 'Nowak';

if grupa[2]. data_ur. rok < 1975 then writeln(grupa[3]. rodzenstwo[1]:20);

...

end .

7.4. Instrukcja wiążąca - with

Instrukcja with upraszcza zapis dostępu do pól rekordu. Odwołanie w instrukcji (także złożonej) może nastąpić bezpośrednio do nazw pól wymienionych w liście zmiennych, bez wyspecyfikowanej nazwy zmiennej całościowej.

with lista_zmiennych_rekordowych do Istrukcja;

Przykład 1:

var zespolona: record

rzecz, uroj: real

end;

begin

with zespolona do

begin

rzecz := 2.5;

uroj := 1.0

end;

...

end .

Przykład 2:

program p11a;

uses crt;

var k, dzien: 1..31;

miesiac: 1..12;

rok: 1900..2000;

begin

clrscr;

write('Podaj dzien:');

read(dzien);

write('Podaj miesiac:');

read(miesiac);

write('Podaj rok:');

readln(rok);

clrscr;

writeln(dzien:72, ':', miesiac:2, ':',rok:4);

for k := 1 to dzien do writeln(k:4);

end .

Przykład 3:

program p11b;

uses crt;

type osoba= record

nr: integer;

nazw: string[30];

end;

var

j: 1..10;

student: osoba;

grupa: array[1..10] of osoba;

begin

clrscr;

writeln('Wczytanie danych do tablicy');

with student do

for j := 1 to 10 do

begin

write('Podaj numer: ');

readln(nr);

write('Podaj nazwisko: ');

readln(nazw);

grupa[ j ] := student

end

.....

end .

Jeżeli rekordy znajdują się w tablicy, np.

var osoba: record

nazwisko:string;

imie:string:

wiek:0..100

end;

grupa: array [1..30] of osoba;

to dostęp do pola pojedynczego rekordu tej tablicy może się odbyć w postaci przykładowej

writeln (grupa[5].nazwisko );

12. Turbo Pascal - procedury, funkcje, pliki

12.1. Procedury i funkcje

Stosowanie procedur i funkcji (podprogramów) umożliwia rozbicie złożonego cią­gu operacji na mniejsze struktury. Zwiększa ono czytelność programu.

Podprogra­my mogą mieć strukturę hierarchiczną a zatem kolejna procedura może być defi­niowana we „wnętrzu” innej.

Zadaniem funkcji jest obliczenie pojedynczej wartości zaś procedura wykonuje sekwencję działań i może wyprowadzać wiele obliczonych wartości.

Definicja procedury i funkcji umieszczana jest w części deklaracyjnej programu głównego (także innej procedury lub funkcji):


procedure nazwa (parametry formalne);

definicje, deklaracje

begin

....

akcje

....

end;

function nazwa (parametry formalne): typ;

definicje, deklaracje

begin

....

nazwa := wyrażenie;

....

end;


Zmienne deklarowane wewnątrz procedury lub funkcji maja zasięg lokalny, tzn. obowiązuję jedynie w ich wnętrzu i niedostępne są po zakończeniu ich wykonania.

Parametry formalne służą do przekazywania danych. Deklaracje parametrów są oddzielane średnikami, każda deklaracja składa się z listy zmiennych i nazwy typu. Poprzedzające listę słowo var określa przekazanie danych przez zmienną, jego brak przekazanie danych przez wartość. Przykładowe nagłówki procedury i funkcji:

procedure alfa (nr, liczba1: integer; var log: boolean);

function ff (x1, x2: real): real;

Wywołanie (wykonanie) funkcji w programie dokonywane jest jak użycie zmiennej. Wywołanie procedury jest odrębną instrukcją. W nawiasie wpisujemy ar­gumenty (parametry aktualne), których liczba i typ muszą odpowiadać liczbie para­metrów formalnych.

Na przykład:

y := z + ff ( 10.5, zm11); {wywołanie funkcji}

alfa (5, 4, jest); {wywołanie procedury}

Przekazanie przez wartość traktowane jest jako nadanie wartości początkowej zmiennej lokalnej, w momencie zakończenia podprogramu parametr formalny przestaje istnieć, wartość argumentu nie zostaje zmieniona. Argumenty mogą być stałymi, zmiennymi bądź wyrażeniami.

Przekazanie przez zmienną może przenieść wartość do procedury (wejście), po jej zakończeniu powoduje zwrot nowej wartości do programu wywołującego procedurę. Parametry aktualne przekazujące przez zmienną muszą być identyfikatorami (naz­wami) zmiennych.

Poniższy program tabelaryzuje wartości funkcji opisanej przedziałami, w 21 pun­ktach zakresu (0.0, 2.0):

program tabela1;

uses crt;

var i: 0..20;

function fun(x: real): real; {definicja funkcji}

var xkw: real;

begin

xkw := x*x;

if x := 0.5 then fun := 0.2xkw-x+0.1

else fun := xkw/(xkw-0.1)

end; {koniec definicji funkcji}

begin {początek programu głównego}

clrscr;

writeln;

writeln('Tabela wartosci funkcji':45);

writeln;

writeln('x':30, 'f(x)':20);

for i := 0 to 20 do

begin

writeln(i:12, i0.1:20:3, fun(i0.1):20:5) {wywołanie funkcji

w instrukcji wyjścia}

end;

repeat until keypressed

end .

12.2. Typ plikowy

Plik w pojęciu Turbo Pascala jest ciągiem elementów tego samego typu, odwzo­rowującym fizyczny zbiór danych gromadzonych w pliku DOS-u w pamięci zew­nętrznej. Dostęp do pliku jest sekwencyjny, tzn. dostępny jest tylko jeden element określony przez aktualne położenie wskaźnika, zaś inne elementy mogą być udos­tępniane tylko po wykonaniu pewnych operacji na pliku (np. przesuwanie wskaź­nika). Rozmiar pliku jest dynamiczny. Zmienną typu plikowego można kojarzyć ko­lejno z różnymi plikami dyskowymi. Plik może mieć dowolny typ składowych oprócz pliku. Definicja typu plikowego ma postać:

type nazwa = file of typ; plik elementowy (zdefiniowany)

type nazwa = file; plik blokowy (niezdefiniowany)

type nazwa = text; plik tekstowy (predefiniowany)

Przykład:

type

osoba = record

nazw: string[30];

imie: string[30]

end;

grupa = file of osoba;

var

student: osoba;

gr1, gr2, gr3: grupa;

begin

...

end.

Dla całościowych zmiennych plikowych możliwe są jedynie niektóre operacje DOS-u, natomiast na składowych możemy wykonywać operacje w zależności od typu składowych.

W pliku zdefiniowanym zapis dokonuje się w postaci binarnej a w tekstowym nawet elementy liczbowe zapisywane są jako tekst.

Obsługa plików wymaga:

 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.

12.3. Operacje plikowe

W poniższej tabeli przedstawiono podstawowe operacje plikowe, w których użyto określeń:

f - nazwa zmiennej plikowej,

Wt - wyrażenie tekstowe,

W - wyrażenie odpowiedniego typu,

Z - nazwa zmiennej.

TABELA 12.1. Podstawowe operacje plikowe

Operacja

Typ

Zapis

Przykład

skojarzenie

procedura

assign (f , Wt)

assign(gr1,'C:\DANE\gr.dt');

otwarcie do odczytu

procedura

reset (f);

reset (gr1);

otwarcie do zapisu

procedura

rewrite (f);

rewrite(gr2);

dopisanie (na końcu pliku!)

procedura

append (f);

append (gr2);

zamknięcie pliku

procedura

close (f);

close(gr3);

detekcja końca pliku

funkcja logiczna

eof (f)

if eof(gr1)= true then ...

odczyt

procedura

read (f,Z1,..,Zn);

read(gr1, student.nazw);

zapis

procedura

write(f, W);

write(gr2, nazwisko);

Uwagi:

Po otwarciu do odczytu wskaźnik ustawia się na początku pliku,

Otwarcie nowego pliku powoduje utworzenie pustego pliku,

Gdy eof(f) = true - wskaźnik znajduje się na końcu pliku,

Gdy po reset okaże się że eof(file) = true to plik jest pusty,

Po przeczytaniu elementu następuje przesunięcie wskaźnika do następnego elementu

Instrukcja writeln istnieje tylko dla pliku typu tekstowego

- zapis dopuszczalny 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ę wcześniejszego przykładu z użyciem procedury oraz zapisu tabeli funkcji do pliku tekstowego:

program tabela2;

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 := xx;

if x = 0.5 then f := 0.2xkw-x+0.1

else f := xkw/(xkw-0.1);

if f < 0 then wsk := '' else wsk := '+'

end;

begin {początek akcji programu}

assign(plik, 'c:\tp\moje\fun.txt'); {skojarzenie pliku}

rewrite(plik); {otwarcie pliku do zapisu}

clrscr;

writeln;

writeln('Tabela wartosci funkcji':45);

writeln;

writeln('x':30, 'f(x)': 20);

for i := 0 to 20 do

begin

oblicz(i0.1, y, w); {wywołanie procedury}

writeln(i:12, i0.1:20:3, y:20:5, w:3);

writeln(plik, i:12, i0.1:20:3, y:20:5); {zapis do pliku}

end;

close(plik); {zamknięcie pliku}

repeat until keypressed

end .

Poniższe przykłady ilustrują wykorzystanie bardziej złożonych struktur i algorytmów:

Przykład programu wyznaczania maksimum i minimum wartości losowych

program maksimum;

uses crt;

var x : array[1..100] of real;

i, k : 1..100;

max, min : real;

begin

clrscr;

randomize;

for i := 1 to 20 do begin

for k := 1 to 100 do

x [k] := random (256*256-1) / (256*256-1);

{wyznaczenie maksimum i minimum}

max := x [1];

min := x [1];

for k := 2 to 100 do

if x [k] > max then max := x [k ];

if x [k] < min then min := x [k ];

writeln( 'max=' , max:12:5, 'min=' : 10 , min:12:5);

end;

repeat until keypressed

end.

SORTOWANIE

Prosty algorytm sortowania

1 przebieg

12  5 11  4  7  2 ZMIANA 1

  5 12 11  4  7  2

 5 12 11  4  7  2 ZMIANA 2

 4 12 11  5  7  2

 4 12 11  5  7  2 ZMIANA 3

 2 12 11  5  7  4

2 przebieg

 2 12 11  5  7  4 ZMIANA 4

 2 11 12  5  7  4 ZMIANA 5

 2  5 12 11  7  4

 2  5 12 11  7  4 ZMIANA 6

 2  4 12 11  7  5

3 przebieg

 2  4 12 11  7  5 ZMIANA 7

 2  4 11 12  7  5 ZMIANA 8

 2  4  7 12 11  5 ZMIANA 9

 2  4  5 12 11  7

4 przebieg

 2  4  5 12 11  7 ZMIANA 10

 2  4  5 11 12  7 ZMIANA 11

 2  4  5  7 12 11

5 przebieg

 2  4  5  7 12 11 ZMIANA 12

 2  4  5  7 11 12

liczba analiz 0x01 graphic

Sortowanie bąbelkowe

1 przebieg

12  5 11  4  7  2 ZMIANA 1

 5 12 11  4  7  2 ZMIANA 2

 5 11 12  4  7  2 ZMIANA 3

 5 11  4 12  7  2 ZMIANA 4

 5 11  4  7 12  2 ZMIANA 5

 5 11  4  7  2 12

2 przebieg

 5 11  4  7  2 12

 5 11  4  7  2 12 ZMIANA 6

 5  4 11  7  2 12 ZMIANA 7

 5  4  7 11  2 12 ZMIANA 8

 5  4  7  2 11 12

 5  4  7  2 11 12

3 przebieg

 5  4  7  2 11 12 ZMIANA 9

 4  5  7  2 11 12

 4  5  7  2 11 12 ZMIANA 10

 4  5  2  7 11 12

 4  5  2  7 11 12

 4  5  2  7 11 12

4 przebieg

 4  5  2  7 11 12

 4  5  2  7 11 12 ZMIANA 11

 4  2  5  7 11 12

 4  2  5  7 11 12

 4  2  5  7 11 12

 4  2  5  7 11 12

5 przebieg

 4  2  5  7 11 12 ZMIANA 12

 2  4  5  7 11 12

 2  4  5  7 11 12

 2  4  5  7 11 12

 2  4  5  7 11 12

 2  4  5  7 11 12

6 przebieg

 2  4  5  7 11 12

 2  4  5  7 11 12

 2  4  5  7 11 12

 2  4  5  7 11 12

 2  4  5  7 11 12

 2  4  5  7 11 12

Sortowanie bąbelkowe skrócone

1 przebieg

12  5 11  4  7  2 ZMIANA 1

 5 12 11  4  7  2 ZMIANA 2

 5 11 12  4  7  2 ZMIANA 3

 5 11  4 12  7  2 ZMIANA 4

 5 11  4  7 12  2 ZMIANA 5

 5 11  4  7  2 12

2 przebieg

 5 11  4  7  2 12

 5 11  4  7  2 12 ZMIANA 6

 5  4 11  7  2 12 ZMIANA 7

 5  4  7 11  2 12 ZMIANA 8

 5  4  7  2 11 12

3 przebieg

 5  4  7  2 11 12 ZMIANA 9

 4  5  7  2 11 12

 4  5  7  2 11 12 ZMIANA 10

 4  5  2  7 11 12

4 przebieg

 4  5  2  7 11 12

 4  5  2  7 11 12 ZMIANA 11

 4  2  5  7 11 12

5 przebieg

 4  2  5  7 11 12 ZMIANA 12

 2  4  5  7 11 12

Prosty algorytm sortowania

Program sortowanie;

type

TOsoba = record { rekord zawierajcy dane osobowe }

Imie :string[ 25 ];

wiek :integer;

end;

const

MaxOsob = 30;

var

ListaOsob : array [ 1..MaxOsob ] of TOsoba;

i,n : integer;

znak : char;

Zamienic : boolean;

pom : TOsoba; {zmienna pomocn. do sortowania tablicy }

begin

..........

..........

{sortowanie}

repeat {wybor sposobu sortowania }

writeln('Wybierz porzadek sortowania:');

writeln(' I - imie');

writeln(' W - wiek');

readln(znak);

znak := UpCase(znak);

case znak of

'I' :writeln('Lista posortowana wedlug imion');

'W' :writeln('Lista posortowana wedlug wieku');

else writeln('Lista nieposortowana');

end;

{sortowanie }

for i := 2 to IloscOsob do

begin

n := i;

repeat

case znak of

'I' : Zamienic := ListaOsob[ n ].Imie< ListaOsob[ n -1 ].Imie;

'W' : Zamienic := ListaOsob[ n ].Wiek < ListaOsob[ n-1 ].Wiek;

end;

if Zamienic then

begin

pom := Listaosob[ n ];

Listaosob[ n ] := ListaOsob[ n -1 ];

Listaosob[ n -1 ] := pom;

end;

Dec(n); {zmniejsza n o 1}

until (n = 1) or (not Zamienic);

program Tab_rekordow;

{ Ilustracja uzycia typu rekordowego }

{ program wczytuje liste osob z klawiatury do tablicy rekordow,

a nastepnie wyswietla liste posortowana wedlug zadanego pola }

type

TOsoba = record { rekord zawierajacy dane osobowe }

Imie : string[ 25 ];

Nazwisko : string[ 25 ];

Adres : string[ 25 ];

wiek : integer;

Plec :(K,M);

end;

const

MaxOsob = 30; {maks. rozmiar tablicy z danymi osobowymi}

var

ListaOsob : array [1..MaxOsob ] of TOsoba;

IloscOsob : integer;

NastepnaOsoba :boolean;

Znak :char;

i,n :integer;

Zamienic :boolean;

Pom :TOsoba; { zmienna pomocn. do sortowania tablicy }

begin

{wczytanie danych z klawiatury }

NastepnaOsoba := true;

Iloscosob := 0;

while NastepnaOsoba and (IloscOsob <= MaxOsob) do

0x08 graphic
begin

inc(IloscOsob);

with ListaOsob [ IloscOsob ] do

0x08 graphic
begin

write('Imie: '); readln(Imie);

write('Nazwisko: '); readln(Nazwisko);

write('Adres: '); readln(Adres);

write('Wiek: '); readln(Wiek);

write('Plec[ K/M ]:'); readln(znak);

0x08 graphic
case znak of

'K','k':Plec := K

else

Plec := M

end;

end;

0x08 graphic
if IloscOsob < MaxOsob then

0x08 graphic
begin

writeln;

write('Chcesz podac nastepna osobe? [ T/N ]');

readln(Znak);

NastepnaOsoba := UpCase(Znak)='T';

end;

end;

{sortowanie i wyswietlanie listy }

0x08 graphic
repeat

{wybor sposobu sortowania }

writeln('Wybierz porzadek sortowania:');

writeln(' I - imie');

writeln(' N - nazwisko');

writeln(' W - wiek');

writeln(' P - Plec');

readln(znak);

znak := UpCase(znak);

case znak of

0x08 graphic
'I' :writeln('Lista posortowana wedlug imion');

'N' :writeln('Lista posortowana wedlug nazwisk');

'W' :writeln('Lista posortowana wedlug wieku');

'P' :writeln('Lista posortowana wedlug plci');

else

writeln('Lista nieposortowana');

end;

{sortowanie }

0x08 graphic
for i := 2 to IloscOsob do

begin

n := i;

0x08 graphic
repeat

0x08 graphic
case znak of

'I' : Zamienic := ListaOsob[ n ].Imie < ListaOsob[ n -1 ].Imie;

'N': Zamienic := ListaOsob[ n ].Nazwisko < ListaOsob[ n -1 ].Nazwisko;

`W': Zamienic := ListaOsob[ n ].Wiek < ListaOsob[ n -1 ].Wiek;

'P' : Zamienic := ListaOsob[n ].Plec < ListaOsob[ n -1 ].Plec;

end;

if Zamienic then

0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
begin

0x08 graphic
pom := Listaosob[ n ];

Listaosob[ n ] := ListaOsob[ n -1 ];

Listaosob[ n -1 ] := pom;

end;

Dec(l);

until (n = 1) or (not Zamienic);

end;

{ wyswietlenie listy }

for i := 1 to IloscOsob do

begin

write(i:2,' ',ListaOsob[ i ].Imie,' ',ListaOsob[ i ].Nazwisko,

'lat ',ListaOsob[ i ].Wiek,' ');

if ListaOsob[ i ].Plec=K then write('K ')

else write(' M ');

writeln(' Adres', Listaosob[ i ].Adres);

end;

writeln;

write('Wyswietlic powtornie [ T/N ]:');

readln(znak);

until Upcase(znak) = 'N';

end.

program Tab_rek_pliki;

{Ilustracja uzycia typu rekordowego wraz z zapisem/odczytem listy z dysku}

{ program w czytuje liste osob z klawiatury do tablicy rekordow, a nastepnie wyswietla liste posortowana wedlug zadanego pola }

uses crt;

type

TOsoba = record { rekord zawierajcy dane osobowe }

Imie :string[ 25 ];

Nazwisko :string[ 25 ];

Adres :string[ 25 ];

wiek :integer;

Plec :(K,M);

end;

const

MaxOsob = 30; { maksymalny rozmiar tablicy z danymi osobowymi }

var

ListaOsob : array [ 1..MaxOsob ] of TOsoba;

IloscOsob : integer;

NastepnaOsoba : boolean;

Znak :char;

i,n : integer;

Zamienic : boolean;

pom :TOsoba; {zmienna pomocn. do sortowania tablicy }

F : file of TOsoba;

Nazwa : string;

begin {początek programu}

Clrscr;

0x08 graphic
repeat

writeln('0 - wprowadzanie danych z klawiatury');

writeln('1 - odczyt danych z dysku');

write('Twoj wybor [ 0/1 ]:');readln(znak);

until (znak = '0') or (znak = '1');

if znak = '0' then

0x08 graphic
begin { wczytanie danych z klawiatury }

NastepnaOsoba := true;

Iloscosob := 0;

while NastepnaOsoba and (IloscOsob <= MaxOsob) do

begin

inc(IloscOsob);

with ListaOsob[ IloscOsob ] do

begin

write('Imie: '); readln(Imie);

0x08 graphic
write('Nazwisko: '); readln(Nazwisko);

write('Adres: '); readln(Adres);

write('Wiek: '); readln(Wiek);

write('Plec [ K/M ]:');

0x08 graphic
repeat

readln(Znak);

Znak := UpCase(Znak);

until (Znak = 'K') or (Znak = 'M');

0x08 graphic
case znak of

'K': Plec := K

else Plec := M

end;

end;

if IloscOsob < MaxOsob then

0x08 graphic
begin

writeln;

writeln('Wprowadziles do tej pory ',IloscOsob,' osob');

write('Chcesz podac nastepna osobe? [ T/N ]');

0x08 graphic
repeat

readln(Znak);

Znak := UpCase(Znak);

until (Znak = 'T') or (Znak = 'N');

NastepnaOsoba := Znak='T';

end;

end;

writeln;

write('Zapisac wprowadzone osoby na dysku [ T/N ]? ');

0x08 graphic
repeat

readln(Znak);

Znak := UpCase(Znak);

until (Znak = 'T') or (Znak = 'N');

if znak = 'T' then

begin { zapis listy na dysk }

write('Podaj nazwe pliku:'); readln(Nazwa);

if Nazwa <> '' then

begin

Assign(F,Nazwa);

Rewrite(F);

for i := 1 to IloscOsob do write(F,ListaOsob[ i ]);

Close(F);

end;

end;

end { koniec wprowadzania z klawiatury }

else { odczyt z dysku }

0x08 graphic
begin

0x08 graphic
repeat

write('Podaj nazwe pliku:');

readln(Nazwa);

until Nazwa < > ``;

Assign(F,Nazwa); {przypisanie zmiennej plikowej pliku dyskowego}

Reset(F); {otwarcie pliku do odczytu}

while not EOF(F) and (IloscOsob < MaxOsob) do

0x08 graphic
begin

inc(IloscOsob);

read(F,ListaOsob [Iloscosob ]);

end;

Close(F); {zamknięcie pliku}

end; { koniec odczytu z dysku }

{sortowanie i wyswietlanie listy }

0x08 graphic
repeat {wybor sposobu sortowania }

writeln('Wybierz porzadek sortowania:');

writeln(' I - imie');

writeln(' N - nazwisko');

writeln(' W - wiek');

writeln(' P - Plec');

readln(znak);

znak := UpCase(znak);

case znak of

'I' :writeln('Lista posortowana wedlug imion');

'N' :writeln('Lista posortowana wedlug nazwisk');

'W' :writeln('Lista posortowana wedlug wieku');

'P' :writeln('Lista posortowana wedlug plci');

else writeln('Lista nieposortowana');

end;

{sortowanie }

for i := 2 to IloscOsob do

0x08 graphic
begin

n := i;

0x08 graphic
repeat

case znak of

'I' : Zamienic := ListaOsob[ n ].Imie< ListaOsob[ n -1 ].Imie;

'N' :Zamienic := ListaOsob[ n ].Nazwisko< ListaOsob[n -1]. Nazwisko;

'W' : Zamienic := ListaOsob[ n ].Wiek < ListaOsob[ n-1 ].Wiek;

'P' : Zamienic := ListaOsob[ n ].Plec < ListaOsob[ n -1 ].Plec;

end;

if Zamienic then

0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
begin

pom := Listaosob[ n ];

Listaosob[ n ] := ListaOsob[ n -1 ];

Listaosob[ n -1 ] := pom;

end;

Dec(n);

until (n = 1) or (not Zamienic);

end;

{ wyswietlenie listy }

for i := 1 to IloscOsob do

0x08 graphic
begin

write(i:2,' ',ListaOsob[ i ].Imie,' ',ListaOsob[ i ].Nazwisko,

' lat ',ListaOsob[ i ].Wiek,' ');

if ListaOsob[ i ].Plec=K then write('K')

else write('M');

writeln(' ',Listaosob[ i ].Adres);

end;

writeln;

write('Wyswietlic powtornie [ T/N ]:');readln(znak);

until Upcase(znak) = 'N';

end.

13. Rekurencja

Wiele zagadnień w technice i matematyce można zdefiniować rekurencyjnie. Definicja rekurencyjna oznacza takie zdefiniowanie problemu gdzie odwołujemy się do definiowanej właśnie definicji. Przykładem takiej definicji może być potęga całkowita nieujemna rzędu N liczby rzeczywistej x:

xn = jeśli n > 0 to xn-1*x

jeśli n = 0 to 1

Rekurencja w językach programowania realizowana jest przy pomocy podprogramów wywołujących same siebie. Podprogramy rekurencyjne aby poprawnie działały muszą spełniać następujący warunek: podprogram musi zawierać warunek, który powoduje zakończenie rekurencji, czyli nie wywołuje po raz kolejny samego siebie.

Rekurencja daje proste i eleganckie programy - niestety ma także poważną wadę: każde wywołanie podprogramu wymaga wykonania przez procesor pewnych czynności administracyjnych co spowalnia działanie programu, oraz powoduje odłożenie na stos systemowy dużej liczby danych.

Przykład - wyznaczanie N-tej potęgi liczby X:

Program Potega1;

{wyznaczanie potęgi całkowitej nieujemnej N z liczby x metodą rekurencyjną}

function PotegaN(x:real;N:integer):real;

{ funkcja wyznacza potege N z liczby X }

begin

if N=0 then PotegaN := 1

else PotegaN := PotegaN(x,N-1)*x;

end;

begin

writeln('2^10=',PotegaN(2,10):0:0);

end.

Przykład - wyznaczanie silni z liczby x:

program Silnia; {Wyznaczanie silni liczby X - metoda rekurencyjna}

function SilniaX(x:longint):longint;

begin

if x = 1 then SilniaX := 1

else SilniaX := SilniaX(x-1)*x;

end;

begin

Writeln('Silnia z liczby 6= ',SilniaX(6));

end.

14. Zmienne wskaźnikowe

Do tej pory używaliśmy zmiennych statycznych. Zmienna statyczna, zadeklarowana deklaracją VAR jest tworzona w chwili uruchomienia programu. Jej rozmiar definiujemy w trakcie pisania programu - tak więc w przypadku tablic pisząc program musimy przyjąć jakąś maksymalną liczbę elementów tablicy. Dodatkowym ograniczeniem w TurboPascal-u jest to, że zmienne zadeklarowane w jednym module nie mogą mięć więcej niż 64kB. Ominąć ten problem pozwalają tzw. zmienne dynamiczne nazywane popularnie wskaźnikami.

Zmienna statyczna z punktu widzenia procesora jest fragmentem pamięci o rozmiarze pozwalającym pomieścić dane określonego typu. W trakcie wykonywania programu procesor nic nie wie o nazwach zmiennych - posługuje się jedynie adresem, który mówi gdzie zmienna znajduje się w pamięci. W trakcie kompilacji na podstawie zadeklarowanego typu zmiennej kompilator przyporządkowuje odwołaniom do zmiennych konkretne procedury działające na zmiennych zadeklarowanego typu. Linker przydziela zaś zmiennym adresy, tak, aby nie nakładały się na siebie.

Zmienna wskaźnikowa pozwala w trakcie programu przydzielać pamięć zmiennym specjalnymi procedurami.

Zmienna wskaźnikowa jest więc adresem wskazującym na miejsce w pamięci, gdzie ma być przechowywana wartość zmiennej. Koncepcja wskaźników w Pascalu pozwala nam nie martwić się o długość zmiennej wskazywanej przez zmienną wskaźnikową (TurboPascal posiada mechanizmy pozwalające wyłączyć kontrolę kompilatora nad typem i długością zmiennej - mechanizmy te nie będą przedmiotem tego wykładu).

14.1. Deklaracja zmiennej wskaźnikowej

Zmienną wskaźnikową (czyli adres do zmiennej jakiegoś konkretnego typu) deklaruje się jako zmienną statyczną. Zmienna wskaźnikowa zajmuje 4 bajty.

var

nazwa_zmiennej_wskaznikowej :^typ_zmiennej;

lub

type

nazwa_typu =^typ_zmiennej;

var

nazwa_zmiennej_wskaznikowej :nazwa_typu;

"nazwa_zmiennej_wskaznikowej" oraz "nazwa_typu" są dowolnymi akceptowanymi przez Pascal nazwami identyfikatorów.

"typ_zmiennej" określa typ zmiennej wskazywanej przez zadeklarowany wskaźnik. Na tej podstawie kompilator rozpoznaje jaką ilość pamięci zawiera zmienna wskazywana przez wskaźnik i jakich procedur użyć do wykonywania operacji na niej.,

Typ ten musi być określony jednym identyfikatorem!

Zmienna wskaźnikowa dopuszcza jeden wyjątek w podstawowej regule składni języka Pascal, że można używać tylko identyfikatorów wcześniej zadeklarowanych:

Deklaracja zmiennej (lub typu) wskaźnikowej może odwoływać się do typu, który zostanie zadeklarowany po deklaracji zmiennej (lub typu) wskaźnikowej.

type

pOsoba =^TOsoba;

TOsoba =record

imie,nazwisko :string;

nastepny :pOsoba;

end;

var

pzmienna:TOsoba;

Zwykle przy deklaracji typów wskaźnikowych (podobnie jak i zmiennych) nazwę identyfikatora typu lub zmiennej zaczyna się od małej litery "p" (od „point” - wskazywać).

14.2. Odwołanie do zmiennej wskaźnikowej

W naszym programie, aby dostać się do wartości na którą wskazuje zmienna wskaźnikowa (inaczej mówiąc do zmiennej umieszczonej w pamięci pod adresem zawartym w zmiennej wskaźnikowej) musimy do nazwy zmiennej dodać znak "^":

var

x,y :^integer;

z :integer;

begin

{...}

z := 2

x^ := z+2;

y := x^*3

z := x^+y^;

{...}

end.

^typ - nazwa typu wskazywanego przez zmienną wskaźnikową

x - zawiera adres w pamięci pod którym przechowywana jest wartość zmiennej

x^ - zawiera wartość zmiennej

14.3. Operacje na wskaźnikach

Na zmiennych wskaźnikowych można wykonać niewiele operacji.

Zmienne wskaźnikowe jak i zmienne przez nie wskazywane można przypisywać - należy wtedy pamiętać aby typy były zgodne. Istnieje możliwość wyłączenia kontroli typów zmiennych wskazywanych przez wskaźniki - pozwala to na różne interpretacje wartości zmiennej. W podanym poniżej przykładzie zastosowano operator "@" - nazwa identyfikatora zmiennej (lub podprogramu) poprzedzona tym operatorem daje adres (czyli wskaźnik) do danej zmiennej. W przykładzie do zmiennej p (wskaźnika do tablicy 6-cio bajtowej) wstawiamy adres do zmiennej x typu REAL (też 6-cio bajtowej). Umożliwia nam to dostęp do poszczególnych bajtów zmiennej x:

Przykład:

type

TByteArray=array[1..6] of byte;

var

x : real;

p : ^TByteArray;

i : integer;

begin

x := 2.5;

p := @x; {przypisanie wskazania na 6-bajtową zmienną typu real do wskazania na równiwż 6-bajtową tablicę)

writeln('Liczba typu real o wartosci:',x:0,' sklada się z nastepujacych bajtow:');

for i := 1 to 6 do

writeln('Bajt ',i,' = ',p^[i]); {wydruk posczególnych bajtów liczby 2.5}

end.

Oprócz przypisania wskaźniki można porównywać. Aby stwierdzić czy zmiennej wskaźnikowej nadano wartość wprowadzono definicję specjalnego adresu, który oznacza umowny "brak adresu" - "NIL". Tak więc, aby sprawdzić czy zmienna wskaźnikowa wskazuje na jakąś zmienną można użyć konstrukcji:

if zmienna <> nil then ...

Niestety należy pamiętać, że likwidowanie zmiennej procedurą DISPOSE (o tym dalej) nie nadaje zmiennej wskaźnikowej wartości NIL. Operację tę należy przeprowadzić samodzielnie.

14.4. Tworzenie i likwidowanie zmiennych dynamicznych

Najważniejszą rzeczą przy zmiennych dynamicznych jest ich tworzenie (inaczej alokacja) w pamięci, a następnie ich likwidowanie. Do utworzenia zmiennej (czyli rezerwacji miejsca w pamięci na zmienną wskazywana przez zmienną wskaźnikową) służy procedura NEW:

procedure NEW(var x:pointer);

Procedura NEW rezerwuje w pamięci RAM obszar pamięci, który pozwoli przechować zmienną typu wskazywanego przez zmienną wskaźnikową x. Adres początku tego obszaru pamięci wpisywany jest do zmiennej x.

Operację odwrotną wykonuje procedura DISPOSE:

procedure DISPOSE(var x:pointer);

Lista

Najciekawszą strukturą danych oferowaną przez zmienne dynamiczne jest lista. Lista składa się z rekordów, w których co najmniej jedno z pól wskazuje na kolejny rekord tego samego typu. Istnieją różne rodzaje list - jednokierunkowa, dwukierunkowa, drzewo itp.

W listach należy pamiętać o tym, że każdy utworzony element musimy dołączyć do łańcuszka elementów, w przeciwnym wypadku, jeśli "zgubimy" adres do niego jest on stracony dla naszej aplikacji.

Przykład

0x08 graphic
0x08 graphic
program dynamika;

uses crt;

0x08 graphic
0x08 graphic
const n=3;

type

Wsk = ^Osoba;

Osoba = record

Kod: 1..100;

Nazw: string[15];

Nast: Wsk;

0x08 graphic
end;

0x08 graphic
var osob_1,osob,pom1,pom2:wsk;

k:integer;

p:text;

{***************************************************}

procedure czytaj(var osob:wsk;N:integer);

var pom1,pom2:wsk;

begin

osob := nil; {puste wskazanie}

writeln ('podaj nr i nazwisko ',n, ' osob');

0x08 graphic
for k:=1 to n do

begin

0x08 graphic
new(pom1);

readln (pom1^.kod);

readln (pom1^.nazw);

pom1^.nast. := nil;

0x08 graphic
if osob = nil then

0x08 graphic
osob:=pom1

else

begin

0x08 graphic
pom2 := osob;

while pom2^.nast <> nil do

pom2 := pom2^.nast;

0x08 graphic
pom2^.nast:=pom1

0x08 graphic
end;

end;

end;

{***************************************************}

procedure dopisz(var osob:wsk);

var pom1,pom2,pom3:wsk;

begin

writeln('podaj nr nazwisko jednej osoby');

new(pom1);

readln(pom1^.kod);

readln(pom1^.nazw);

pom1^.nast:=nil;

pom2:=osob;

if pom1^.nazw <= pom2^.nazw then

osob:=pom1 {jesli na poczatku listy}

else

begin {szukanie miejsca w szeregu}

while pom1^.nazw > pom2^.nazw do

begin

pom3:=pom2; {zapamietanie miejsca}

pom2:=pom2^.nast; {miejsce nastepne}

end;

pom3^.nast:=pom1; {wskazanie na wczytane dane}

end;

pom1^.nast:=pom2; {wskazanie nastepnych danych}

end;

{***************************************************}

procedure pisz(var osob:wsk);

begin

clrscr;

writeln('zawartosc listy');

osob_1 := osob; {przepisanie wskazania do pomocniczej zmiennej}

while osob_1<> nil do

begin

writeln(osob_1^.kod:4,' ':4,osob_1^.nazw);

osob_1:=osob_1^.nast {przesuwanie wskazań}

end;

repeat until keypressed

end;

{****************************************************}

begin {cialo programu}

clrscr;

czytaj(osob,N);

pisz(osob);

dopisz(osob);

pisz(osob);

repeat until keypressed;

end.

Poniżej przedstawiono schemat logiczny tworzenia listy jednokierunkowej:

0x01 graphic

0x01 graphic

Lista dwukierunkowa, w której dwa pola wskaźnikowe każdej zmiennej zawierają wskazanie na element następny i poprzedni.

0x01 graphic

Na podobnej zasadzie działa struktura drzewa, w którym zmienna wskaźnikowa oprócz pól statycznch zawiera wiele pól, zawierających bądź wskazanie puste (NIL) bądź na inne zmienne

14. Moduły

Moduły są podstawą programowania modularnego i służą do grupowania funkcji i procedur w biblioteki. Moduł nie stanowi samodzielnego programu. Jego użycie wymaga deklaracji. Moduł powinien być wcześniej skompilowany i umieszczony w katalogu UNITS.

14.1. Opis struktury modułu:

unit nazwa_modułu;

interface {część opisowa }

deklaracja modułów {zawsze pierwsza}

definicja stałych

definicja typów

definicja zmiennych

lista nagłówków procedur i funkcji

implementation {część implementacyjna}

deklaracje i definicje stałych, typów i zmien­nych elementów dostępnych tylko w module

definicje procedur i funkcji

end lub instrukcja złożona {część inicjująca}

.

Przykład modułu:

unit cmplx;

interface

type complex = record

im,re:real

end;

procedure dodaj (a,b:complex; var c:complex);

procedure odejmij (a,b:complex; var c:complex);

............ {i inne}

implementation

procedure dodaj(a,b:complex; var c:complex);

begin

c.re := a.re + b.re;

c.im := a.im + b.im

end;

procedure odejmij (a,b:complex; var c:complex);

begin

c.re := a.re - b.re;

c.im := a.im - b.im

end;

end.

Tak utworzony moduł powinien być poprawnie skompilowany na dysk (opcja Destination - disk menu Compile). Jego skomplilowany plik z rozszerzeniem tpu powstanie w katalogu określonym w menu Options - Directories... jako katalog EXE & TPU. Następnie należy go przenieść (lub skopiować) do katalogu określonego w menu Options - Directories... jako Units directory, wówczas można z niego korzystać w dowolnym programie.

Przykład wykorzystania modułu:

Program m12;

uses cmplx;

var x,y,z : complex;

begin

........ {zdefiniowane x i y}

dodaj (x,y,z);

writeln (`Suma=', z.re:12:5 , z.im:12:5);

odejmij (x,y,z);

writeln (`Roznica=', z.re:12:5 , z.im:12:5)

end.

Jeśli jeden moduł wykorzystuje wewnątrz funkcje lub procedury innego modułu, deklaracja powinna wyglądać następująco:

unit A;

interface

.............

implementation

uses B;

..............

jeżeli zaś będzie

unit B;

interface

.............

implementation

uses A;

..............

to moduły A i B są wzajemnie zależne.

14.2. Moduły standardowe TurboPascala

Moduł Printer

Zawiera deklarację pliku tekstowego Lst, dzięki któremu:

program drukuj;

uses Printer;

begin

writeln(Lst, `Tekst wyprowadzany')

end;

Moduł System

(Uwaga: nie trzeba go deklarować w bloku Uses)

Zawiera:

  1. Predefiniowane stałe i zmienne dla identyfikacji błędów, obsługi wejścia i wyjścia.

  2. Procedury przerwania pętli i programu:

Break - przerwanie pętli

Exit - wyjście z bieżącego bloku

Halt - przerwanie programu.

  1. Funkcje i procedury dynamicznego przydziału pamięci: New, Dispose i inne, adresowe i wskaźnikowe.

  2. Funkcje konwersji: Chr, Ord, Round, Trunc

  3. Arytmetyczne funkcje standardowe.

  4. Procedury porządkowe: Inc, Dec, Odd, Pred, Succ.

  5. Funkcje i procedury łańcuchowe: Concat, Copy, Length,

Concat (lista_łańcuchów) - połączenie łańcuchów

Copy (łańcuch, pozycja, długość) - wycięcie z łańcucha

Length (łańcuch) - długość łańcucha

Str (argument numeryczny, zmienna łańcuchowa)

- zamiana wartości na łańcuch

Val(łańcuch, zmienna numeryczna, kod)

- zamiana łańcucha na wartość (kod - pozycja pierwszego błędnego znaku)

  1. Procedury i funkcje obsługi zbiorów: Assign, Reset, Rewrite, Close, Eof, Eoln i inne.

  2. Inne procedury i funkcje, np.:

Randomize - inicjacja generatora liczb losowych

Random(zakres) - wartość losowa z zakresu Randomize

Moduł Crt

Zawiera predefiniowane identyfikatory: trybu ekranu, kolorów

  1. Podprogramy sterowania trybami ekranu:

ClrScr, Window, Gotoxy (x,y), TextColor, TextBackground i inne

  1. Funkcje:

Readkey - wczytanie jednego znaku

Procedury dźwiękowe:

Delay(opóźnienie w milisekundach);

Sound (częstotliwość);

NoSound; - przerwanie dźwieku

Moduł Strings - Funkcje i procedury operacji na tekstach

Moduł Dos i WinDos- Funkcje i procedury do bezpośredniego kontaktu z systemem operacyjnym.

Moduł Graph - funkcje i procedury graficzne.

14.2. Podstawy programowania obiektowego

Elementy opisane uprzednio dotyczą tzw. programowania strukturalnego - koncepcja tradycyjna. Główną jego składową są instrukcje działające na danych. Złożone programy korzystają z funkcji, procedur i modułów w celu uproszczenia zarządzania i kontroli nad programem, lecz nie zmienia to podstawowej koncepcji.

Programowanie zorientowane obiektowo (OOP - Object Oriented Programming) umożliwia przedstawienie problemu w postaci logicznie powiązanych ze sobą struktur danych zwanych obiektami, wymieniających informacje między sobą.

Znając pojęcie modułu można tworzyć quasi-obiekty, przykładowo:

unit kolo;

interface

var sx, sy, pr, wzorzec, kolor :Word;

procedure inicjuj (x, y, r : Word);

procedure styl (k, w: Word);

procedure rysuj;

implementation

uses Graph;

procedure inicjuj;

begin

sx:=x;

sy:=y;

pr:=r;

kolor:= GetMaxColor; {na wypadek pominięcia wyboru koloru}

wzorzec:= SolidFill {i wzorca procedurą styl}

end;

procedure styl;

begin

kolor:=k;

wzorzec:=w;

end;

procedure rysuj;

begin

SetColor(kolor);

SetFillStyle (wzorzec, kolor);

FillEllipse(sx, sy, pr, pr);

end;

end .

unit ramka;

interface

var lgx, lgy, pdx, pdy, wzorzec, kolor :Word;

procedure inicjuj (x1, y1, x2, y2 : Word);

procedure styl (k, w: Word);

procedure rysuj;

implementation

uses Graph;

procedure inicjuj;

begin

lgx:=x1;

lgy:=y1;

pdx:=x2;

pdy:=y2;

kolor:= GetMaxColor;

wzorzec:= SolidFill

end;

procedure styl;

begin

kolor:=k;

wzorze:=w;

end;

procedure rysuj;

begin

SetColor(kolor);

SetFillStyle (wzorzec, kolor);

Bar3D(lgx, lgy, pdx, pdy, 0, TopOff);

end;

end .

Widoczne jest podobieństwo obu modułów, powtarzalność pewnych parametrów.

Zapisujemy obydwa moduły na dysku pod nazwami plikowymi takimi jak w nagłówkach modułów i kompilujemy na dysk (powstają dwa pliki z rozszerzeniem tpu). Umieszczamy je w katalogu UNITS. Wykorzystanie obu modułów mogłoby przykładowo wyglądać następująco:

program grafika;

uses crt, graph, kolo, ramka;

var st,tryb :integer;

znak:Char;

begin

repeat

writeln('1 - kolo, 2 - ramka. Wybieraj ');

znak:=Readkey

until (znak='1') or (znak='2')

st:=Detect; {detekcja sterownika graficznego}

InitGraph(st,tryb, 'C:\TP\BGI'); {zainicjowanie trybu graficznego}

case znak of

'1': begin

kolo.inicjuj( 10, 20, 50);

kolo.styl ( LightRed, SolidFill);

kolo.rysuj

end;

'2' : begin

ramka.inicjuj( 10, 10, 50, 50);

ramka.styl ( LightBlue, SlashFill);

ramka.rysuj

end

end;

repeat until keypressed;

CloseGraph

end.

Należy zwrócić uwagę na sposób wywołania procedur modułów (ze względu na identyczność nazw procedur odnosimy się do nazwy odpowiedniego modułu w konwencji podobnej jak w rekordach moduł.procedura)

Zwraca uwagę powtarzanie podobnych struktur programu, zwiększa się rozmiar programu i zmniejsza jego czytelność. Dodanie nowego obiektu wymaga nowego modułu.

Aby usunąć te niedogodności wprowadzono pojęcie obiektu.

Obiekt - złożona struktura posiadająca:

pola (właściwości opisane wartościami dowolnych typów, także strukturalnych)

metody (procedury i funkcje wykonywane na polach)

Typ obiektowy nazywamy klasą. Może on być niezależny, (zdefiniowany podobnie jak typ rekordowy) lub jako potomek istniejącego. Wtedy mówimy, że obiekt dziedziczy wszystkie elementy (pola i metody) swojego przodka lub jest typem potomnym. Obiekty potomne mogą mieć własnego potomka (lub wielu). Stąd wzajemne zależności obiektów układają się w drzewo hierarchii obiektów.

Dziedziczność bezpośrednia - przodek jest niezależny (sam nie ma przodka)

Dziedziczność pośrednia - przodek już dziedziczy (sam ma przodka)

Obiekty mogą opisywać własności obiektów rzeczywistych lub być abstrakcyjne.

Przykład:

type polozenie = object {obiekt niezależny}

x,y:integer;

end;

punkt = object (polozenie) {obiekt potomny}

widocznosc: Boolean

end;

Obiekt punkt jest zdefiniowany jako potomny obiektu polozenie dziedziczy jego własności x, y oraz posiada własne dodatkowe pole widocznosc.

Metody określają czynności na obiekcie - przy ich pomocy mamy dostęp do pól. Metoda jest to procedura lub funkcja mająca deklarację w ramach typu obiektowego (sam nagłówek procedury lub funkcji). Definicja metody występuje poza definicją typu obiektowego i po niej. W nagłówku definicji nazwa jest kwalifikowana, czyli wskazuje na obiekt, którego dotyczy i ma postać:

nazwa_typu_obiektowego . nazwa_metody

Przykład:

type polozenie = object {obiekt niezależny}

x,y:integer;

procedure przesun (nx, ny: Integer)

end;

procedure polozenie.przesun

begin

x:=nx;

y:=ny;

end;

Obiekty (klasy) grupuje się też modułach. W części opisowej modułu (interface) podajemy opisu obiektów, w części implementacyjnej zaś definiujemy metody. W części implementacyjnej mogą też wystąpić wewnętrzne definicje obiektów i innych zmiennych, typ obiektu zdefiniowany w części opisowej może też mieć swojego potomka w części implementacyjnej.

Potomek może mieć tę samą nazwę metody jak przodek, „przykrywa” ona wówczas metodę przodka. Definiując metodę potomka, (np. gdy jest ona rozszerzeniem metody nadrzędnej), można odwołać się do metody dziedziczonej od przodka.

Przykładowo, istnieje klasa osoba i jej metoda drukuj, wypisująca na ekranie nazwisko i imię osoby, oraz potomek uczen (poszerzony o pole klasa), którego metodę drukuj definiujemy:

procedure uczen.drukuj

inherited drukuj; {wywołanie metody dziedziczonej}

writeln('numer klasy :', klasa)

end;

Fakt, że dostęp do pól odbywa się jedynie przy użyciu metod nazywa się hermetyzacją. Jest to ważne z punktu widzenia dyscypliny programowania, w jednym miejscu mamy dane i dozwolone operacje na nich. Ułatwia to kontrolę poprawności złożonych programów. W tradycyjnym programowaniu niebezpieczne jest modyfikowanie struktur danych, konsekwencje takiej zmiany należy uwzględnić w całym programie. W programowaniu obiektowym zmiana dotyczy tylko obiektu.

Programowanie strukturalne: procedury i przekazywanie im danych.

Programowanie obiektowe: aktywacja metod dla umieszczonych w polach obiektu danych

Przykłady:

program obiekty1;

{deficja i wykorzystanie prostego typu obiektowego} uses crt; type TOsoba=object

nazwisko:string;

imie:string;

miasto:string;

procedure czytaj;

procedure pisz;

end;

procedure TOsoba.czytaj;

begin

readln(nazwisko);

readln(imie);

readln(miasto);

end;

procedure TOsoba.pisz;

begin

writeln('Oto dane osoby');

writeln(nazwisko);

writeln(imie);

writeln(miasto);

end;

var n,m,i:string;

czlowiek:TOsoba;

begin

clrscr;

czlowiek.czytaj;

czlowiek.pisz;

end.

program obiekty1_1;

{definicja i wykorzystanie prostego typu obiektowego tablicowego}

uses crt;

type TOsoba=object

nazwisko:string;

imie:string;

miasto:string;

procedure czytaj;

procedure pisz;

end;

procedure TOsoba.czytaj;

begin

writeln('Podaj dane osoby: nazwisko, imie, miasto');

readln(nazwisko);

readln(imie);

readln(miasto);

end;

procedure TOsoba.pisz;

begin

writeln('Oto dane osoby');

writeln('Nazwisko':nazwisko);

writeln('Imie: ',imie); writeln('Miasto: ',miasto); end;

var n,m,i:string; grupa:array[1..10] of TOsoba;

k:integer;

begin

clrscr;

for k:=1 to 10 do

grupa[k].czytaj;

for k:=1 to 10 do grupa[k].pisz;

end.

program obiekty2_1;

{dziedziczenie proste - wlasciwosci}

uses crt;

type TOsoba=object

nazwisko:string;

imie:string;

miasto:string;

procedure czytaj;

procedure pisz;

end;

TUczen=object(TOsoba) {typ dziedziczony od TOsoba}

ocena:2..5; {dodatkowe pole}

procedure czytaj_ocene; {dodatkowe metody}

procedure pisz_ocene;

end;

procedure TOsoba.czytaj;

begin

write('Podaj nazwisko:':20);

readln(nazwisko);

write('Podaj imie:':20);

readln(imie);

write('Podaj miasto:':20);

readln(miasto);

end;

procedure TOsoba.pisz;

begin

writeln;

writeln('Oto dane osoby':20);

writeln('Nazwisko:':20,nazwisko);

writeln('Imie:':20,imie);

writeln('Miasto:':20,miasto);

end;

procedure TUczen.Czytaj_ocene;

begin

write('Podaj ocene :':20);

readln(ocena);

end;

procedure TUczen.Pisz_ocene;

begin

writeln('Ocena:':20,ocena);

end;

var n,m,i:string;

k:1..5;

czlowiek:TOsoba;

student:TUczen;

grupa:array[1..5] of TUczen;

{poczatek programu}

begin

for k:=1 to 5 do

begin

clrscr;

writeln(k);

student.czytaj;

student.czytaj_ocene;

student.pisz;

student.pisz_ocene;

grupa[k]:=student

end;

for k:=1 to 5 do writeln(grupa[k].nazwisko);

repeat until keypressed

end.

program rysuj2;uses crt, graph, grafika;var st,tryb :integer;

znak:Char;

ob1:kolo;

ob2:ramka;

begin

repeat

writeln('1 - kolo, 2 - ramka. Wybieraj ');

znak:=readkey

until (znak='1') or (znak='2');

st:=Detect; {detekcja sterownika graficznego}

InitGraph(st,tryb, 'e:\TP\BGI'); {zainicjowanie trybu graficznego}

case znak of

'1': begin

ob1.inicjuj( 100, 200, 50);

ob1.styl ( LightRed, SolidFill);

ob1.rysuj

end;

'2' : begin

ob2.inicjuj( 10, 10, 50, 50);

ob2.styl ( LightBlue, SlashFill);

ob2.rysuj

end

end;

repeat until keypressed;

CloseGraph

end.

Przykład modułu z wykorzystaniem dziedziczenia.

unit grafika;

interface

type figura = object

wzorzec, kolor :Word;

procedure styl (k, w: Word);

end;

kolo = object (figura)

sx,sy,pr:Word;

procedure inicjuj(x, y, r : Word);

procedure rysuj;

end;

ramka = object (figura)

lgx,lgy,pdx,pdy:Word;

procedure inicjuj(x1,y1,x2,y2: Word);

procedure rysuj;

end;

implementation

uses graph;

procedure figura.styl;

begin

kolor:=k;

wzorzec:=w;

end;

procedure kolo.inicjuj (x, y, r : Word);

begin

sx:=x;

sy:=y;

pr:=r;

kolor:= GetMaxColor;

wzorzec:= SolidFill;

end;

procedure kolo.rysuj;

begin

SetColor(kolor);

SetFillStyle (wzorzec, kolor);

FillEllipse(sx, sy, pr, pr);

end;

procedure ramka.inicjuj(x1,y1,x2,y2:Word);

begin

lgx:=x1;

lgy:=y1;

pdx:=x2;

pdy:=y2;

kolor:= GetMaxColor;

wzorzec:= SolidFill;

end;

procedure ramka.rysuj;

begin

SetColor(kolor);

SetFillStyle (wzorzec, kolor);

Bar3D(lgx, lgy, pdx, pdy, 0, TopOff);

end;

end .

51

sekcja

instrukcji

blok

główny

Sekcja

deklaracji

Dopisanie na końcu

Przewijanie listy do końca NIL

Przepisanie wskazania do pomocniczej zmiennej

Pom1^.kod

to zawartość pola rekordu wskazywanego przez zmienną pom1

Zmienne tego typu wskazują na adres w pamięci

WYJĄTEK:

Użycie typu, który jest definiowany później

Typ wskaźnikowy

zamiana wartości zmiennych z użyciem pomocniczej zmiennej



Wyszukiwarka

Podobne podstrony:
Podstawy Informatyki Wykład XI Object Pascal Podstawy programowania w Object Pascalu
Podstawy Programowania W Języku Pascal
Podstawy Informatyki Wykład X Object Pascal Jezyki programowania, Proste typy danych
Nowa podstawa programowa WF (1)
1 Podstawy programowania dialogowego
nowa podstawa programowa sp
11-nkb~1, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, l2
2-eukl~1, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, l2
Zmiany w podstawie programowej w zakresie edukcji matematycznej, Wczesna edukacja, Materiały do prac
1-algo~1, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, l2
c-zadania-w3, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, kol
Wychowanie w nowej podstawie programowej katechezy, szkoła, Rady Pedagogiczne, wychowanie, profilakt
PP temat6, Podstawy programowania
PODSTAWA PROGRAMOWA WYCHOWANIA PRZEDSZKOLNEGO
Laboratorium Podstaw Programowania 2
Podstawa programowa dla gimnazjum
Pytania na egzamin nowa podstawa programowa, sem I

więcej podobnych podstron