Środowisko zintegrowanego pakietu programowania w języku
TURBO PASCAL (7.0).
Wiadomości wstępne
Historia praktycznego wykorzystania języków programowania ma kilkadziesiąt lat, choć podstawy teoretyczne algorytmicznego sterowania automatami cyfrowymi są znacznie starsze. Do połowy lat 50-tych panował język maszynowy (komputery Eniac, Mark I). Kodowanie instrukcji procesora odbywa się tu w postaci tworzenia ciągu liczb dwójkowych (elementarny rozkaz i dane), co jest bardzo pracochłonne (same liczby, długie algorytmy działań takich jak dodawanie i mnożenie) i powoduje trudność śledzenia błędów.
W latach 50-tych zastąpiono kody binarne elementarnych operacji ich nazwami mnemotechnicznymi (np. mnożenie MPY - multiply), taki język symboliczny zwany jest assemblerem. Assembler to także program tłumaczący na kod maszynowy (wewnętrzny) zaś program dissassembler przeprowadza tłumaczenie odwrotne. Stosowany jest do dziś - np. w oprogramowaniu interfejsów pomiarowych, wprowadzaniu danych z pomiarów, ich komputerowym przetwarzaniu itp. Cechami assemblera są: zmniejszona ale nadal duża pracochłonność tworzenia algorytmów, możliwość błędów (prawie każda kombinacja znaków można być wykonana), ukierunkowanie na konkretny komputer (procesor) dla którego program był pisany, wąski zbiór rozkazów (np. brak operacji zmiennoprzecinkowych).
Pod koniec lat 50-tych zapanował etap tzw. języków wysokiego poziomu (kod maszynowy i assembler to niski poziom - bliższy procesorowi). Zapis operacji wykonywanych przez program jest tu łatwiejszy dla programisty, zrozumiały i dobrze kontrolowany. Po stworzeniu kodu źródłowego programu w języku wysokiego poziomu następuje proces tłumaczenia na język wewnętrzny komputera: w całości (kompilacja) i dopiero jego wykonanie, lub też dla niektórych języków (np. Basic, LOGO) kod źródłowy jest tłumaczony w czasie wykonania instrukcja po instrukcji (interpretacja).
Języki wysokiego poziomu po etapie początkowym stały się maszynowo niezależne z powodu wielu wersji kompilatorów (programów kompilujących).
W kolejnych latach nastąpiła obfitość języków programowania. Najważniejsze to:
COBOL - dla przedsiębiorstw, język prawie naturalny (np. instrukcje MULTIPLY - mnożenie, ADD- dodawanie),
FORTRAN, PASCAL - języki ukierunkowane na obliczenia naukowe,
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+- języki strukturalne (modułowa struktura programów),
OOP (Object Oriented Programming) - języki zorientowane obiektowo (PROLOG, Visual Basic, C++, Delphi -Object Pascal, Java)
Klasyfikacja języków programowania:
do przetwarzania danych: COBOL, dBase
do obliczeń naukowych: Fortran, Pascal,
do programowania systemowego - tworzenie systemów operacyjnych: C, BCPL, BLISS,
opisu zleceń - DOS, MVS,
konwersacyjne: LISP, zmiany z terminala w trakcie konwersacji
symulacyjne - symulacja procesów (najczęściej w czasie rzeczywistym): mechanika, elektronika, termodynamika itp. - SIMULA, CSSL
algorytmiczne (większość): programowanie to zapis sposobu wykonania zadania przy pomocy kolejno wykonywanych instrukcji,
niealgorytmiczne: nie jak ale co ma być zrobione - sterowanie nie algorytmem lecz danymi
obiektowe - nazwane zbiory danych (obiekty) posiadające własności statyczne (pola) i dynamiczne (metody); poprzez zdarzenia (zwykle wymuszone przez użytkownika) można te własności zmieniać lub wywoływać akcje obliczeniowe przez aktywizację metod,
specjalizowane - ukierunkowane na pewną klasę problemów, np. obróbkę baz danych, analizę układów elektronicznych itp.
Świat rzeczywisty lub abstrakcyjny reprezentowany jest przez dane, na których wykonywane są operacje. Aby opisać dane i operacje potrzebne są ustalone umowy, tworzące tzw. język formalny - zbiór słów nad określonym alfabetem.
Język programowania to zbiór konwencji i umów umożliwiających komunikatywność zapisu i ich zrozumiałość 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.
Błędy składniowe - np. pominięcie słowa kluczowego instrukcji lub jego przekręcenie,
Błędy semantyczne - np. zły typ danych, licznik pętli nie jest typu całkowitego itp.
Jeżeli spełnione są warunki, iż:
- 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ń, 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.
deklaracje, definicje - są to opisy obiektów używanych w programie,
instrukcje - czynności na obiektach,
program - algorytm zapisany w języku programowania,
podprogram - wyodrębniona część programu (ze względu na zwiększenie czytelności lub umożliwienie jego wielokrotnego użycia), 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
Język PASCAL (autor Nicklaus Wirth, powstał w latach 70-tych) posiada następujące cechy:
Język wysokiego poziomu - zezwala na stosowanie składni syntaktycznej języka bez znajomości struktury wewnętrznej komputera,
Język algorytmiczny - zapis koncepcji i zadań opracowanych przez programistę,
Język strukturalny - fragmenty algorytmu zapisywane są w odrębnych strukturach językowych,
Język modularny - składanie programu z modułów,
Posiada mechanizmy kontroli struktur i reguł gramatycznych - umożliwia identyfikację i poprawę błędów,
Sposoby pisania programu
Rys. 1.1 Etapy programowania.
program źródłowy utworzony dowolnym edytorem tekstu, następnie kompilacja, ewentualnie konsolidacja (linkowanie - łączenie z podprogramami bibliotecznymi - modułami), wykonanie,
korzystanie z ze zintegrowanych pakietów programistycznych (wewnętrzne narzędzia edycji, kompilacji i konsolidacji, weryfikacji błędów itp.)
Uruchamianie pakietu Turbo Pascal. Podstawowe operacje.
Aktywizacja środowiska programistycznego polega na wykonaniu plików:
turbo [plik.pas] - wersja trybu rzeczywistego DOS
tpx [plik.pas] - wersja trybu chronionego DOS
W systemie Windows dla wygody użytkownika zalecane jest utworzenie skrótu do pliku turbo.exe (np. na pulpicie), ustawiając we właściwościach skrótu opcję "zamykaj przy zakończeniu", zaś we właściwościach zaawansowanych zaznaczając "Sugeruj tryb MS-DOS jeśli wymagany".
Rys.1.2. Okno edytora środowiska Turbo Pascala.
Środowisko języka zgłasza się oknem edytora kodu źródłowego (jak na rys.1.2). Poniższa tabela przedstawia podstawowe operacje klawiszowe i wyjaśnia pojęcia używane w rozwijanym menu.
Tabela 1.
Operacja |
Sposób wykonania - opis |
Dostęp do menu |
ALT+wyróżniona litera nagłówka menu |
Wybór okna edycyjnego |
ALT+nr okna |
Przełączanie: |
ALT+F5 |
Otwarcie pliku z dysku |
F3 |
Zapis pliku na dysk |
F2 |
Kompilacja |
ALT+ F9 (F9) |
Kompilacja +wykonanie |
CRTL+F9 |
Step over |
F8 - krokowe wykonywanie programu głównego |
Trace into |
F7 - jak wyżej lecz dodatkowo krokowe wykonanie podprogramów |
Watch |
ALT+F7 lub menu Debug-Watch-Add watch - śledzenie wartości wyszczególnionych zmiennych (dodawanie zmiennych klawiszem Insert) |
Breakpoints |
menu Debug-Add breakpoint - "pułapki" - miejsca chwilowego zatrzymania programu w celu sprawdzenia wartości zmiennych na danym etapie |
Pomoc |
F1 - pomoc ogólna, CTRL+F1 - pomoc kontekstowa (na temat wskazanego w edytorze słowa) |
Oprócz okna edytora (możliwe jest otwarcie wielu okien edycyjnych) najważniejszy to ekran Output przedstawiający wyniki wykonania programu - aktywizowany kombinacją klawiszy ALT+F5 w postaci pełnoekranowej lub przez menu Debug - Output w postaci okienkowej.
Błędy
W przypadku wystąpienia błędu proces kompilacji zatrzymuje się i wskazywane jest miejsce wystąpienia błędu z angielskim, skrótowym opisem.
Najczęstsze błędy składniowe przedstawia tabela 1.
Tabela 2.
Opis angielski |
Opis |
unknown identifier |
nieznany identyfikator |
syntax error |
zła składnia |
type mismatch |
niezgodność typów |
error in expression |
błąd w wyrażeniu |
unexpected end of file |
nieoczekiwany koniec pliku |
";" expected |
";" oczekiwany |
")" expected |
")" oczekiwany |
"DO" expected |
oczekiwane słowo kluczowe "DO" |
Błędy wykonania polegają zazwyczaj na:
niewłaściwym użyciu poprawnych instrukcji,
przekroczeniu zakresów zmiennych (kontrola przez opcję menu Options - Compiler...- Runtime errors - Range checking)
braku możliwości wykonania operacji systemowych,
niewłaściwej operacji matematycznej np. dzielenie przez 0, logarytm z liczby ujemnej itp.
Kombinacja CTRL+Break umożliwia przerwanie "zawieszonego" programu.
Edytor Turbo Pascala
Standardowo pliki pisane w języku Turbo Pascal mają rozszerzenie pas.
Operacje edytorskie mogą się odbywać przez aktywizację pozycji menu, użycie klawiszy nawigacyjnych lub naciśnięcie CTRL+znak (lub CTRL+znak1(Q lub K) a następnie znak2).
Podstawowe operacje edycyjne przedstawia poniższa tabela:
Tabela 3.
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 małego bloku |
SHIFT+klawisze nawigacyjne |
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 |
Ćwiczenie
1. Uruchomić środowisko języka Turbo Pascal.
2. Napisać w edytorze środowiska tekst przykładowego, prostego programu:
program test ;
begin
writeln(' To jest mój program testowy')
end.
3. Przetestować operacje edycyjne: nawigację po tekście, zaznaczanie słowa, wiersza, kilku wierszy, kasowanie i dopisywanie (w trybie zastępowania i wstawiania), kopiowanie i przenoszenie tekstu z zaznaczaniem bloku, wyszukiwanie ciągu znaków, korzystając z tabeli 3. Zaznaczyć blok tekstu (3 kompletne wiersze) i wykonać jego wcięcie i ponowne wysunięcie. Korzystać ze skrótów klawiszowych zamieszczonych w tabeli.
4. Wykonać operację menu: File - DOS Shell. W trybie DOS utworzyć nowy folder PROGRAMY na dysku roboczym. Wrócić do edytora wpisując polecenie exit. Plik źródłowy zapisać w utworzonym folderze prze operację menu File - Save lub skrót F2 nadając plikowi własną nazwę. Zaobserwować zmianę nazwy w szyldzie okna.
5. Otworzyć nowe okno operacją File - New. Przełączać okna operacją ALT+nr_okna. Rozmieszczać okna na ekranie korzystając z myszki lub (jeśli jest niedostępna) przez operacje menu Window - Size, korzystając z podpowiedzi w pasku stanu. Zapisać plik z okna drugiego na dyskietce.
6. Skopiować tekst programu z okna 1 do okna 2 korzystając z menu Edit (Cut, Copy, Paste). Uaktywnić okno schowka przez operację menu Edit - Show Clipboard.
7. Wykonać kompilację programu (F9). Zaobserwować błędy. Jeśli ich nie będzie wprowadzać celowo błędne postaci słowa kluczowego program, nazwy podprogramu writeln, brak średnika po linii tytułowej, brak kropki na końcu programu itp.. Za każdy razem obserwować komunikaty o błędach.
8. W menu Compile wybrać pozycję Destination memory - spowoduje to zmianę na Destination disk, co oznacza, że odtąd po skompilowaniu programu źródłowego powstanie na dysku plik wykonywalny z rozszerzeniem exe. Sprawdzić w menu Options -Directories... jaki jest docelowy folder dla plików wykonywalnych. Przeprowadzić kompilację programu przykładowego, uruchomić DOS-Shell i znaleźć plik wykonywalny.
9. Wykonać program (CTRL+F9). Przełączyć się na okno Output (ALT+F5), obejrzeć ekran wyników programu. Powrócić do edytora (ALT+F5). Wykonać ponownie program. Otworzyć okno Output w postaci okienkowej (menu Debug - Output). Obejrzeć wynik. Wprowadzić modyfikację tekstu w instrukcji writeln wewnątrz apostrofów. Ponownie wykonać program i obejrzeć rezultaty.
10. Poniżej instrukcji writeln wpisać inne instrukcje tej samej postaci (instrukcje powinny być oddzielone średnikami ;), wyprowadzające na ekran inne, dowolne teksty.
writeln ('................');
writeln ('................ ');
Zaobserwować rezultaty na ekranie Output
SKŁADOWE JĘZYKA. DEKLARACJE.
INSTRUKCJA PRZYPISANIA.
Struktura blokowa programu i podprogramów
Rys.2.1 Struktura programu źródłowego w jeśyku Turbo Pascal.
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 jest opcjonalny (czyli nieobowiązkowy) i składa się z:
- słowa kluczowego program i identyfikatora (nazwy) o długości do 255 znaków,
- opcjonalnych parametrów programu w nawiasie - -nazw plików wejścia i wyjścia (standardowo INPUT oraz OUTPUT).
W sekcji deklaracji opisujemy elementy używane przez program (deklaracje i definicje). Istotna jest kolejność, np. wcześniej powinna wystąpić definicja typu a potem deklaracja zmiennej tego typu.
W sekcji instrukcji występują kolejne akcje jakie ma wykonać program.
UWAGA:
BEGIN END to początek i koniec sekcji instrukcji,
kropka kończy tekst programu źródłowego, teksty po kropce są ignorowane,
INSTRUKCJE są oddzielane średnikami.
Alfabet języka
Na alfabet języka składają się:
- duże i małe litery alfabetu łacińskiego (rozróżnialne tylko dla stałych tekstowych)
- cyfry 0 do 9
- jednoznakowe symbole specjalne:
+ - * / = < > [ ] .
, : ; ( ) { } ^ # $ @
- dwuznakowe symbole specjalne:
< > < = > = := . .
Podstawowe słowa kluczowe to:
AND |
DOWNTO |
IF |
PROCEDURE |
TYPE |
ARRAY |
ELSE |
IN |
PROGRAM |
UNTIL |
BEGIN |
END |
LABEL |
RECORD |
USES |
CASE |
FILE |
MOD |
REPEAT |
VAR |
CONST |
FOR |
NOT |
SET |
WHILE |
DIV |
FUNCTION |
OF |
THEN |
WITH |
DO |
GOTO |
OR |
TO |
|
Identyfikatory (nazwy)
Identyfikatory własne nadaje użytkownik dla programu, obiektów (zmiennych), typów, podprogramów, modułów. Identyfikatory to nazwy złożone z ciągu znaków.
Identyfikatory standardowe (zastrzeżone):
typów danych - boolean, char, integer, real, string i inne,
stałych - false, true, maxint,
funkcji - abs, sin, cos, sqr, sqrt, exp i inne,
procedur - read, readln, reset, rewrite, write, writeln i inne,
plików - input, output.
Dla większości identyfikatorów standardowych ich użycie jako własnych jest dopuszczalne lecz powoduje przedefiniowanie ich pierwotnego znaczenia.
Zasady tworzenia identyfikatorów (nazw) 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ść identyfikatora do 255 znaków
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.
Komentarz
Komentarz (własne uwagi lub opis działań) ma postać dowolnego ciągu znaków w nawiasach klamrowych:
{ dowolny fragment programu }
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.
Separatory
Separator nagłówka programu, deklaracji i instrukcji to średnik ";"
Separatory symboli języka to:
spacja (lub ciąg spacji), ENTER, komentarz
z tym że:
dwa dowolne słowa kluczowe, identyfikatory lub liczby bez znaku muszą być oddzielone co najmniej jednym separatorem,
ciąg spacji jest równoważny jednej spacji,
po instrukcjach, po których występuje słowo kluczowe END średnik nie jest wymagany.
Stałe (literały)
Stałe liczbowe
całkowite
Stałą liczbową całkowitą jest 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)
liczby w układzie szesnastkowym
Stałą w układzie szesnastkowym poprzedzamy znakiem $.
Przykłady: $5 $FFF $1A12
rzeczywiste
Stałą liczbową rzeczywistą zapisujemy w dwóch formatach:
Zapis stałopozycyjny
[{±}]m.n gdzie m i n to liczby całkowite, dodatnie
Uwaga: w nawiasach klamrowych { } - elementy do wyboru,
w nawiasach kwadratowych [ ] - elementy opcjonalne (mogą zostać pominięte).
Separatorem części całkowitej i ułamkowej jest kropka ! (nie przecinek)
Przykłady: 2.333 -456.0
NIE WOLNO: .45 brak części całkowitej
WOLNO: 234. brak 0 po kropce dziesiętnej
Zapis zmiennopozycyjny (wykładniczy)
[-]m[.n]
[-]k
gdzie m, n, k to liczby całkowite dodatnie.
Elementy w nawiasach [ ] opcjonalne, w nawiasach {} do wyboru.
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}
UWAGA: Zakresy dla różnych podtypów są różne !!!!
Stałe łańcuchowe
Stałą łańcuchową (tekstową) jest ciąg znaków ograniczonych apostrofami.
Przykłady: 'Turbo Pascal' 'a'
Stałe logiczne
Wartości logiczne nadawane zmiennym i wyrażeniom typu logicznego boolean to:
True - prawda False - fałsz
Deklaracje i definicje
Deklaracja modułów.
Moduły są to biblioteki gotowych 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 ;
Definicje stałych (nazw literałów) i ich wartości.
Stałe są nazwanymi 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';
Definicja typu
Definicja typu jest nazwanym opisem typu, używanym potem w deklaracjach zmiennych.
type nazwa_typu1 = opis_typu1 ; nazwa_typu2 = opis_typu2 ; .....;
np. type
dni_tyg = (po,wt,sr,cz,pi,so,ni); {typ wyliczeniowy}
ck = 1..20; {typ okrojony}
napis = string[30]; {typ łańcuchowy o długości max. 30 znaków}
Typ wyliczeniowy i okrojony poznamy dokładnie później.
W przypadku stosowania jedynie typów standardowych blok type nie jest potrzebny.
Deklaracje zmiennych.
Deklaracje wprowadzonych przez użytkownika zmiennych umieszczamy w bloku poprzedzonym słowem kluczowym var, w następującej, ogólnej postaci:
var lista nazw zmiennych: nazwa_typu1;
lista nazw zmiennych: nazwa_typu2;
....;
Przykładowe deklaracje:
var
x, suma, v15: integer;
wynik1: real;
znak: char;
czy_jest: boolean;
nazwisko, imie: napis; { typ wcześniej opisany}
var alfa : dni_tyg; { typ wcześniej opisany}
x , y , z : ck; { typ wcześniej opisany}
Można również stosować opisy typów w deklaracji zmiennych, na przykład:
var
liczby : 1..23;
dni : (pon, wto, sro, czw, pia, sob, nie);
W niektórych sytuacjach (na przykład przy zastosowaniu funkcji i procedur), konieczne będzie wprowadzenie nazw typów opisywanych przez użytkownika.
Klasyfikacja typów danych
Każda stała, zmienna, wyrażenie lub funkcja jest określonego typu - pozwala to uniezależnić się od fizycznej reprezentacji obiektów w pamięci operacyjnej, umożliwia kontrolę dozwolonych wartości dla danego typu.
Typ określa:
Zbiór wartości, do którego należy stała, bądź jakie może przyjmować zmienna czy wyrażenie, lub jakie mogą być generowane przez funkcję,
Zbiór operacji jakie mogą być wykonywane przez funkcję.
Typy oferowane przez język Turbo Pascal:
standardowe typy proste - integer, real, word, byte, boolean, char i inne,
standardowy typ strukturalny - string,
niestandardowe typy proste - okrojony, wyliczeniowy,
niestandardowe typy strukturalne: tablicowy, zbiorowy, rekordowy, plikowy.
Typ standardowy to zbiór wartości i operacje zdefiniowane w języku, z których użytkownik może korzystać bez ich definiowania.
Typy strukturalne (złożone) - wprowadzone w związku z praktycznymi potrzebami reprezentacji danych.
W sekcji instrukcji wolno używać tylko identyfikatorów standardowych i takich, których znaczenie określono w sekcji deklaracji.
Rys. 2.2 Klasyfikacja typów danych.
Typy proste (porządkowe i rzeczywiste)
Typy porządkowe
Typy całkowite
Podstawowy typ całkowity to typ integer. Używamy go w deklaracji zmiennych w przykładowej postaci:
var x, y: integer;
Zakres typu integer zależy od implementacji - dla komputera PC stała Maxint określa maksymalną wartość dla tego typu i jest równa 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 |
Typ znakowy - char
Zmienne tego typu mogą przyjmować wartości pojedynczego znaku.
Przykład:
var znak : char;
begin
znak := 'c'; {operacja przypisania - nadania wartości}
.....
end.
Typ logiczny - boolean
Zmienne tego typu mogą przyjmować wartości stałych logicznych true lub false.
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)
Można zastosować opis typu bezpośrednio przy deklaracji zmiennych:
var
forma: (prostokat, kwadrat, elipsa, okrag);
dzien: (po, wt, sr, cz, pi, so, ni);
lub wcześniej opisać typ
type
figura=(prostokat, kwadrat, elipsa, okrag);
dni = (po, wt, sr, cz, pi, so, ni);
var
forma : figura;
dzien : dni;
Dopuszcza się wykonywanie 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 {poprzedni element}
ord(wt) 1 {licznik kolejności - liczony od 0}
Dla obiektów tego typu nie wolno stosować operacji arytmetycznych oraz wykorzystywać zmiennych tego typu w instrukcjach wprowadzania i wyprowadzania danych (read/write).
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
dzien : (po, wt, sr, cz, pi, so, ni); {zmienna bazowego typu wyliczeniowego}
zakres: 1..10; {podzbiór typu integer}
cyfra: '0'..'9'; {podzbiór typu char}
dni_wolne: so .. ni;
Operacje i funkcje obowiązują jak dla typu bazowego.
Typy rzeczywiste
Typy rzeczywiste używane są dla zmiennych przyjmujących wartość liczbową rzeczywistą. Podstawowym typem jest tu typ real.
Tabela typów rzeczywistych:
Nazwa typu |
Najmniejsza wartość dodatnia |
Największa 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 1: opcje pakietu dopuszczają brak sprawdzania zakresów w trakcie wykonania programu, w menu Options - Compiler - Runtime errors - Range checking można uaktywnić sprawdzanie zakresów.
UWAGA 2: PAMIĘĆ: Char - 1 bajt, Integer - 2 bajty, Real - 6 bajtów inne więcej.
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}
....
end.
Instrukcja przypisania
Instrukcja przypisania jest podstawową, prostą instrukcją w większości języków programowania. Przy jej pomocy zmiennym nadawane są wartości w trakcie wykonywania programu.
identyfikator zmiennej := wyrażenie;
: = dwuznakowy operator przypisania
Najprostsza postać wyrażenia to stała lub zmienna:
W → stała
W → zmienna
W instrukcji przypisania zmiennej o identyfikatorze z lewej strony znaku przypisania nadawana jest wartość obliczonego wyrażenia obecnego po prawej stronie operatora.
UWAGA: Zachodzi konieczność zachowania zgodności typów zmiennej i wyrażenia (wyjątkiem jest dopuszczenie przypisania zmiennej typu real wartości wyrażenia typu integer)
Ćwiczenie
1. Wpisać tekst następującego programu, którego zadaniem jest nadanie wartości zdefiniowanym zmiennym prostym rożnych typów. W programie brak jest oczywiście instrukcji wyprowadzających wartości zmiennych na ekran.
program deklaracje;
type
figury = (kwadrat, trojkat, kolo);
napis_krotki = string [5];
var
litera: char;
liczba: integer;
godzina, minuta, sekunda: 1..60;
ilosc, suma: real;
napis_tytulowy : string;
etykieta: napis_krotki;
figura : figury;
czy : boolean;
begin
litera :='A';
godzina := 12;
minuta := 45;
napis_tytulowy := 'To jest napis' ;
ilosc := 12.56 ;
suma := ilosc;
figura := kwadrat ;
czy := false ;
end.
2. Uaktywnić okno Watch (menu Debug - Watch). W oknie podglądu wartości zmiennych wstawić (klawisz Insert - Add Watch a następnie wpisanie nazwy zmiennej obserwowanej) wybrane nazwy zmiennych (np. litera, godzina, czy). Wykonywać program krok po kroku (F7) obserwując wartości zmiennych po wykonaniu kolejnych instrukcji.
3. Dokonać próby nadania zmiennym wartości innych typów niż zadeklarowane, na przykład zmiennej logicznej czy nadać dowolną wartość liczbową, czy zmiennej całkowitej godzina wartość rzeczywistą 4.5. Zaobserwować, że nadanie zmiennej ilosc, która jest typu real wartości całkowitej nie powoduje błędu.
4. Wpisać tekst poniższego przykładu:
program wartosci;
const
e = 2.71828;
l_pi = 3.1415926;
fraza = 'Koniec danych';
symbol = ':=' ;
var
litera: char;
godzina: 0..24;
minuta, sekunda: 1..60;
ilosc, suma: real;
napis_tytulowy: string;
begin
godzina := 12 ;
minuta := 23 ;
litera := 'C' ;
ilosc := 56.87e4;
napis_tytulowy :='Wykres `funkcji';
minuta := 24
end.
5. W menu Options - Compiler zaznaczyć w bloku Runtime errors opcję Range checking (sprawdzanie zakresów). Wprowadzić zmiany w programie tak, wartości przekraczały dopuszczalne zakresy, np. dla zmiennej Minuta wartość 100. Uruchomić program i zaobserwować komunikat o błędzie.
Wyrażenia arytmetyczne i logiczne.
Wprowadzanie i wyprowadzanie danych.
Definicja 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.
Bardziej skomplikowane wyrażenia zawierają operatory i funkcje. Ponadto używamy nawiasów (okrągłych!) w celu zmiany hierarchii działań.
Definicja rekurencyjna wyrażenia (czyli definiowanie przez samą siebie) ma postać:
wyrażenie → stała
wyrażenie → zmienna
wyrażenie → funkcja(wyrażenie)
wyrażenie → wyrażenie operator wyrażenie
Z definicji wynika, że wyrażenia po prawej stronie definicji mogą mieć każdą z postaci definiowanych a zatem np. wyrażenie w nawiasie funkcji może być inną funkcją (tzw. zagnieżdżanie funkcji), operatorami można łączyć wiele wyrażeń itp. Wyrażenia używane są najczęściej w instrukcjach przypisania po prawej stronie znaku :=. Dopuszczalne jest użycie wyrażeń arytmetycznych i logicznych jako parametru procedury wyprowadzania danych (write, writeln) a także w innych instrukcjach zgodnie z zasadami ich składni.
Operatory arytmetyczne
Rozróżniamy następujące operatory:
- 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,
(gdzie znak przedstawia spację),
- 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 |
Hierarchię wykonywania operacji określają następujące reguły:
- nawiasy są najważniejsze (od najbardziej wewnętrznych),
- waga operatorów:
1. jednoargumentowe - najwcześniej wykonywane,
2. multiplikatywne,
3. addytywne - wykonywane na końcu.
Uwaga:
- dla operatorów tej samej wagi - kolejność działań od lewej do prawej,
- jeżeli w wyrażeniu są tylko argumenty całkowite i nie ma dzielenia rzeczywistego to wynik jest typu integer,
- jeżeli występuje chociaż jeden element typu real lub dzielenie jest rzeczywiste to wynik jest typu real.
Na elementach tekstowych (char, string) możemy dokonywać operacji łączenia tekstów (tzw. konkatenacja) używając znaku +,
Przykładowo:
nazwisko := 'Kowalski';
tekst_1 := 'Pan ' + nazwisko ;
W rezultacie zmienna tekst_1 przyjmie wartość tekstową 'Pan Kowalski'.
Funkcje standardowe
Istnieje możliwość użycia w wyrażeniu funkcji standardowych (w kontekście identycznym jak zmienne proste) w postaci:
identyfikator_funkcji (argument)
Argumentem może być wyrażenie odpowiedniego typu. Zestaw funkcji standardowych przedstawia tabela.
TABELA. Funkcje standardowe.
Znaczenie |
Nazwa funkcji |
Typ wyniku |
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 |
pi |
rzeczywisty |
brak (jest to stała predefiniowana) |
sin(30*pi/180) |
Część całkowita |
int |
rzeczywisty |
całkowity rzeczywisty |
int(2.5) 2.0 |
Część ułamkowa |
frac |
rzeczywisty |
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)),
a w przypadku wyższych lub niecałkowitych potęg stosujemy zapis:
xy exp (yln (x))
Brak w języku również innych, często potrzebnych funkcji, jak na przykład tangens czy logarytm dziesiętny. Trzeba wówczas radzić sobie korzystając z elementarnych definicji matematycznych:
Należy zwrócić uwagę na możliwość wystąpienia przekroczenia dopuszczalnych zakresów przy obliczeniach.
Przykładowo poniższe wyrażenie w postaci matematycznej:
należy zapisać w postaci:
(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; {powiększenie wartości x o 5}
...
w wyniku uzyskuje się x równe 27.
Funkcje standardowe nie wymagają deklaracji ich użycia ani deklaracji modułu System, w którym są umieszczone.
Możliwe jest stosowanie także funkcji, które umieszczone są w modułach bibliotecznych, np. Crt, Graph i in.. Ich użycie wymaga odpowiedniej deklaracji modułu, np.:
uses crt ;
Użyteczne są funkcje biblioteczne modułu crt:
- clrscr procedura czyszczenia ekranu
- bezparametrowa funkcja readkey, która służy do wczytania z klawiatury jednego znaku,
- bezparametrowa funkcja logiczna keypressed, która służy do sprawdzenia naciśnięcia dowolnego klawisza.
Uwaga na:
operatory arytmetyczne - szczególnie mnożenia - 2*x a nie 2x
format wykładniczy - 1.34E-8, 1e7 a nie e7
argumenty funkcji trygonometrycznych - podajemy je w radianach, w przypadku konieczności używania kąta w stopniach należy przeliczyć na radiany wyrażeniem alfa*pi/180,
hierarchię działań - nawiasy
brak potęgowania, brak funkcji tangens i cotangens, logarytm dziesiętny,
różnicę między funkcjami o podobnych nazwach - SQR i SQRT.
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_relacji 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 zmiennej logicznej musi zachodzić zgodność typów.
Przykład:
program p3;
var
zwolniony, obecny: boolean ;
ocena: real ;
liczba_ob: integer ;
begin
readln (ocena) ;
readln (liczba_ob) ;
obecny := liczba_ob>=6;
zwolniony := (ocena >= 4.5) and obecny ;
writeln(zwolniony) {przed end nie musimy wstawiać średnika}
end.
Standardowe procedury czytania i wyprowadzania danych
Do wprowadzenia (standardowo z klawiatury) wartości zmiennej w trakcie wykonania programu służy procedura:
[(lista zmiennych)];
Np. readln (x1, x2, x3, y);
read(x);
Po napotkaniu instrukcji program zatrzymuje się i oczekuje podania danych o typach wynikających z typu zmiennych. Dane 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:
[ (lista elementów) ];
Po wykonaniu instrukcji write kursor pozostaje na końcu wiersza zaś po writeln następuje zmiana wiersza. Instrukcja writeln bez parametrów wyprowadza pusty wiersz.
Elementami listy są stałe, zmienne i wyrażenia wraz z opcjonalnym określeniem formatu wyprowadzenia o postaci:
wyrażenie:m gdzie m to wyrażenie całkowite określające szerokość pola (liczba znaków), dla liczb typu real m 8, jeżeli mniejsze (np. 0) to szerokość dopasowana będzie do niezbędnej liczby cyfr do zapisu wartości (z ewentualnym znakiem),
wyrażenie:m:n m - jak wyżej, n - liczba cyfr po kropce dziesiętnej (tylko typ real).
Przykład:
var x:real ; y:string;
begin
x := -21.546;
y := ' Napis= ';
writeln ; {wyprowadzenie pustego wiersza)
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.
Ćwiczenie
Wpisać tekst programu:
program p3_1;
var pensja1,pensja2, srednia: real;begin
(Wprowadzanie danych}
write ('Podaj pensję pierwszą:' ) ; readln(pensja1); write ('Podaj pensję drugą:' ); readln(pensja2);
{Obliczenie średniej} srednia := (pensja1+pensja2)/2;
{Wyprowadzenie wyników}
writeln ; {pusty wiersz}
writeln ('pensja pierwsza:', pensja1:10:2, ' zł'); writeln ('pensja druga :', pensja2:10:2, ' zł'); writeln('Średnia wynosi:':43, srednia:10:2);end.
Wykonać program i obejrzeć wyniki. Wykonać ponownie program zmieniając wartości wprowadzanych danych. Zmienić format wyprowadzanych danych, np. 15:4. Następnie usunąć parametry formatu w procedurze writeln jak poniżej:
writeln ('pensja pierwsza:', pensja1, ' tys. zl');
writeln ('pensja druga :', pensja2, ' tys. zl');
writeln('Średnia :', srednia);
i wykonać program, obserwując postać wyprowadzonych wartości w formacie wykładniczym.
Wprowadzić po nagłówku programu deklarację:
uses crt;
a następnie procedurę czyszczącą ekran:
clrscr;
jako pierwszą instrukcję wykonywalną. Zaobserwować pojawienie się wyników na wyczyszczonym ekranie output przy kolejnych wykonaniach programu.
Zmodyfikować program tak, aby liczył średnią dla trzech liczb o wartościach wprowadzanych klawiatury.
Napisać program:
program p3_2;
uses crt;
var a, b, c, d: integer;
log1, log2, log3: boolean ;
begin
clrscr ;
writeln ('Podaj 2 liczby całkowite oddzielone spacja' );
readln (a, b);
c:= a div b;
d:= a mod b;
log1 := a>0;
log2 := a<>b;
log3 := (a< 5) and (b>= -5);
writeln ('a=', a:3);
writeln ('b=', b:3);
writeln ('c=', c:3);
writeln ('d=', d:3);
writeln (log1:10, log2:10 , log3:10)
end.
Wykonać program kilkukrotnie dla różnych wartości a i b. Przeanalizować otrzymane wartości numeryczne c i d oraz logiczne.
Napisać program, w którym dla zadanej wartości x (np. 3.45) obliczane są wartości następujących wyrażeń i wyprowadzane wyniki na ekran Output:
;
;
;
Sprawdzić zapis wyrażeń, zwracając uwagę na obecność operatorów (szczególnie operatora mnożenia), obecność nawiasów decydujących o hierarchii działań, prawidłowe nazwy funkcji, obowiązkową obecność nawiasów po nazwie funkcji itp. Wykonać program wprowadzając różne wartości x, zwrócić uwagę na błędy wykonania wynikające z niewłaściwych obszarów określoności dla funkcji. Wprowadzać celowo błędy w wyrażeniach, np. brak nawiasów, przekręcone nazwy funkcji itp., zaobserwować wynikające stąd błędy kompilacji.
Napisać program, którego zadaniem będzie znajdowanie kodu ASCII wprowadzanego przez użytkownika znaku.
Napisać program, którego zadaniem będzie znajdowanie znaku o podanym przez użytkownika kodzie ASCII.
Napisać program, który po nadaniu kilku zmiennym wartości tekstowych wypisze je na ekranie:
w jednym wierszu obok siebie,
w osobnych wierszach jeden pod drugim z wyrównaniem do lewej,
w osobnych wierszach jeden pod drugim z przesunięciem w prawo, np.:
tygrys
pantera
piesek
krokodyl
jak wyżej lecz z odstępami międzywierszowymi.
Zadanie do samodzielnego wykonania w domu: Napisać program, w którym zadeklarowane 2 zmienne tekstowe przyjmują wartości dwóch nazwisk wczytywanych z klawiatury w trakcie przebiegu programu. Program sprawdza czy pierwsze nazwisko jest wcześniejsze w kolejności alfabetycznej i umieszcza wynik testu w zmiennej logicznej a następnie wyprowadza jej wartość na ekran.
Schematy blokowe. Instrukcje warunkowe.
Reguły graficzne tworzenia schematów blokowych.
Start i stop
Operacje wejścia i wyjścia
Instrukcja wykonawcza (proces) Blok decyzyjny
Łącznik stronicowy
Rys.4.1. Symbole operacji używane na schematach blokowych.
Klasyfikacja instrukcji.
Rys.4.2 Klasyfikacja instukcji w języku Turbo Pascal.
Instrukcje warunkowe.
Instrukcja if.. then ( jeżeli.. to).
Postać skrócona :
if WB then Instrukcja;
jeżeli" "to"
W instrukcji wykonywane jest badanie warunku logicznego WB a następnie:
- jeśli WB = true to Instrukcja jest wykonywana,
- jeśli WB = false to Instrukcja jest ignorowana.
Postać pełna:
if WB then Instrukcja_1 else Instrukcja_2;
"jeżeli" "to" "w przeciwnym przypadku"
Wykonywane jest badanie warunku:
- jeśli WB = true to wykonywana jest Instrukcja_1,
- jeśli WB = false to wykonywana jest Instrukcja_2.
Instrukcja if.. then.. należy do grupy instrukcji strukturalnych - w jej skład wchodzi inna instrukcja (prosta lub strukturalna).
Schematy blokowe ilustrujące działanie obu postaci instrukcji ilustruje rysunek.
postać skrócona postać pełna
Rys.4.3 Schemat blokowy istrukcji if.. then..
Przykład:
program p4_1;
uses crt;
var x : real ;
begin
clrscr ;
readln(x);
if x = 0 then writeln ( ' Pierwiastek z x wynosi:', sqrt(x):10:3)
else writeln ( 'x jest ujemne' );
readln
end.
W przykładzie tym instrukcja wyprowadzająca wartość pierwiastka wykonana zostanie jeżeli zajdzie warunek x>=0, w przeciwnym wypadku zostanie wykonana instrukcja wyprowadzająca komunikat, że x jest ujemne.
Instrukcje wewnętrzne if mogą także być innymi instrukcjami if. Taką postać stosujemy w przypadku konieczności wykonania różnych instrukcji dla trzech przedziałów wartości zmiennej, sprawdzanej w wyrażeniu logicznym.
Przykład 1:
program p4_2;
uses crt;
var x : real;
begin
clrscr;
readln (x);
if (x 0) then writeln ('x dodatnie' )
else if (x<0) then
writeln ('x ujemne' )
else writeln ('x=0' );
readln {zatrzymanie ekranu OUTPUT}
end.
Przykład 2:
if (x 0) then y := 5
else if (x<0) then y := 6
else y := 7;
Po wykonaniu powyższej instrukcji if odbędą się przypisania:
y → 5 dla x>0
y → 6 dla x<0
y → 7 dla x=0
Instrukcja wyboru - case
Instrukcja case umożliwia alternatywne wykonanie wielu instrukcji w zależności od wartości wyrażenia typu porządkowego. 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 (np. 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 odpowiadająca wartości (wartościom, zakresowi) stałej wyboru.
Instrukcja w opcjonalnym bloku po else wykonywana jest dla wartości nie występującej wcześniej. W listach wyboru można powtarzać te same wartości.
Przykład:
...
readln(miesiac);
case miesiac of
2: dni := 28;
4, 6 , 9, 10: dni := 30;
1..12: dni := 31; {lub else dni := 31}
end ;
Instrukcja złożona (sekwencji).
W przypadku konieczności wykonania więcej niż jednej instrukcji wewnątrz dowolnej instrukcji strukturalnej stosujemy tzw. instrukcję złożoną (sekwencji):
begin
ciąg instrukcji
end;
Przykład:
if x = 0 then
begin
y := y+5;
writeln(y:10:3)
end
else writeln('x jest ujemne');
W przykładzie tym obie instrukcje pomiędzy słowami kluczowymi begin i end wykonane zostaną jeżeli zajdzie warunek x>=0, w przeciwnym wypadku zostanie wykonana instrukcja wyprowadzająca komunikat, że x jest ujemne.
Ćwiczenie
Napisać tekst programu p4_1. Wykonać program kilkukrotnie wprowadzając wartości x dodatnie i ujemne. Wykonać program krok po kroku obserwując które instrukcje są wykonywane wewnątrz instrukcji warunkowej.
Napisać tekst programu p4_2. Wykonać program kilkukrotnie wprowadzając wartości x dodatnie i ujemne. Wykonać program krok po kroku, obserwując które instrukcje są wykonywane wewnątrz zagnieżdżanej instrukcji warunkowej.
Napisać tekst programu p4_3. Wykonać program kilkukrotnie wprowadzając różne wartości zmiennej miesiac. Wykonać program krok po kroku.
Zmodyfikować program p4_3 tak, aby dni lutego były równe 28 lub 29 w zależności od tego czy rok jest przestępny (wskazówka: badać przy pomocy instrukcji if.. then.. resztę z dzielenia roku przez 4).
Wpisać tekst programu:
program test4_4;
var p1, p2, p3: real;
spr : boolean;begin
p1:= 34.56; {kąt w stopniach}
p2:= sin(p1*pi/180);
if p2>0 then writeln(' Funkcja ma wartość dodatnią')
else writeln(' Funkcja ma wartość ujemną')
end.
lub
...
begin
p1:= 34.56;
p2:= sin(p1*pi/180);
spr := p2>0;
if spr then writeln(' Funkcja ma wartość dodatnią')
else writeln(' Funkcja ma wartość ujemną')
end.
Przetestować obie wersje programu. Zmodyfikować jego treść tak, aby wartość zmiennej p1 była wprowadzana z klawiatury w trakcie wykonania programu.
Wykonać i przetestować poniższy program, którego zadaniem jest obliczanie pierwiastków równania kwadratowego.
program p4_5;
uses crt;
var
a, b, c, delta, x1, x2: real;
begin
clrscr;
writeln('Podaj współczynniki równania 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 pierwiastków 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 równania kwadratowego');
writeln('x1=':20,x1:10:2);
writeln('x2=':20,x2:10:2)
end;
readln;
end .
Wpisać tekst i przeanalizować poniższy program (instrukcja case z zagnieżdżaniem):
program test4_6;
uses crt;
var nr: integer;
begin
clrscr;
write('Podaj numer miesiąca:');
readln(nr);
case nr of
4,6,9,11:writeln('Miesiąc ma 30 dni');
2: writeln('Miesiąc luty ma 28 lub 29 dni')
else
case nr of
1..12 : writeln('Miesiąc ma 31 dni');
else writeln('Nie ma takiego miesiąca')
end;
end;
end.
Wykonać program i kilkakrotnie przetestować jego działanie.
Zadania do samodzielnego wykonania:
Napisać tekst programu, który wprowadza dowolny rok z przedziału 0 do 4000 i sprawdza czy jest on przestępny. Wskazówka: Zastosować sprawdzanie czy reszta z całkowitego dzielenia roku przez 4 jest równa zero.
Napisać program, który bada podzielność wprowadzanej liczby całkowitej przez 2 i w zależności od reszty z dzielenia (0 lub 1) wyprowadza komunikat czy liczba jest parzysta czy nieparzysta.
Instrukcje iteracyjne (1)
Instrukcja for.. do.. (dla.. wykonuj..)
for Z := Wi1
Wi2 do Instrukcja;
Z - zmienna sterująca, typu porządkowego (np. całkowitego lub znakowego),
Wi1 i Wi2 - wyrażenia tego samego typu.
Wersja z to Wersja z downto
Rys. 5.1 . Schemat blokowy działania instrukcji for.. do.. .
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 3-krotnie wykonanej iteracji x przyjmie wartość 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 lecz wolno (i często się to robi) używać zmiennej sterującej w wyrażeniach.
Instrukcją wewnętrzną może być dowolna instrukcja, także inna instrukcja for (zagnieżdżanie iteracji) też instrukcja złożona.
Przykłady:
program p5_1;
var i: integer;
j: char;
begin
for i := 1 to 10 do
begin
for j := 'a' to 'd' do write('');
writeln
end
end.
Zmienna sterująca i przyjmuje wartość 1 i wykonywane są instrukcje wewnętrzne (w tym wewnętrzne for..do..), następnie wartość i zwiększana jest o 1, ponownie wykonywane instrukcje wewnętrzne, itd. Program wyprowadza 10 wierszy po 4 gwiazdki w wierszu.
Drugi przykład zawiera użycie zmiennej sterującej w wyrażeniach:
program p5_2;
var i: integer;
z : real;
begin
z := 2;
for i := 1 to 3 do
begin
z := z + 3 * i;
writeln (z:5*i:2)
end
end.
Efektem programu będzie wyprowadzenie wartości:
5.00 (na 5-ciu pozycjach)
11.00 (na 10-ciu pozycjach)
20.00 (na 15-tu pozycjach)
Ćwiczenie
Wpisać teksty programów przykładowych z rozdziału, w razie potrzeby uzupełniając je o odpowiednie deklaracje, przypisania i instrukcje wyprowadzające wartości zmiennych na ekran Output. Wykonać programy przykładowe używając krokowego śledzenia wartości zmiennych. Testować zmiany zakresów zmiennych sterujących iteracji. W przykładzie p5_1 zmienić typ zmiennej j ze znakowego na całkowity i dokonać odpowiednie korekty w treści programu.
Przetestować program obliczający sumę kolejnych N liczb nieparzystych.
program p5_3;
uses crt;
var i, N, suma: integer;
begin
clrscr ;
suma:=0 ;
write ( 'Podaj ile liczb nieparzystych chcesz sumować:' ) ;
readln( N);
for i := 1 to N do
suma:= suma+ 2*i -1;
writeln ( ' Suma wynosi: ',suma:10);
readln
end.
Opracować program obliczający wartość N! (silnia) dla podawanej liczby N. Przetestować zakres liczb N dla których program działa prawidłowo. Wprowadzić w programie instrukcję warunkową uniemożliwiającą wprowadzenie N spoza zakresu i żądającą ponownego podania liczby N w dopuszczalnym przedziale.
Opracować program tabelaryzujący funkcję, czyli wyprowadzający na ekran kolejne wartości funkcji dla różnych argumentów. 91 Stabelaryzować funkcje sinx i cosx dla wartości kątów od 0 do 90 stopni.
Instrukcje iteracyjne (2)
Instrukcja repeat.. until.. (powtarzaj .. aż..)
Postać ogólna instrukcji:
repeat
ciąg instrukcji
until WB ;
Ciąg instrukcji wewnętrznych w instrukcji repeat..unti 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 co najmniej raz wykonywana. Jedna z instrukcji powinna mieć wpływ na wartość wyrażenia logicznego, w przeciwnym wypadku iteracja nigdy się nie skończy. Jeśli błędny warunek spowoduje nieskończoną pętlę możemy przerwać wykonywanie programu kombinacją klawiszy CTRL+Break.
Rys.6.1 Schemat blokowy instrukcji repeat.. until.. .
Przykład:
program p6_1;
var x: integer;
begin
x := 3;
repeat
x := x + 5;
writeln(x:10)
until x 100;
end.
Program wydrukuje w wierszach kolejne wartości 8, 13.... 103.
Instrukcja while.. do.. (dopóki.. wykonuj..)
Postać ogólna instrukcji:
while WB do Instrukcja;
"dopóki" "wykonuj"
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. Instrukcja wewnętrzna iteracji może być instrukcją złożoną (begin.....instrukcje... end).
Podobnie jak w repeat..until.. istnieje konieczność wykonania wewnątrz iteracji (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.
Rys.6.2 Schemat blokowy instrukcji while.. do..
Przykładowy fragment programu oblicza sumę liczb parzystych od 2 do 100:
program p6_2;
var i,suma:integer;
begin
i := 2;
suma := 0;
while i <= 100 do
begin
suma := suma + i;
i := i + 2;
end;
end.
Ćwiczenie
Wpisać teksty programów przykładowych z rozdziału, w razie potrzeby uzupełniając je o odpowiednie deklaracje, przypisania i instrukcje wyprowadzające wartości zmiennych na ekran Output. W przykładzie p6_1 zamienić miejscami instrukcje wewnętrzne iteracji repeat, sprawdzić i wyjaśnić efekt. Wykonać programy przykładowe używając krokowego śledzenia wartości zmiennych.
Przeanalizować i wykonać poniższy program:
program p6_3;{Przydzielenie do grup wiekowych}
uses crt;
var wiek: integer;
begin
clrscr;
repeat
write( 'Podaj wiek:' );
readln(wiek);
{ if wiek = 0 then break ;}
case wiek of
0 : writeln ( 'Koniec danych' );
1..20 : writeln ( 'GRUPA I' );
21..40 : writeln ( 'GRUPA II' );
41..60 : writeln ( 'GRUPA III' )
else writeln ( 'GRUPA IV' )
end;
until wiek = 0;
writeln ('Naciśnij dowolny klawisz ') ;
repeat until keypressed {X}
end.
Instrukcja {X} jest wielokrotnie wykonywaną iteracją powodującą zatrzymanie ekranu OUTPUT aż do naciśnięcia dowolnego klawisza (funkcja logiczna keypressed pobrana z modułu crt przybiera wówczas wartość true). Uaktywnienie instrukcji w nawiasie klamrowym powoduje przerwanie pętli (procedura break powoduje wcześniejsze zakończenie bieżącej iteracji), sprawdzić to wykonując program krokowo. Czy da się napisać identyczny program ale przy użyciu instrukcji while..do..?
Instrukcje iteracyjne (tego samego lub różnego typu) mogą być zagnieżdżane, jak np. poniżej:
program p6_4;
var a,b,c:integer;
begin
a:=1;
b:=1;
while not (a>=20) do
begin
for c:=2 downto 1 do b:=b+c;
a:=2*b;
end;
writeln( a:5, b:5, c:5)
end.
Przeanalizować powyższy program (bez uruchamiania) i określić końcowe wartości zmiennych a, b, c.
Przetestować krokowo następujący program:
program p6_5;
uses crt;
var znak:char;
begin
write('Naciśnij literę A:');
readln(znak);
while ord(znak)<>65 do
begin
write('To nie ten znak:');
readln(znak)
end; {koniec while}
writeln('Nacisnąłeś A');
repeat until keypressed
end.
Przeanalizować i wykonać poniższy program ilustrujący użycie wszystkich trzech form iteracji w tym samym celu. Wykonywać program "krok po kroku" w celu lepszego zrozumienia zasad działania iteracji.
program p6_6;
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 .
Zadania do samodzielnego wykonania:
Opracować program, w którym podajemy dwie liczby, następnie na ekranie drukowany jest ich iloczyn i iloraz. Operacje powtarzają się aż do podania wartości zero dla pierwszej z liczb zadawanych.
Opracować program, w którym podajemy liczbę, następnie w pętli jest ona dzielona przez 2, wynik znowu przez 2 i tak dalej aż do uzyskania wartości mniejszej niż 10-20. Dodatkowo wprowadzić zmienną zliczającą ile operacji wykonano i wyprowadzić jej wartość na ekran.
Program z pkt. b wzbogacić o wielokrotne jego wykonywanie, tzn. po zakończeniu obliczeń zadawane jest pytanie "czy wykonać obliczenia dla innej liczby?". Naciśnięcie znaku 't' lub 'n' na klawiaturze powoduje odpowiednie działanie programu.
Typ tablicowy array
Typ tablicowy jest typem strukturalnym (złożonym) stanowiącym skończony zbiór elementów tego samego typu, o położeniu określanym przez indeksy. Zmienna typu tablicowego odpowiada w sensie matematycznym tablicy (macierzy).
Opis typu:
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). Wektor jest tablicą 1-wymiarową.
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.
Inne operacje dokonywane być mogą tylko na składowych - jeśli są dozwolone dla ich typu.
Odwołanie do elementu tablicy dokonuje się w postaci:
nazwa_zmiennej [ indeks1, .... ]
Do nadawania wartości poszczególnym elementom tablicy stosuje się instrukcje wprowadzania danych (read) i instrukcje przypisania. Często wykorzystuje się instrukcje for.. do.. gdy poprzez zmienną sterującą iteracji możemy określić indeks (lub indeksy dla tablic wielowymiarowych) oraz użyć zmiennej sterującej w wyrażeniu przypisywanym elementowi tablicy.
W tablicy dwuwymiarowej trudno jest określić, który wymiar opisuje wiersze a który kolumny, gdyż wartości w pamięci operacyjnej układane są "liniowo". Wszystko zależy od "umowy programowej" i odpowiednio dobierając zmienne sterujące zagnieżdżanych iteracji for.. do.. można wyprowadzić tablicę na ekran wierszami lub kolumnami.
Przykład 1:
program p7_1;
uses crt;
var tab1: array [1..5, 1..5] of real;
{lub
type t55= array [1..5, 1..5] of real;
var tab1:t55; }
i, k :1..5;
begin
clrscr;
tab1[2,3] := 0.1; {nadanie wartości elementowi tablicy}
for i := 1 to 5 do tab1[1, i]:= 0.0; {wypełnianie pierwszego wiersza zerami}
for i := 1 to 5 do tab1[i, i]:= i/2; {wypełnianie przekątnej głównej wartościami 0.5 1 1.5 itd.}
for i := 1 to 5 do
for k:= 1 to 5 do tab1[i, k]:= i+2*k; {wypełnianie całej tablicy stałą wartością, zagnieżdżanie iteracji}
for i := 1 to 5 do
begin
for k:= 1 to 5 do write(tab1[i,k]:4:0);
writeln
end; {wydruk na ekranie całej tablicy}
writeln;
for k:= 1 to 5 do
begin
for i:= 1 to 5 do write(tab1[i,k]:4:0);
writeln
end; {wydruk na ekranie całej tablicy transponowanej - zamiana wierszy i kolumn}
end.
Przykład 2:
program p7_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;
x[wt, false]:= 34.0;
writeln(x[wt, false]/100:20:5);
if x[sr,false] > 3e2 then writeln(' W srode za dużo ');
...
end.
Oczywiście tablica typu wek będzie dwuwymiarowa o rozmiarach 7x2.
Przykład 3:
program p7_3;
type opis= (nazw, imie); {wyliczeniowy}
var grupa: array[1..100, opis] of string[30];
i: integer;
begin
...
grupa[1, nazw] := 'Kowalski';
if grupa[i, imie] = 'Stanislaw' then
writeln(grupa[i, nazw]:30, grupa[i, imie]:20);
...
end .
Ćwiczenie
Wpisać teksty programów przykładowych z rozdziału, w razie potrzeby uzupełniając je o odpowiednie instrukcje wyprowadzające wartości zmiennych na ekran Output. Prześledzić krokowo programy, obserwując zmienne w oknie Watch.
Sporządzić kod poniższego programu wyznaczania maksimum i minimum wartości losowych:
program p12_2;
uses crt;
var x : array[1..100] of real;
i, k : 1..100;
max, min : real;
begin
clrscr;
randomize; {procedura inicjująca generator liczb losowych}
for i := 1 to 20 do
for k := 1 to 100 do
x [k] := random (256*256-1) / (256*256-1); {random - funkcja losująca}
{wyznaczenie maksimum i minimum}
max := x [1];
min := x [1];
for k := 2 to 100 do
begin
if x [k] > max then max := x [k ];
if x [k] < min then min := x [k ]
end;
writeln ( 'max=' , max:12:5, 'min=' : 10 , min:12:5);
repeat until keypressed
end.
Przeanalizować strukturę i mechanizmy programu. Wykonać program krokowo obserwując wartości zmiennych w oknie Watch.
Opracować kod programu w którym tablica 5x5 wypełniana jest w pętli kolumnami a jej elementy są:
wartościami średnimi obydwu indeksów,
sumami obydwu indeksów,
różnicami indeksu wiersza i kolumny.
Tablica wyprowadzana jest na ekran.
Opracować kod programu w którym tablica 5x5 wypełniona jest wartościami 1 (wszystkie elementy) a następnie przeciwprzekątna wartościami 2. Tablica wyprowadzana jest na ekran.
Opracować kod programu, w którym wektor o rozmiarze 100 wypełniany jest kwadratami kolejnych liczb parzystych aż do przekroczenia wartości 5000 (pozostałe elementy pozostają wypełnione zerami). Tablica wyprowadzana jest na ekran.
Opracować program wyprowadzający na ekran 30 wierszy trójkąta Pascala, definiowanego w postaci:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
....................................................................
gdzie elementy wiersza są sumą sąsiednich elementów wiersza poprzedniego. Dla elementów nieparzystych drukować znak gwiazdki a dla nieparzystych znak spacji. Wykorzystać zagnieżdżane iteracje for..do..
Typ rekordowy - record
Definicja typu rekordowego
Typ rekordowy jest typem strukturalnym o strukturze jednowymiarowej i o składowych dowolnych typów, które nazywają się polami. Zmiennych typu rekordowego używamy w przypadku konieczności utworzenia obiektu opisywanego zbiorem danych różnego typu.
Opis typu:
record
lista_nazw_pól_1: typ1;
lista_nazw_pól_2: typ2;
........
end;
np.
program p8_1;
type
data = record
rok : 1900..2100;
mies : 1..12;
dzien : 1..31
end;
osoba = record
nazw : string[20];
imie1, imie2 : string[15];
data_ur : data; {typ rekordowy wcześniej zdefiniowany}
mezczyzna : boolean;
rodzenstwo : array[1..5] of string[15]
end;
var student:osoba;
begin
....
end.
Pola rekordu mogą być różnego typu, a zatem także rekordowego, tablicowego itp.
Do pól rekordu istnieje dostęp bezpośredni, odwołanie do pola zmiennej odbywa się przez nazwę zmiennej rekordowej i nazwę pola (tzw. dostęp kwalifikowany), oddzielonych kropką:
nazwa_zmiennej . nazwa_pola {. ewentualna_nazwa_pola_składowego ...}
np.
student . nazw := 'Kowalski';
if student . data_ur.rok < 1975 then ... {pole data_ur jest typu rekordowego}
UWAGI:
W jednym typie rekordowym wszystkie pola muszą mieć różne nazwy,
Dopuszczalne jest całościowe przypisanie jednej zmiennej rekordowej wartości innej zmiennej rekordowej pod warunkiem, że są tego samego typu,
Na zmiennych składowych można dokonywać operacji dopuszczalnych dla ich typu.
Tworzenie wielu zmiennych rekordowych dla zapamiętywania danych strukturalnych w trakcie przebiegu programu jest niewygodne, dlatego też często dane tego typu gromadzi się w tablicy (najczęściej jednowymiarowej).
Jeżeli rekordy znajdują się w tablicy, np.
type osoba: record
nazwisko:string;
imie:string:
wiek:0..100
end;
var grupa: array [1..30] of osoba;
to dostęp do pola pojedynczego rekordu, będącego elementem tej tablicy może się odbyć w przykładowej postaci:
writeln (grupa[5].nazwisko ) {wczytanie do pola nazwisko w 5-tym elemencie tablicy}
lub
grupa[5].nazwisko= 'Kowalski'; {przypisanie}
Przykład:
program p8_2;
type osoba= record
nazwisko, imie :string[20];
data_ur: record
dzien, miesiac, rok: integer;
end;
rodzenstwo:0..20;
end;
var grupa: array[1..30] of osoba;
{lub var grupa: array[1..30] of record
definicja pól
end;}
var i:1..30;
begin
for i :=1 to 30 do begin
writeln ( 'Podaj dane ', i , '-tego studenta :' );
write ( 'Nazwisko' );
readln (grupa[i]. nazwisko);
write ( 'Rok urodzenia' );
readln (grupa[i]. data_ur.rok);
{....itd. wypełnienie tablicy}
end;
for i :=1 to 30 do
if grupa[i]. data_ur. rok < 1975 then
writeln(grupa[i].nazwisko:30,grupa[i]. rodzenstwo:4);
{wypisanie liczby rodzeństwa tylko dla urodzonych przed 1975 rokiem}
end .
Instrukcja wiążąca - with.. do..
Instrukcja with upraszcza zapis dostępu do pól rekordu. Odwołanie w instrukcji wewnętrznej (także złożonej) może nastąpić bezpośrednio do nazw pól wymienionych w liście zmiennych, bez wyspecyfikowanych nazw zmiennych całościowych z listy.
with lista_zmiennych_rekordowych do Istrukcja;
Przykład 1:
program p8_3;
var zespolona: record
rzecz, uroj: real
end;
begin
with zespolona do
begin
rzecz := 2.5;
uroj := 1.0
end;
...
end .
Przykład 2:
program p8_4;
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 .
Ćwiczenie
Wpisać teksty programów przykładowych z rozdziału, w razie potrzeby uzupełniając je o odpowiednie instrukcje wyprowadzające wartości zmiennych na ekran Output. Prześledzić krokowo programy, obserwując zmienne w oknie Watch.
Opracować kod programu, w którym podawane z klawiatury rekordy o organizacji AUTO(marka, rocznik, silnik(pojemność, moc)), gdzie Silnik jest polem typu rekordowego.
Program umożliwia:
wprowadzenie kilku rekordów (wykorzystać iterację),
wyświetlenie wprowadzanych danych na ekranie.
Zmodyfikować program tak, aby wprowadzane rekordy były gromadzone w tablicy 1-wymiarowej.
Uzupełnić kod programu p8.3 o operacje mnożenia dwóch liczb zespolonych o organizacji rekordowej Zesp( re , im ). Wzór na iloczyn dwóch liczb zespolonych to:
re3 = re1* re2 - im1* im2, im3 = re1* im2 + re2* im1.
Obliczone składowe iloczynu wyprowadzić na ekran.
Tablice rekordów. Sortowanie.
Prosty algorytm sortowania
Algorytm polega na porównywaniu pierwszego elementu z kolejnymi, w następnym przebiegu drugiego elementu z kolejnymi itd., aż do porównania dwóch ostatnich elementów:
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 zamiana 3
2 12 11 5 7 4
2 przebieg
2 12 11 5 7 4 zamiana 4
2 11 12 5 7 4 zamiana 5
2 5 12 11 7 4
2 5 12 11 7 4 zamiana 6
2 4 12 11 7 5
3 przebieg
2 4 12 11 7 5 zamiana 7
2 4 11 12 7 5 zamiana 8
2 4 7 12 11 5 zamiana 9
2 4 5 12 11 7
4 przebieg
2 4 5 12 11 7 zamiana 10
2 4 5 11 12 7 zamiana 11
2 4 5 7 12 11
5 przebieg
2 4 5 7 12 11 zamiana 12
2 4 5 7 11 12
liczba analiz:
Sortowanie bąbelkowe
Algorytm polega na n-krotnym (gdzie n jest liczbą elementów zbioru) porównywaniu wszystkich par elementów sąsiadujących:
1 przebieg
12 5 11 4 7 2 zamiana 1
5 12 11 4 7 2 zamiana 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 efekt ostatniej zamiany
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
Algorytm polega na (n-1)-krotnym porównywaniu kolejnych par elementów sąsiadujących, z tym, że w każdym kolejnym przebiegu zmniejszana jest o 1 liczba analizowanych par:
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
Ćwiczenie
Przeanalizować program:
program Lista;
{program wczytuje listę osób z klawiatury do tablicy rekordów, a następnie wyświetla listę posortowaną według zadanego pola }
type
TOsoba = record {opis typu rekordowego zawierającego dane osobowe}
Imie : string[ 25 ];
Nazwisko : string[ 25 ];
Adres : string [ 25 ];
Wiek : integer;
Plec : (K,M);
end;
const MaxOsob = 30; {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 pomocnicza do sortowania tablicy }
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);
Write ( 'Nazwisko: ' ); Readln(Nazwisko);
Write ( 'Adres: ' ); Readln(Adres);
Write ( 'Wiek: ' ); Readln(Wiek);
Write ( 'Plec [ K/M ]: ' ); Readln(znak);
case znak of
'K','k': Plec := K
else Plec := M
end;
end;
if IloscOsob < MaxOsob then
begin
Writeln;
Write ('Chcesz podać następną osobę? [ T/N ]');
Readln (Znak);
NastepnaOsoba := UpCase (Znak)='T'; {funkcja Upcase zamienia literę na dużą}
end;
end;
{ sortowanie i wyświetlanie listy }
repeat
{ wybór pola sortowania }
Writeln ('Wybierz porządek 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 według imion');
'N' :Writeln ( 'Lista posortowana według nazwisk');
'W' :Writeln ( 'Lista posortowana według wieku');
'P' :Writeln ( 'Lista posortowana według płci');
else Writeln ( 'Lista nieposortowana');
end;
{ sortowanie }
for i := 2 to IloscOsob do
begin
n := i;
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 {równoważne składni if Zamienic=true then }
begin {zamiana z użyciem zmiennej pomocniczej pom}
pom := Listaosob[ n ];
Listaosob[ n ] := ListaOsob[ n - 1];
Listaosob [n - 1] := pom;
end;
n:= n - 1;
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( 'Wyświetlić powtórnie [ T/N ]:' ); Readln(znak);
until Upcase(znak) = 'N';
end .
Przeanalizować, który z przedstawionych algorytmów sortujących został użyty w programie (a może żaden z nich?). Zaobserwować mechanizm zamiany (użycie zmiennej pomocniczej). Wprowadzić w kodzie programu wydruki kontrolne tablicy w trakcie kolejnych kroków sortowania, obserwować dokonywane zamiany.
Przykładowe rozwiązanie problemu "Trójkąt Pascala":
program tr_pascala;
var x : array[1..30,1..30] of integer;
i , j : integer;
begin
x[1,1]:=1;
x[2,1]:=1;
x[2,2]:=1;
{wypełnianie tablicy}
for i :=3 to 30 do
begin
x[ i ,1]:=1;
for j := 2 to i do
x[ i , j]:=x[ i -1, j -1]+x[ i -1, j];
end;
{wyprowadzenie tablicy na ekran}
for i :=1 to 30 do
begin
write ( ' ':39 - i); {wyprowadzenie spacji}
for j:=1 to i do
if x[ i ,j] mod 2 =0 then write( ' ':2) else write( '*':2);
writeln;
end;
end.
Opracować programy wypełniające tablice w następujący sposób:
0 |
0 |
0 |
20 |
20 |
0 |
0 |
0 |
0 |
30 |
30 |
0 |
0 |
0 |
0 |
40 |
40 |
0 |
0 |
0 |
0 |
50 |
50 |
0 |
0 |
0 |
0 |
60 |
60 |
0 |
0 |
0 |
0 |
70 |
70 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
10 |
10 |
10 |
0 |
0 |
0 |
10 |
10 |
10 |
0 |
0 |
0 |
10 |
10 |
10 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
12 |
13 |
24 |
25 |
36 |
2 |
11 |
14 |
23 |
26 |
35 |
3 |
10 |
15 |
22 |
27 |
34 |
4 |
9 |
16 |
21 |
28 |
33 |
5 |
8 |
17 |
20 |
29 |
32 |
6 |
7 |
18 |
19 |
30 |
31 |
Wyprowadzić tablice na ekran.
Utworzyć program, w którym wprowadzamy dane o rekordach posiadających strukturę AUTO (Marka, Rok produkcji, Przebieg, Cena) i umieszczamy je w kilkuelementowej tablicy. Następnie program sprawdza:
ile jest w tablicy aut marki Polonez,
który z wprowadzonych samochodów jest najstarszy,
który z wprowadzonych samochodów ma największy przebieg,
jaka jest suma cen wszystkich aut.
Odpowiedzi na pytania wyprowadzane są na ekran.
6 1. Środowisko zintegrowanego pakietu programowania w języku TURBO PASCAL
1. Środowisko zintegrowanego pakietu programowania w języku TURBO PASCAL 5
14 2. Składowe języka. deklaracje. Instrukcja przypisania.
2. Składowe języka. deklaracje. Instrukcja przypisania. 13
2. Składowe języka. deklaracje. Instrukcja przypisania. 7
20 3. Wyrażenia arytmetyczne i logiczne. Wprowadzanie i wyprowadzanie danych.
3. Wyrażenia arytmetyczne i logiczne. Wprowadzanie i wyprowadzanie danych. 19
3. Wyrażenia arytmetyczne i logiczne. Wprowadzanie i wyprowadzanie danych. 16
26 4. Schematy blokowe. Instrukcje warunkowe.
4. Schematy blokowe. Instrukcje warunkowe. 25
28 5. Instrukcje iteracyjne (1)
5. Instrukcje iteracyjne (1) 27
32 6. Instrukcje iteracyjne (2)
6. Instrukcje iteracyjne (2) 31
34 7. Typ tablicowy array
7. Typ tablicowy array 35
38 8. Typ rekordowy - record
8. Typ rekordowy - record 37
42 9..Tablice i rekordy. Sortowanie.
9..Tablice i rekordy. Sortowanie. 43