Rozdział 14 - Podprogramy

Czasami różne części twojego programu będą posiadały raczej podobne zadania do wykonania i zauważysz, iż wpisujesz po raz kolejny te same polecenia; jednakże nie ma takiej potrzeby. Możesz prowadzić wiersze programu raz w postaci znanej jako podprogram, a następnie użyć ich lub wywołać z dowolnego miejsca w programie bez ponownego wprowadzania.

W celu wykonania tego zadania używasz poleceń GOSUB (IDŹ do PODPROGRAMU) i RETURN (POWRÓĆ).

GOSUB n

gdzie n jest numerem pierwszego wiersza w podprogramie; jest to bardzo podobne do GOTO n, z wyjątkiem tego, iż komputer zapamiętuje numer wiersza polecenia GOSUB, aby później powrócić po wykonaniu podprogramu. Wykonuje to zapamiętywanie przez umieszczenie numeru wiersza (adresu powrotnego) na szczycie stosu adresów (stosu poleceń GOSUB).

RETURN

pobiera numer wiersza ze szczytu stosu GOSUB i idzie do wiersza o numerze bezpośrednio większym.

Jako pierwszy przykład, wpisz:

    10 PRINT "TO JEST GLOWNY PROGRAM",
    20 GOSUB 1000
    30 PRINT "I JESZCZE RAZ";
    40 GOSUB 1000
    50 PRINT "I TO WSZYSTKO."
    60 STOP
1000 REM PODPROGRAM ZACZYNA SIE TUTAJ
1010 PRINT "TO JEST TEN PODPROGRAM,"
1020 RETURN

Polecenie STOP w wierszu 60 jest bardzo ważne, ponieważ w przeciwnym razie program wbiegłby do podprogramu i spowodowałby błąd 7 przy próbie wykonania polecenia RETURN.

Jako mniej trywialny przykład załóżmy, iż masz ochotę napisać program komputerowy zajmujący się funtami, szylingami i pensami (pamiętaj, iż jest to tłumaczenie z j. angielskiego - przyp. tłum.). Posiadający dobrą pamięć wiedzą, iż przed rokiem 1971 funt angielski dzielony był na dwadzieścia szylingów - zatem szyling odpowiada 5 pensom - a z kolei szyling dzielony był na dwanaście starych pensów (d było skrótem dla starego pensa). Będziesz miał trzy zmienne: L, S i D (być może inne - L1, S1, D1 itd.), a arytmetyka jest prosta jak drut. Po pierwsze stosujesz ją rozdzielnie dla funtów, szylingów i pensów - na przykład, aby dodać dwie sumy pieniężne, dodajesz pensy, dodajesz szylingi i dodajesz funty; aby podwoić sumę pieniędzy, podwajasz pensy, szylingi i funty; itd. Gdy będzie wszystko wyliczone, sprowadzasz wyniki do poprawnej postaci tak, aby pensy znalazły się pomiędzy 0 i 11, szylingi pomiędzy 0 i 19, a funty tyle ile wyjdzie. Ostatni etap jest wspólny dla wszystkich tych operacji, zatem możemy przekształcić go w podprogram.

Odkładając na moment pojęcie podprogramu, warto poświęcić chwilę swojego czasu na próbę samodzielnego napisania tego programu. Mając dane dowolne liczby L, S i D, jak sprowadziłbyś je do właściwej liczby funtów, szylingów i pensów? Częścią problemu jest to, iż zaczniesz myśleć o coraz bardziej dziwnych przypadkach.

Najpierw przyjdzie ci pewnie na myśl coś takiego jak 1£ 25s 17d, które chcesz zamienić na 2£ 6s i 5d. Bułka z masłem. Lecz załóżmy, iż masz liczby ujemne. Dług 1£ 25s 17d lub -1£ -25s -17d mógłby równie dobrze zmienić się na -3£ 13s 7d, co raczej jest dziwnym sposobem zapisywania go (jakby ludzie pożyczali sobie nawzajem tylko całe funty). A co z ułamkami? Jeśli podzielisz 1£ 25s 17d przez dwa, dostaniesz 0,5£ 12,5s 8,5d i chociaż ilość pensów 8,5 wpada pomiędzy 0 a 11, ilość szylingów 12,5 wpada pomiędzy 0 a 19, na pewno nie jest to tak dobre, jak 1£ 3s 2,5d. Postaraj się wypracować swoje własne rozwiązania tych problemów i wykorzystaj je w programie komputerowym, zanim zaczniesz czytać dalej (marzenie belfra, no nie? - przyp. tłum.).

