PP 6, Podstawy programowania


6. INSTRUKCJA PRZYPISANIA

6.1. Składnia i działanie

Instrukcja przypisania to jedna z najczęściej używanych instrukcji. Jej ogólna postać jest następująca:

Nazwa_zmiennej := Wyrażenie;

Po lewej stronie instrukcji może wystąpić wyłącznie nazwa zmiennej. Po niej mamy operator przypisania „:=”, a po prawej stronie instrukcji - jakieś wyrażenie. Wyrażenie umieszczone po prawej stronie instrukcji może być stałą jawną, nazwą stałej definiowanej, zmienną, wywołaniem funkcji lub złożonym wzorem, zawierającym wymienione elementy, połączone odpowiednimi operatorami działań. Poniżej pokazano kilka przykładów instrukcji:

X:= 0;

I:=I+1;

Delta:=Sqrt(B*B-4*A*C);

Odleglosc:=Sqrt(Sqr(X1-X2)+Sqr(Y1-Y2));

Pole_trojkata:=Podstawa*Wysokosc/2;

X:=Pi;

A:=Abs(A);

Nie należy mylić operatora przypisania ':=' ze znakiem równości '='. Operator przypisania jest symbolem operacji przesyłania danej w kierunku od prawej do lewej strony instrukcji. Operacja przypisania składa się z dwóch faz:

  1. Zostaje obliczona wartość wyrażenia po prawej stronie instrukcji

  2. Wynik zostaje zapamiętany w zmiennej, której nazwa jest po lewej stronie instrukcji. (Poprzednia wartość tej zmiennej zostaje wymazana).

Przykład przebiegu dwóch faz działania instrukcji pokazano na rysunku 6.1.

const K:Byte=3;

begin

K:=K+1;

end.

Faza 1

0x08 graphic

0x08 graphic
K 3

K+1=3+1=4

0x08 graphic

Faza 2

0x08 graphic

0x08 graphic
K 3 4

Rys. 6.1. Działanie instrukcji przypisania K:=K+1

W programie z przykładu 6.1 zastosowano trzy instrukcje przypisania do zamiany miejscami aktualnych wartości dwóch zmiennych. Zamiana taka nie jest możliwa bez pomocniczej zmiennej, nazwanej tu Kopia. Zachęcamy do samodzielnej analizy tego programu, w czym pomagają umieszczone w nim komentarze.

Przykład 6.1. Zamiana miejscami wartości dwóch zmiennych

program Ex6_1;

{Zamienia miejscami aktualne wartości zmiennych A,B.}

uses Crt;

var A,B,Kopia:Integer;

begin

Clrscr;

A:=88;

B:=5;

Writeln('Wartosci poczatkowe:');

Writeln(' A=',A,', B=',B);

{Zamiana miejscami}

Kopia:=A; {A=88, Kopia=88}

A:=B; {B=5, A=5}

B:=Kopia; {Kopia=88, B=88}

Writeln;

Writeln('Wartosci po zamianie:');

Writeln(' A=',A,', B=',B);

Readln;

end.

6.2. Zgodność typów w sensie przypisania

Wykonanie instrukcji przypisania:

L:=P;

wymaga, by typ zmiennej L był zgodny z typem wyrażenia P. Jednak nie oznacza to, że zgodność występuje tylko wtedy, gdy typy L i P są identyczne. Przypisanie jest dozwolone, kiedy:

W przypadku niezgodności typów, w czasie kompilowania programu źródłowego wystąpi błąd kompilacji z komunikatem:

Error 26: Type mismatch.

6.3. Zastosowanie instrukcji przypisania do obliczania wartości wyrażeń

Ponieważ po prawej stronie instrukcji przypisania może wystąpić dowolne wyrażenie, które w pierwszej fazie działania instrukcji jest obliczane, a w drugiej fazie - jego wartość zostaje zapamiętana w odpowiedniej zmiennej, przydatność tej instrukcji do obliczeń jest oczywista. Do konstrukcji wyrażeń stosuje się ogólnie znane operatory arytmetyczne, zestawione w tabeli 6.1. Umieszczono w niej także operatory relacyjne i logiczne, które zostaną dokładniej omówione w rozdziale 7.