Oto jedno z rozwiązań:

1000 REM PODPROGRAM WYLICZAJACY POPRAWNA LICZBE FUNTOW, SZYLINGOW I PENSOW
1010 LET D=240*L+12*S+D
1020 REM TERAZ WSZYSTKO JEST W PENSACH
1030 LET E=SGN D
1040 LET D=ABS D
1050 REM PRACUJEMY Z DODATNIM D, PAMIETAJAC ZNAK W E
1060 LET S=INT (D/12)
1070 LET D=(D-12*S)*E
1080 LET L=INT (S/20)*E
1090 LET S=S*E-20*L
1100 RETURN

Sam z siebie ten podprogram nie jest specjalnie użyteczny, ponieważ nie zawiera poleceń ani ustawiających zmienne L, S i D, ani wykorzystujących wyniki. Wpisz program główny oraz również inny podprogram wyświetlania L, S i D.

    10 INPUT L
    20 INPUT S
    30 INPUT D
    40 GOSUB 2000
    45 REM WYSWIETLENIE WARTOSCI
    50 PRINT
    60 PRINT " = ";
    70 GOSUB 1000
    75 REM POPRAWIANIE
    80 GOSUB 2000
    85 REM WYSWIETLENIE WARTOSCI
    90 PRINT
  100 GOTO 10
2000 REM PODPROGRAM WYSWIETLANIA L,S I D
2010 PRINT "£";L;"..";S;"S..";D;"D";
2020 RETURN

(Przypomnij sobie z rozdziału 9, iż puste polecenie PRINT w wierszu 50 wyświetla jeden pusty wiersz).

Wyraźnie zaoszczędziliśmy na programie wykorzystując podprogram wydruku od wiersza 2000, co samo w sobie jest bardzo powszechnym wykorzystaniem podprogramów: skracanie długości programów. Jednakże podprogram korygowania w rzeczywistości spowodował wydłużenie programu - przez polecenia GOSUB i RETURN; zatem sama długość programu nie jest jedynym powodem stosowania podprogramów. Jeśli zostaną użyte umiejętnie, to podprogramy mogą ułatwić zrozumienie działania całego programu tym, którzy się tutaj liczą - nam, ludziom.

Program główny uległ uproszczeniu dzięki zastosowaniu bardziej zaawansowanych poleceń: każdy GOSUB reprezentuje pewien skomplikowany podprogram, lecz można o tym zapomnieć, liczy się tylko wynik jego działania. Dzięki temu łatwiej uchwycić główną strukturę programu.

Z drugiej strony podprogramy są upraszczane z całkiem innego powodu, mianowicie są one krótsze. Wciąż używają tych samych, starych poleceń LET i PRINT, lecz muszą one wykonać jedynie część całej pracy, a tak łatwiej się je pisze.

Sztuka polega na wybraniu warstwy - lub warstw - na których pisze się podprogramy. Muszą być wystarczająco duże, aby posiadały znaczący wpływ na program główny, a jednak na tyle małe, aby pisało się je łatwiej niż cały program bez podprogramów. Te przykłady (nie polecane) ilustrują opisane problemy:

Pierwszy:

    10 GOSUB 1000
    20 GOTO 10
1000 INPUT L
1010 INPUT S
1020 INPUT D
1030 PRINT " ";L;"..";S;"S..";D;"D";TAB 8;"=";
1040 LET D=240*L+12*S+D
:    :
:    :
2000 RETURN

i drugi:

    10 GOSUB 1010
    20 GOSUB 1020
    30 GOSUB 1030
    40 GOSUB 1040
    50 GOSUB 1050
    :    :
    :    :
  300 GOTO 10
1010 INPUT L
1015 RETURN
1020 INPUT S
1025 RETURN
1030 INPUT D
1035 RETURN
1040 PRINT " ";L;"..";S;"S..";D;"D";TAB 8; "=";
1045 RETURN
1050 LET D=240*L+12*S+D
1055 RETURN
:    :
:    :

Pierwszy ze swoim zaawansowanym podprogramem oraz drugi ze swoimi licznymi, trywialnymi podprogramami demonstrują zupełnie przeciwne skrajności, lecz z jednakową bezcelowością.

Podprogram może bez problemu wywoływać następny, lub nawet sam siebie (podprogram wywołujący sam siebie nazywamy rekursywnym), zatem nie bój się stosować kilku warstw.

 

Podsumowanie

Polecenia: GOSUB, RETURN

 

Ćwiczenia

  1. Przykładowy program jest prawie uniwersalnym kalkulatorem dla funtów, szylingów i pensów. Jak zastosowałbyś go:

(i) do zamiany funtów i nowych pensów na funty, szylingi i pensy?
(ii) do zamiany gwinei na funty i szylingi? (1 gwinea = 1£ 1s)
(iii) do wyznaczania ułamka funta? (np. jednej trzeciej funta)

Wstaw wiersz zaokrąglający pensy do najbliższego ćwierć pensa (1/4d).

 

 

  1. Dodaj dwa polecenia do programu:

4 LET POPRAW=1000
7 LET PISZ LSD=2000

i zmień

GOSUB 1000 na GOSUB POPRAW
GOSUB 2000 na GOSUB PISZ LSD

Zadziała to dokładnie tak, jak myślisz; w rzeczywistości numery wierszy w poleceniu GOSUB (lub GOTO i RUN) mogą być dowolnymi wyrażeniami liczbowymi (nie myśl sobie, iż takie coś będzie działać na komputerach innych niż ZX81, ponieważ nie jest to standardowym językiem BASIC).

Tego typu rzeczy mogą zdziałać cuda dla przejrzystości programów.

 

 

  1. Przepisz główny program w przykładzie, aby wykonywał coś zupełnie innego, lecz wykorzystywał przy tym te same podprogramy.

 

 

  1. W kolejnych wierszach polecenia

... GOSUB n
... RETURN

można zastąpić przez

... GOTO n

Dlaczego?

 

 

  1. Podprogram może posiadać kilka punktów wejścia. Na przykład ze względu na sposób wykorzystywania podprogramów w naszym programie głównym. gdzie polecenie GOSUB 1000 występuje bezpośrednio przed GOSUB 2000, możemy zastąpić te dwa podprogramy jednym dużym, który koryguje L, S i D i wyświetla je. Posiada on dwa punkty wejścia: Jeden na początku do całego podprogramu oraz drugi nieco dalej do fragmentu dokonującego jedynie wyświetlania.

Zrób odpowiednie poprawki.

 

 

  1. Uruchom program:

10 GOSUB 20
20 GOSUB 10

Adresy powrotne są umieszczane stadnie na stosie GOSUB, lecz nigdy nie są z niego usuwane i w końcu w komputerze zabraknie dla nich miejsca. Wtedy program zatrzyma się z komunikatem błędu 4 (zobacz do dodatku B).

Mógłbyś mieć kłopoty z usunięciem adresów ze stosu bez kasowania wszystkiego, lecz to powinno ci pomóc:

(i) Usuń te dwa polecenia GOSUB.
(ii) Wstaw dwa nowe wiersze:

11 RETURN
21 RETURN

(iii) Wpisz:

RETURN

Adresy powrotu będą zdejmowane ze stosu aż otrzymasz błąd 7.

(iv) Zmień swój program tak, aby to samo się już nie powtórzyło.

Jak to zadziałało?

 



List do administratora Serwisu Edukacyjnego Nauczycieli I LO

Twój email: (jeśli chcesz otrzymać odpowiedź)
Temat:
Uwaga: ← tutaj wpisz wyraz  ilo , inaczej list zostanie zignorowany

Poniżej wpisz swoje uwagi lub pytania dotyczące tego rozdziału (max. 2048 znaków).

Liczba znaków do wykorzystania: 2048

 

W związku z dużą liczbą listów do naszego serwisu edukacyjnego nie będziemy udzielać odpowiedzi na prośby rozwiązywania zadań, pisania programów zaliczeniowych, przesyłania materiałów czy też tłumaczenia zagadnień szeroko opisywanych w podręcznikach.



   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2018 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.