Tabela 6.1 Ważniejsze operatory Turbo Pascala

Symbol

Operacja

Typy argumentów

Typ wyniku

Operatory arytmetyczne (dwa pierwsze są jednoargumentowe)

+

-

Identyczność znaku

Zmiana znaku

Rzeczywisty/całkowity

Rzeczywisty/całkowity

Rzeczywisty/całkowity

Rzeczywisty/całkowity

+

-

*

/

div

mod

Dodawanie

Odejmowanie

Mnożenie

Dzielenie

Dzielenie całkowite

Daje resztę z dzielenia

Rzeczywiste/całkowite

Rzeczywiste/całkowite

Rzeczywiste/całkowite

Rzeczywiste/całkowite

Całkowite

Całkowite

Rzeczywisty/całkowity

Rzeczywisty/całkowity

Rzeczywisty/całkowity

Rzeczywisty

Całkowity

Całkowity

Operatory logiczne

not

and

or

xor

Negacja

Koniunkcja

Alternatywa

Alternatywa wyłączająca

Boolean

Boolean

Boolean

Boolean

Boolean

Boolean

Boolean

Boolean

Operatory relacyjne

=

<>

<

>

<=

>=

Równy

Nierówny

Mniejszy

Większy

Nie większy

Nie mniejszy

Liczby/string/Char/set of

Liczby/string/Char/set of

Liczby/string/Char

Liczby/string/Char

Liczby/string/Char

Liczby/string/Char

Boolean

Boolean

Boolean

Boolean

Boolean

Boolean

in

<=

>=

Jest elementem zbioru

Jest podzbiorem

Jest nadzbiorem

Lewy: typ porządkowy,

prawy: set of

set of

set of

Boolean

Boolean

Boolean

Pisząc wyrażenia, musimy pamiętać, że pomiędzy operatorami występuje hierarchia, decydująca o porządku wykonywania operacji (tabela 6.2). Operacje o jednakowym priorytecie wykonywane są w kolejności ich zapisu w wyrażeniu - od lewej do prawej. Jeżeli w wyrażeniu występują operatory o różnym poziomie priorytetu, to te poziomy wyznaczają porządek wykonywania działań. Na przykład w wyrażeniu: A*B+C*D mamy operator '*' o wyższym priorytecie od operatora '+'. Dlatego najpierw zostaną kolejno obliczone iloczyny A*B oraz C*D , a dopiero potem ich suma da wartość całego wyrażenia. Porządek obliczeń wynikający z priorytetów operatorów można zawsze zmienić, stosując nawiasy, na przykład pisząc: A*(B+C)*D. Pamiętajmy, że w wyrażeniach arytmetycznych można stosować tylko nawiasy zwykłe; nawiasy klamrowe służą do zaznaczania komentarzy, a kwadratowe - do zapisu indeksów i stałych typu zbiorowego.

Tabela 6.2. Priorytet operatorów

Operatory

Priorytet

Kategoria operatorów

+, -, not

*, /, div, mod, and

+, -, or, xor

=, <>, <, >, <=, >=, in

1 (najwyższy)

2

3

4 (najniższy)

Jednoargumentowe

Multiplikatywne

Addytywne

Relacyjne

Trzeba pamiętać, że jeżeli w wyrażeniu wystąpi chociażby jedna wartość rzeczywista, to wynik wyrażenia także będzie typu rzeczywistego. Zauważmy też, że wynik zwykłego dzielenia (operator `/ `) jest zawsze typu rzeczywistego, nawet w przypadku, gdy dzielna i  dzielnik są całkowite i dzielą się bez reszty.

W module podstawowym System znajduje się wiele standardowych funkcji, które można wykorzystywać w wyrażeniach po prawej stronie instrukcji przypisania, lub stosować jako argumenty innych funkcji lub procedur. Listę funkcji standardowych, z podaniem ich właściwości, zawiera tabela 6.3.

Tabela 6.3. Funkcje arytmetyczne Turbo Pascala

Wywołanie

Wielkość zwracana

Typ argumentu

Typ wyniku

Arctan(x)

Arcus tangens od x

Dowolny liczbowy

Real

Sin(x)

Sinus kąta x (x w radianach)

Dowolny liczbowy

Real

Cos(x)

Cosinus kąta x (x w radianach)

Dowolny liczbowy

Real

Exp(x)

ex

Dowolny liczbowy

Real

Ln(x)

Logarytm naturalny z x

Liczbowy nieujemny

Real

Sqr(x)

Kwadrat liczby x

Liczbowy

Taki, jak argumentu

Sqrt(x)

Pierwiastek kwadratowy z x

Liczbowy nieujemny

Real

Pi

Liczba π = 3.14159…..

Real

Random(x)

Liczba losowa z przedziału [0..x-1]

Word

Word

Random;

Liczba losowa z przedziału

[0, 1)

Real

Abs(x)

Wartość bezwzględna x

Dowolny liczbowy

Taki, jak argumentu

Frac(x)

Część ułamkowa x

Real

Real

Int(x)

Część całkowita x

Real

Real

Round(x)

Konwersja x do typu całkowitego z zaokrągleniem

Real

Longint

Trunc(x)

Konwersja x do typu całkowitego z odrzuceniem części ułamkowej x

Real

Longint

6 4. Przykłady programów wykorzystujących instrukcje przypisania.

Program pokazany w przykładzie 6.2 może w pierwszej chwili zaskakiwać pozornie nieuzasadnionym skomplikowaniem obliczeń. Ten sam rezultat można przecież uzyskać, wykonując jedną instrukcje przypisania:

Wynik:=X*X*X;

Jednak przy dużej wartości wykładnika, na przykład gdybyśmy chcieli obliczyć X100, to pozornie proste podejście byłoby nie do przyjęcia - trzeba byłoby po prawej stronie instrukcji napisać 100 identyfikatorów X i 99 znaków mnożenia! Ponieważ chcemy, by nasz algorytm był przydatny dla dowolnych potęg X, posłużymy się metodą iteracyjną, która polega na stopniowym dochodzeniu do wyniku przez wielokrotne powtarzanie tej samej sekwencji instrukcji,

W naszym przypadku, po zainicjowaniu zmiennej Wynik wartością 1, kolejno powtarzamy tę samą instrukcję:

Wynik:=Wynik*X;

Po każdym wykonania instrukcji, wartość zmiennej Wynik zostaje pomnożona przez X i zapamiętana jako nowa wartość zmiennej Wynik, zastępując wartość poprzednią. Z definicji operacji potęgowania wynika, że kolejne wartości przejściowe, przypisywane zmiennej Wynik, to kolejne potęgi liczby X. Chcąc podnieść X do potęgi N, musimy N-krotnie powtórzyć pokazaną instrukcję przypisania.

Chociaż opisana metoda jest ogólna, a wykonywana instrukcja przypisania jest bardzo prosta, to w przypadku dużych wartości wykładnika N program, napisany tak jak w przykładzie 6.2, nie byłby wygodny - musiałby zawierać bardzo wiele instrukcji. Na szczęście, w językach programowania można wykorzystywać tzw. instrukcje powtarzające. Instrukcje powtarzające Turbo Pascala omówione będą w rozdziale 8. Tam też zostanie przedstawiony bardziej zwięzły zapis pokazanych tutaj programów z iteracjami.

Przykład 6.2. Program do iteracyjnego obliczenia x3

program Ex6_2;

{Iteracyjnie oblicza trzecią potęgę liczby czytanej z klawiatury.}

uses Crt;

var X,Wynik:Real;

begin

Clrscr;

Write('Podaj liczbe: ');

Readln(X);

Wynik:=1.0; { Wynik=1.0}

Wynik:=Wynik*X; { Wynik=1*X }

Wynik:=Wynik*X; { Wynik=(1*X)*X }

Wynik:=Wynik*X; { Wynik=(1*X*X)*X }

Write('Wynik: ',Wynik:0:6);

Readln;

end.

W przykładzie 6.3 również posłużono się metodą iteracyjną, by znaleźć sumę i średnią wartość trzech kolejno wprowadzanych z klawiatury liczb. Do przechowania każdej kolejnej liczby służy ta sama zmienna X, a do przechowania sumy przejściowej zmienna Suma, którą inicjujemy wartością 0. W kolejnych krokach obliczeń powtarzana jest sekwencja trzech operacji:

Write('Podaj liczbe: ');

Readln(X);

Suma:=Suma+X;

Operacje te realizują kolejno następujące działania: wezwanie użytkownika do wprowadzenia liczby, odczyt tej liczby z klawiatury, powiększenie o tę liczbę aktualnej wartości zmiennej Suma, by uzyskać nową wartość tej zmiennej.

Po trzech krokach zmienna Suma przechowuje sumę trzech wprowadzonych z klawiatury liczb. Dzieląc tę sumę przez 3, dostajemy szukaną średnią arytmetyczną.

Przykład 6.3. Program iteracyjny obliczający sumę i średnią z trzech liczb

program Ex6_3;

{Iteracyjnie sumuje 3 liczby czytane z klawiatury i liczy ich średnią.}

uses Crt;

var X,Suma,Srednia:Real;

begin

Clrscr;

Suma:=0;

Write('Podaj liczbe: ');

Readln(X);

Suma:=Suma+X;

Write('Podaj liczbe: ');

Readln(X);

Suma:=Suma+X;

Write('Podaj liczbe: ');

Readln(X);

Suma:=Suma+X;

Srednia:=Suma/3;

Write('Srednia z tych liczb to ');

Write(Srednia:0:6);

Readln;

end.

Przykład 6.4 pokazuje obliczenie wartości funkcji silnia dla argumentu równego 6. Ponieważ argument jest niewielki, dla otrzymania wyniku można by zastosować pojedynczą instrukcję przypisania o postaci:

S:=1*2*3*4*5*6;

Z tych samych powodów, co poprzednio, tego typu podejście nie byłoby wygodne dla dużych argumentów silni, co więcej - nie pozwoliłoby uogólnić metody na dowolną wartość argumentu. Z tego powodu wybrano iteracyjną metodę obliczeń. W programie występuje pomocnicza zmienna I, równa początkowo 0, która w każdym kroku zwiększa się o 1, przyjmując kolejno wartości 1, 2, 3, 4, 5, 6. Przez te wartości, zgodnie z definicją silni, mnoży się kolejno wynik przejściowy, pamiętany w zmiennej S. Przed rozpoczęciem obliczeń S=1. Po sześciu powtórzeniach pary instrukcji, w zmiennej S znajdzie się szukany rezultat. W rozdziale 8 pokażemy, jak można zwięźle zapisać ten program, posługując się instrukcją powtarzającą.

Przykład 6.4. Iteracyjne obliczanie wartości silni liczby 6

program Ex6_4;

{Oblicza iteracyjnie silnię liczby 6.}

uses Crt;

var S:Longint;

I:Byte;

begin

Clrscr;

I:=0; {I=0} {Inicjalizacja}

S:=1; {S=1}

I:=I+1; {I=0+1=1} {Krok 1}

S:=S*I; {S=1*1=1}

I:=I+1; {I=1+1=2 {Krok 2}

S:=S*I; {S=1*2=2}

I:=I+1; {I=2+1=3} {Krok 3}

S:=S*I; {S=2*3=6}

I:=I+1; {I=3+1=4} {Krok 4}

S:=S*I; {S:=6*4=24}

I:=I+1; {I=4+1=5} {Krok 5}

S:=S*I; {S=24*5=120}

I:=I+1; {I=5+1=6} {Krok 6}

S:=S*I; {S=120*6=720}

Write(' 6! = ',S);

Readln;

end.

30



Wyszukiwarka