Professional Documents
Culture Documents
tufsvkdf
22:
231
BvupMJTQ!!qsbluzd{oz!lvst
PROG_017.LSP
Przykad uycia instrukcji while wersja 2.
PROG_018.LSP
Przykad uycia instrukcji while.
Obliczenie i wypisanie kwadratw liczb cakowitych od 1 do 10.
PROG_019.LSP
Przykad zagniedonej instrukcji while.
Wypisanie liczb od 1 do 100 w 10 rzdach po 10 kolumn.
PROG_020.LSP
Przykad uycia instrukcji cond wersja 1.
PROG_021.LSP
Przykad uycia instrukcji cond wersja 2.
PROG_022.LSP
Przykad uycia instrukcji cond.
Obliczenie pierwiastkw rwnania kwadratowego.
PROG_023.LSP
Przykad uycia instrukcji repeat.
Obliczenie i wypisanie kwadratw liczb cakowitych od 1 do 100.
PROG_024.LSP
Przykad uycia zagniedonych instrukcji repeat.
Wypisanie liczb od 1 do 100 w 10 rzdach po 10 kolumn.
PROG_025.LSP
Realizacja ptli FOR w AutoLISPie.
PROG_026.LSP
Uycie instrukcji FOR przykad 1.
PROG_027.LSP
Uycie instrukcji FOR przykad 2.
PROG_028.LSP
Uycie instrukcji FOR przykad 3.
Tworzenie listy oraz wywietlanie jej zawartoci.
PROG_029.LSP
Uycie instrukcji FOR przykad 4.
Obliczenie i wypisanie kwadratw liczb cakowitych od 1 do 10.
PROG_030.LSP
Uycie zagniedonych instrukcji FOR.
Wypisanie liczb od 1 do 100 w 10 rzdach po 10 kolumn.
9/!Qumf!j!lpotusvldkf!tufsvkdf
232
PROG_031.LSP
Realizacja ptli DO_WHILE w AutoLISPie.
PROG_032.LSP
Uycie instrukcji DO_WHILE.
Obliczenie i wypisanie kwadratw liczb cakowitych od 1 do 10.
Czsto zdarza si, e, w zalenoci od sytuacji, program musi dokona wyboru, jaka
jego sekcja ma by wykonywana. W takim przypadku moemy zastosowa instrukcj
warunkow if.
Instrukcja if moe mie 2 formy:
(if wyraenie
(instrukcja_1)
);if
lub
(if wyraenie
(instrukcja_1)
(instrukcja_2)
);if
;else
233
BvupMJTQ!!qsbluzd{oz!lvst
;---------;pobranie wartosci zmiennej x
(setq
x (getint "\nPodaj liczbe calkowita: ")
);setq
;---------;sprawdzenie warunku na x
(if (= x 10)
(princ "Zmienna x ma wartosc 10.")
(princ "Zmienna x ma wartosc inna niz 10.") ;else
);if
;---------(princ)
;---------;**************************************************KONIEC
9/!Qumf!j!lpotusvldkf!tufsvkdf
234
9/2/2/!Jotusvldkf!qsptuf!j!{p
9/2/2/!Jotusvldkf!qsptuf!j!{ppof
kf!qsptuf!j!{ppof
W jzyku AutoLISP rol symbolu kocowego instrukcji gra lewy skrajny nawias zamykajcy. Tak wic zapisy:
(setq x 3)
oraz
(setq
x 3
);setq
oraz
(setq
x
3
);setq
oraz
(
setq
x
3
)
Przyjto zasad, e wszdzie tam, gdzie mona napisa instrukcj prost, rwnie dobrze
wolno umieci instrukcj zoon.
235
BvupMJTQ!!qsbluzd{oz!lvst
Konstrukcja:
(if (warunek)
(progn
; instrukcja pusta
);progn
(progn ;else
lista_instrukcji
);progn
);if
9/!Qumf!j!lpotusvldkf!tufsvkdf
236
9/2/3/![bhojfepof!jot
9/2/3/![bhojfepof!jotusvldkf!JG
bhojfepof!jotusvldkf!JG
Po warunku if lub else moe wystpi dowolny typ instrukcji. Moe to by instrukcja,
ktra wprowadza lub wyprowadza dane, wykonuje dziaania matematyczne lub wywouje funkcj uytkownika. Moe to by take kolejna instrukcja if. O instrukcji if, ktra
zawiera si wewntrz innej instrukcji if, mwimy, e jest zagniedona. Przykadowo,
w poniszym kodzie druga instrukcja if jest zagniedona w pierwszej:
(if (> x 1)
(if (< y 10)
(setq k1 1.25)
);if
);if
Drugi warunek if testuje si tylko wwczas, gdy prawdziwy jest warunek pierwszy, tak
wic zmiennej k1 jest przypisywana warto 1.25 tylko wtedy, kiedy obydwa warunki
s prawdziwe. To samo mona zapisa nastpujco:
(if (and (> x 1)(< y 10))
(setq k1 1.25)
);if
Obydwa zapisy powoduj wykonanie tego samego zadania, ale w drugim przykadzie,
dziki uyciu operatora logicznego and, zapis jest janiejszy. Nie trzeba rozszyfro-
237
BvupMJTQ!!qsbluzd{oz!lvst
wywa, co wykonuje kada instrukcja if; wystarczy odczyta instrukcj, by j zrozumie Jeli x jest wiksze ni 1 i y jest mniejsze ni 10, to k1 wynosi 1.25.
Generalnie, dwie nastpujce po sobie zagniedone instrukcje if mona zastpi jedn
z operatorem and. Z reguy mdrze jest ich unika, poniewa mog nas doprowadzi do
niejasnych sytuacji i trudnych do odczytania kodw.
Poniej przedstawiam przykad eksponujcy zastosowanie zagniedonej instrukcji
warunkowej if. Tym razem jest to temat szkolny i jednoczenie klasyczny w wielu
podrcznikach programowania, a mianowicie obliczenie pierwiastkw rwnania kwadratowego o postaci:
ax2 + bx + c = 0
2. delta = 0
zastosowanie odpowiedniego wzoru w celu uzyskania wartoci
pierwiastka podwjnego, a nastpnie, po opatrzeniu odpowiednim komunikatem,
wyprowadzenie jej na ekran
3. delta > 0
zastosowanie odpowiednich wzorw do uzyskania wartoci dwch
rnych pierwiastkw rzeczywistych i podanie ich w odpowiedniej postaci
Program realizujcy powysze zadania moemy zrealizowa wykorzystujc zagniedone instrukcje warunkowe if else.
Oto program obliczajcy pierwiastki dwumianu kwadratowego:
;**************************************************PROG_014
;Obliczenie pierwiastkow rownania kwadratowego - wersja 1.
;
;-------------------------------------------------(textpage)
(princ "Obliczenie pierwiastkow rownania kwadratowego.")
(terpri)
(terpri)
;---------;pobranie wspolczynnikow a, b i c
;
(initget (+ 1 2))
(setq a (getreal "Podaj wartosc wspolczynnika a: "))
;
(initget 1)
(setq b (getreal "Podaj wartosc wspolczynnika b: "))
;
(initget 1)
(setq c (getreal "Podaj wartosc wspolczynnika c: "))
(terpri)
9/!Qumf!j!lpotusvldkf!tufsvkdf
;---------;obliczenie delty
;
(setq
delta (- (* b b)(* 4.0 a c))
);setq
;---------;obliczenie pierwiastkow rownania
;
(if (< delta 0)
(progn ;brak pierwiastkow rzeczywistych
(princ
(strcat
"\nDla wspolczynnikow "
(rtos a 2 4)
", "
(rtos b 2 4)
", "
(rtos c 2 4)
"\nwielomian kwadratowy nie ma "
"rozwiazan rzeczywistych."
);strcat
);princ
);progn
238
;delta = 0 i delta > 0
;
(if (= delta 0) ;podwojny pierwiastek rzeczywisty
(progn
(setq
x1 (/ (- b)(* 2.0 a))
);setq
(princ
(strcat
"\nDla wspolczynnikow "
(rtos a 2 4)
", "
(rtos b 2 4)
", "
(rtos c 2 4)
"\nwielomian kwadratowy ma "
"podwojny pierwiastek rzeczywisty"
"\nx1 = "
(rtos x1 2 4)
);strcat
);princ
);progn
(progn ;else - ostatnia, trzecia mozliwosc
;delta > 0 - 2 rozne pierwiastki rzeczywiste
;
(setq
x1 (/ (- (- b)(sqrt delta))(* 2.0 a))
x2 (/ (+ (- b)(sqrt delta))(* 2.0 a))
);setq
(progn
239
BvupMJTQ!!qsbluzd{oz!lvst
(princ
(strcat
"\nDla wspolczynnikow "
(rtos a 2 4)
", "
(rtos b 2 4)
", "
(rtos c 2 4)
"\nwielomian kwadratowy ma "
"2 rozne pierwiastki rzeczywiste"
"\nx1 = "
(rtos x1 2 4)
"
"
"x2 = "
(rtos x2 2 4)
);strcat
);princ
);progn
);if
);progn
);if
;---------(terpri)
(princ)
;---------;**************************************************KONIEC
9/!Qumf!j!lpotusvldkf!tufsvkdf
23:
241
BvupMJTQ!!qsbluzd{oz!lvst
Tutaj dokonujemy kolejnego ucilenia warunku na delt. Ten blok instrukcji ma
zosta wykonany, gdy delta jest rwna zero.
W linii tej nastpuje zgrupowanie instrukcji w blok, ktry ma zosta wykonany,
gdy delta jest wiksza od zera.
Poniewa zastosowanie zagniedonych instrukcji warunkowych if prowadzi do otrzymania zawiego kodu, poniszy przykad pokazuje sposb obejcia tego problemu.
;**************************************************PROG_015
;Obliczenie pierwiastkow rownania kwadratowego - wersja 2.
;
;-------------------------------------------------(textpage)
(princ "Obliczenie pierwiastkow rownania kwadratowego.")
(terpri)
(terpri)
;---------;pobranie wspolczynnikow a, b i c
;
(initget (+ 1 2))
(setq a (getreal "Podaj wartosc wspolczynnika a: "))
;
(initget 1)
(setq b (getreal "Podaj wartosc wspolczynnika b: "))
;
(initget 1)
(setq c (getreal "Podaj wartosc wspolczynnika c: "))
(terpri)
;---------;obliczenie delty
;
(setq
delta (- (* b b)(* 4.0 a c))
);setq
;---------;obliczenie pierwiastkow rownania
;
(if (< delta 0)
(progn ;brak pierwiastkow rzeczywistych
(princ
(strcat
"\nDla wspolczynnikow "
(rtos a 2 4)
", "
(rtos b 2 4)
", "
(rtos c 2 4)
"\nwielomian kwadratowy nie ma "
"rozwiazan rzeczywistych."
);strcat
);princ
);progn
);if
9/!Qumf!j!lpotusvldkf!tufsvkdf
;
(if (= delta 0) ;podwojny pierwiastek rzeczywisty
(progn
(setq
x1 (/ (- b)(* 2.0 a))
);setq
(princ
(strcat
"\nDla wspolczynnikow "
(rtos a 2 4)
", "
(rtos b 2 4)
", "
(rtos c 2 4)
"\nwielomian kwadratowy ma "
"podwojny pierwiastek rzeczywisty"
"\nx1 = "
(rtos x1 2 4)
);strcat
);princ
);progn
);if
;
(if (> delta 0) ;2 rozne pierwiastki rzeczywiste
(progn
(setq
x1 (/ (- (- b)(sqrt delta))(* 2.0 a))
x2 (/ (+ (- b)(sqrt delta))(* 2.0 a))
);setq
(princ
(strcat
"\nDla wspolczynnikow "
(rtos a 2 4)
", "
(rtos b 2 4)
", "
(rtos c 2 4)
"\nwielomian kwadratowy ma "
"2 rozne pierwiastki rzeczywiste"
"\nx1 = "
(rtos x1 2 4)
"
"
"x2 = "
(rtos x2 2 4)
);strcat
);princ
);progn
);if
;---------(terpri)
(princ)
;---------;**************************************************KONIEC
242
243
BvupMJTQ!!qsbluzd{oz!lvst
Wykonanie powyszego programu jest dla uytkownika identyczne jak programu
PROG_014.LSP rnice widoczne s tylko z punktu widzenia programisty. Jak
wida w powyszym kodzie, wykorzystujc obliczon wczeniej delt, do obliczenia
pierwiastkw rwnania wykorzystano trzy proste instrukcje warunkowe if (bez
realizacji warunku typu else):
(if (< delta 0)
(progn
.....
);progn
);if
;
(if (= delta 0)
(progn
.....
);progn
);if
;
(if (> delta 0)
(progn
.....
);progn
);if
Najpierw oblicza si warto wyraenia. Jeli wynik jest rwny nil (fasz), wwczas
instrukcja_1 nie jest wcale wykonywana. Jeli jednak warto wyraenia jest rna od
nil (prawda), wwczas wykonywana jest instrukcja_1, po czym ponownie obliczana jest
warto wyraenia. Jeli nadal warto tego wyraenia jest rna od nil, wwczas
ponownie wykonywana jest instrukcja_1 i tak dalej, dopki (while!) wyraenie ma
warto rn od nil. Jeli w kocu kiedy obliczone wyraenie bdzie rwne nil,
wwczas dopiero ptla zostanie przerwana.
Obliczenie wartoci wyraenia odbywa si przed wykonaniem instrukcji
instrukcja_1.
9/!Qumf!j!lpotusvldkf!tufsvkdf
244
Qs{zlbe!2
W przykadzie tym, bdc w ptli while, pobieramy coraz to nowe wartoci zmiennej x.
Warunkiem opuszczenia ptli while jest nadanie zmiennej x wartoci zero.
;*************************************************PROG_016
;Wykorzystanie instrukcji WHILE - wersja 1.
;
;------------------------------------------------(textpage) ;przejscie na ekran tekstowy
;---------;nadanie zmiennej x wartosci nil
(setq x nil)
;---------;wejscie w petle while
(while (/= x 0)
(progn
;---------;pobranie nowej wartosci zmiennej x
(setq
x (getint
"Podaj nowa wartosc zmiennej x [0 - koniec]: "
);getint
);setq
;---------);progn
);while
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
Command:
245
BvupMJTQ!!qsbluzd{oz!lvst
Wchodzimy w ptl while i rozpoczynamy pobieranie wartoci zmiennej
x. Wyraeniem, powodujcym dopuszczenie do wejcia w ptl jest (/= x 0).
Wyraenie to jest prawdziwe (zwraca T), gdy wczeniej zmiennej x zostaa
nadana warto nil.
Pobieramy now warto zmiennej x, po czym wracamy na pocztek ptli while,
by ponownie porwna warunek (/= x 0). Jeli warunek jest prawdziwy,
pobieramy nastpn warto zmiennej x i znowu skaczemy na pocztek ptli.
Jeli warunek jest faszywy, omijamy ptl while i wykonujemy dalszy cig
instrukcji w tym przypadku jest to tylko instrukcja (princ), powodujca
niezauwaalne zakoczenie wykonywania programu.
Qs{zlbe!3
Program ten stanowi modyfikacj programu PROG_016. Ukazuje on inny sposb kontroli wyraenia, powodujcego wyjcie z ptli while.
;*************************************************PROG_017
;Wykorzystanie instrukcji WHILE - wersja 2.
;
;------------------------------------------------(textpage) ;przejscie na ekran tekstowy
;---------;nadanie zmiennej jeszcze wartosci T
(setq jeszcze T)
;---------;wejscie w petle while
(while jeszcze
(progn
;---------;pobranie nowej wartosci zmiennej x
(setq
x (getint
"Podaj nowa wartosc zmiennej x [0 - koniec]: "
);getint
);setq
;---------;zbadanie wartosci zmiennej x
(if (= x 0)
(progn
(setq jeszcze nil)
);progn
);if
;---------);progn
);while jeszcze
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
9/!Qumf!j!lpotusvldkf!tufsvkdf
246
Wykonanie programu jest identyczne jak dla programu PROG_016 rnice s widoczne jedynie dla programisty.
Omwmy teraz wyrnione linie programu:
Inicjalizujemy zmienn jeszcze i nadajemy jej warto T (prawda). Zmienna ta
bdzie sterowa ptl while.
Poniewa wczeniej zmiennej jeszcze nadano warto T, wchodzimy w ptl
while.
Pobieramy now warto zmiennej x.
Sprawdzamy, czy zmienna x jest rwna zero.
Jeeli zmienna x jest rwna zero, ustawiamy warto zmiennej jeszcze na nil,
umoliwiajc tym samym opuszczenie ptli while.
Qs{zlbe!4
W przykadzie tym, wykorzystujemy instrukcj while do obliczenia i wypisania na
ekranie tekstowym kwadratw liczb cakowitych od 1 do 10.
;*************************************************PROG_018
;Wykorzystanie instrukcji WHILE.
;
;Program do obliczania kwadratow liczb calkowitych
;od 1 do 10.
;------------------------------------------------(textpage) ;przejscie na ekran tekstowy
;---------(setq liczba 1)
(princ "\nKwadraty liczb calkowitych od 1 do 10.\n")
(princ "\nLiczba
Kwadrat liczby\n")
(while (< liczba 11)
(progn
(setq kwadrat (* liczba liczba))
(princ
(strcat
" "
(rtos liczba 2 0)
"
"
(rtos kwadrat 2 0)
);strcat
);princ
(terpri)
(setq liczba (1+ liczba))
);progn
);while
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
247
BvupMJTQ!!qsbluzd{oz!lvst
Po wykonaniu programu ekran tekstowy bdzie wyglda nastpujco:
Command: (load "prog_018")
Kwadrat liczby
1
4
9
16
25
36
49
64
81
100
9/3/2/![bhojfepof!jotusv
9/3/2/![bhojfepof!jotusvldkf!XIJ
fepof!jotusvldkf!XIJMF
ldkf!XIJMF
Aby zapewni sobie dwa poziomy powtarzania, moemy zagniedzi ptle while.
Mona na przykad zastosowa zewntrzn ptl w celu powtarzania caego programu,
dopki uytkownik nie zadecyduje inaczej, oraz wewntrzn do sprawdzania
poprawnoci danych wejciowych.
Poniszy program pokazuje wykorzystanie zagniedonych ptli while do wypisania na
ekranie tekstowym liczb od 1 do 100 w 10 rzdach po 10 kolumn.
;*************************************************PROG_019
;Wykorzystanie zagniezdzonych instrukcji WHILE.
;
;Wypisanie liczb od 1 do 100 w 10 rzedach po 10 kolumn.
;
;-------------------------------------------------
9/!Qumf!j!lpotusvldkf!tufsvkdf
(textpage)
;---------(princ "\nWykorzystanie zagniezdzonych instrukcji WHILE.")
(princ
(strcat
"\nWypisanie liczb od 1 do 100 "
"w 10 rzedach po 10 kolumn."
);strcat
);princ
(princ "\n\n")
;---------(setq rzad 1)
;
(while (< rzad 11)
(progn
;---------(setq
kolumna 1
liczba 1
);setq
;---------(while (< kolumna 11)
(progn
;---------(princ (+ liczba (* 10 (- rzad 1))))
(princ " ")
;---------(setq
kolumna (1+ kolumna)
liczba (1+ liczba)
);setq
;---------);progn
);while kolumna
;---------(princ "\n")
(setq rzad (1+ rzad))
;---------);progn
);while rzad
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
5 6 7 8
14 15 16
24 25 26
9 10
17 18
27 28
19
29
20
30
248
249
BvupMJTQ!!qsbluzd{oz!lvst
31 32 33
41 42 43
51 52 53
61 62 63
71 72 73
81 82 83
91 92 93
Command:
34
44
54
64
74
84
94
35
45
55
65
75
85
95
36
46
56
66
76
86
96
37
47
57
67
77
87
97
38
48
58
68
78
88
98
39
49
59
69
79
89
99
40
50
60
70
80
90
100
9/!Qumf!j!lpotusvldkf!tufsvkdf
24:
if (warunek_3)
czynnosc_3
itd.
Argumentami funkcji moe by dowolna liczba list. Funkcja testuje wyraenia test,
wyznaczajc warto pierwszych elementw kadej kolejnej listy podrzdnej (w podanym porzdku), a do momentu, gdy warto ktrego z nich okae si rna od nil.
Nastpnie wartociowane jest to wyraenie result, ktre wystpuje po pozytywnie
przetestowanym wyraeniu test i zwracana jest warto ostatniego wyraenia listy
podrzdnej.
Zwykle jako ostatnie wyraenie test uywa si T (jest ono uwzgldniane w przypadku
braku pozytywnego wyniku testowania wszystkich poprzednich).
Typowym przykadem zastosowania tej instrukcji moe by program zarzdzania
danymi, ktrego dziaaniem steruje si za porednictwem menu. Uytkownik programu
otrzymuje nastpujce menu:
Mozliwe opcje programu:
1.
2.
3.
4.
5.
6.
Jest sze funkcji przeznaczonych do wykonywania tych zada oraz funkcja o nazwie
MENU, zarzdzajca pozostaymi funkcjami.
A oto i program realizujcy powysze zadania:
;*************************************************PROG_020
;Przyklad uzycia instrukcji COND - wersja 1.
;
;=================================================
;definicje poszczegolnych funkcji programu
;
;------------------------------------------------;
(defun NOWY_PLIK ()
(progn
;---------(princ "\nWybrales opcje NOWY PLIK.")
251
BvupMJTQ!!qsbluzd{oz!lvst
;---------;cialo_funkcji
;---------(princ)
;---------);progn
);NOWY_PLIK
;
;------------------------------------------------;
(defun DOPISZ_ELEMENT ()
(progn
;---------(princ "\nWybrales opcje DOPISZ ELEMENT.")
;---------;cialo_funkcji
;---------(princ)
;---------);progn
);DOPISZ_ELEMENT
;
;------------------------------------------------;
(defun USUN_ELEMENT ()
(progn
;---------(princ "\nWybrales opcje USUN ELEMENT.")
;---------;cialo_funkcji
;---------(princ)
;---------);progn
);USUN_ELEMENT
;
;------------------------------------------------;
(defun WYPISZ_ELEMENT ()
(progn
;---------(princ "\nWybrales opcje WYPISZ ELEMENT.")
;---------;cialo_funkcji
;---------(princ)
;---------);progn
);WYPISZ_ELEMENT
;
;------------------------------------------------;
(defun SZUKAJ ()
(progn
;----------
9/!Qumf!j!lpotusvldkf!tufsvkdf
(princ "\nWybrales opcje SZUKAJ.")
;---------;cialo_funkcji
;---------(princ)
;---------);progn
);SZUKAJ
;
;------------------------------------------------;
(defun ZAKONCZ_PRACE ()
(progn
;---------(princ "\nWybrales opcje ZAKONCZ PRACE.")
;---------;cialo_funkcji
;---------(setq jeszcze nil)
;---------(princ)
;---------);progn
);ZAKONCZ PRACE
;
;------------------------------------------------;Funkcja glowna
;
(defun MENU ()
(progn
;---------(setq jeszcze T)
(while jeszcze
(progn
;---------(textpage)
;---------;wypisanie zawartosci menu
(princ
(strcat
"\nMozliwe opcje programu:"
"\n1. Utworz nowy plik."
"\n2. Dolacz jeden element do pliku."
"\n3. Usun jeden element z pliku."
"\n4. Wypisz jeden element z pliku."
"\n5. Przeszukaj plik."
"\n6. Zakoncz prace."
);strcat
);princ
(terpri)
;---------;pobranie numeru opcji
(setq
opcja (getint
252
253
BvupMJTQ!!qsbluzd{oz!lvst
"\nWybierz opcje [1-6]: "
);getint
);setq
;---------(textpage)
;---------;wywolanie funkcji zwiazanej z numerem podanej opcji
(cond
((= opcja 1)(NOWY_PLIK))
((= opcja 2)(DOPISZ_ELEMENT))
((= opcja 3)(USUN_ELEMENT))
((= opcja 4)(WYPISZ_ELEMENT))
((= opcja 5)(SZUKAJ))
((= opcja 6)(ZAKONCZ_PRACE))
(T (princ "\nNiepoprawny przypadek."))
);cond
;---------;zatrzymanie realizacji programu do chwili nacisniecia
;klawisza ENTER
(getstring "\n\nNacisnij ENTER...")
;---------);progn
);while jeszcze
;---------(princ)
;---------);progn
);MENU
;
;------------------------------------------------;
;koniec definicji funkcji
;=================================================
;wywolanie funkcji MENU
(MENU)
;=================================================
(princ)
;*************************************************KONIEC
9/!Qumf!j!lpotusvldkf!tufsvkdf
254
Nacisnij ENTER...
Niepoprawny przypadek.
Nacisnij ENTER...
Command:
255
BvupMJTQ!!qsbluzd{oz!lvst
W linii tej, widzimy, jak w instrukcji cond zastosowa opcj domyln. Jeeli
warto zmiennej opcja bdzie mniejsza ni 1 lub wiksza ni 6, to instrukcja
cond wybierze instrukcje wystpujce po staej predefiniowanej T wypisze
komunikat "Niepoprawny przypadek.", po czym zostanie ponowiony wybr
opcji z menu.
Wywoujemy wczeniej zdefiniowan funkcj MENU. Postpowanie takie automatycznie wywouje funkcj MENU zaraz po pomylnym zaadowaniu
programu do interpretera AutoLISPu.
Naley zwrci szczegln uwag na odpowiedni liczb nawiasw, oddzielajcych od siebie poszczeglne warunki.
Na przykad zapis:
(cond
((= x1 1)
;lista_instrukcji
)
((and (= x1 2)(/= x3 0))
;lista_instrukcji
)
);cond
9/!Qumf!j!lpotusvldkf!tufsvkdf
256
);koniec przypadku 2
;
.....
;
(;przypadek n
(warunek_n)
(progn
;lista_instrukcji_n
);progn
);koniec przypadku n
);cond
Zapis taki jest przejrzysty i czytelny, mona rwnie atwo zlokalizowa odpowiadajc
sobie par nawiasw.
Wrmy jednak do naszego programu. Funkcja gwna MENU wywoywana bya z ptli while. Po wyborze i wykonaniu funkcji z menu 1 5, nastpowao ponowne
wywoanie funkcji MENU. Co jednak zrobi, jeli chcemy, aby funkcja MENU bya
wywoywana jednokrotnie (tzn. wykonywaa jedn z funkcji podrzdnych, po czym
opuszczaa ptl while)?
Odpowied jest bardzo prosta. Wystarczy do kadej funkcji pomocniczej dopisa na
kocu instrukcj ustalajc warto zmiennej jeszcze na nil.
Program PROG_021, znajdujcy si na doczonej dyskietce, zawiera odpowiednie
zmiany, pozwalajce na dziaanie w wyej wymieniony sposb.
Ostatnim przykadem uycia instrukcji cond bdzie program obliczajcy pierwiastki
rwnania kwadratowego.
;**************************************************PROG_022
;Wykorzystanie instrukcji COND.
;Obliczenie pierwiastkow rownania kwadratowego.
;
;-------------------------------------------------(textpage)
(princ "Obliczenie pierwiastkow rownania kwadratowego.")
(terpri)
(terpri)
;---------;pobranie wspolczynnikow a, b i c
;
(initget (+ 1 2))
(setq a (getreal "Podaj wartosc wspolczynnika a: "))
;
(initget 1)
(setq b (getreal "Podaj wartosc wspolczynnika b: "))
;
(initget 1)
(setq c (getreal "Podaj wartosc wspolczynnika c: "))
(terpri)
;---------;obliczenie delty
257
BvupMJTQ!!qsbluzd{oz!lvst
;
(setq
delta (- (* b b)(* 4.0 a c))
);setq
;---------;obliczenie pierwiastkow rownania
;
(cond
((< delta 0)
(progn ;brak pierwiastkow rzeczywistych
(princ
(strcat
"\nDla wspolczynnikow "
(rtos a 2 4)
", "
(rtos b 2 4)
", "
(rtos c 2 4)
"\nwielomian kwadratowy nie ma "
"rozwiazan rzeczywistych."
);strcat
);princ
);progn
);koniec delta < 0
;
((= delta 0) ;podwojny pierwiastek rzeczywisty
(progn
(setq
x1 (/ (- b)(* 2.0 a))
);setq
(princ
(strcat
"\nDla wspolczynnikow "
(rtos a 2 4)
", "
(rtos b 2 4)
", "
(rtos c 2 4)
"\nwielomian kwadratowy ma "
"podwojny pierwiastek rzeczywisty"
"\nx1 = "
(rtos x1 2 4)
);strcat
);princ
);progn
);koniec delta = 0
;
((> delta 0) ;2 rozne pierwiastki rzeczywiste
(progn
(setq
x1 (/ (- (- b)(sqrt delta))(* 2.0 a))
x2 (/ (+ (- b)(sqrt delta))(* 2.0 a))
);setq
(princ
9/!Qumf!j!lpotusvldkf!tufsvkdf
258
(strcat
"\nDla wspolczynnikow "
(rtos a 2 4)
", "
(rtos b 2 4)
", "
(rtos c 2 4)
"\nwielomian kwadratowy ma "
"2 rozne pierwiastki rzeczywiste"
"\nx1 = "
(rtos x1 2 4)
"
"
"x2 = "
(rtos x2 2 4)
);strcat
);princ
);progn
);koniec delta > 0
);cond
;---------(terpri)
(princ)
;---------;**************************************************KONIEC
W funkcji tej argument number jest dowoln dodatni liczb typu integer. Funkcja
dokonuje wartociowania kadego argumentu expr tyle razy, ile okrela argument
number i zwraca warto ostatniego z nich.
259
BvupMJTQ!!qsbluzd{oz!lvst
Funkcja ta jest podobna do by moe znanej Ci z innych jzykw programowania
funkcji for. Jej dziaanie przeledzimy na poniszym przykadzie. Bdzie to modyfikacja programu PROG_018, ktry oblicza i wypisuje kwadraty liczb cakowitych od 1 do
10. W programie PROG_018, zostaa do tego celu uyta funkcja while. W poniszym
programie poka Ci, jak rozwiza to zadanie przy pomocy ptli repeat.
A oto i nasz program:
;*************************************************PROG_023
;Wykorzystanie instrukcji REPEAT.
;
;Program do obliczania kwadratow liczb calkowitych
;od 1 do 10.
;------------------------------------------------(textpage) ;przejscie na ekran tekstowy
;---------(setq liczba 1)
(princ "\nKwadraty liczb calkowitych od 1 do 10.\n")
(princ "\nLiczba
Kwadrat liczby\n")
(repeat 10 ;zmiana w stosunku do PROG11
(progn
(setq kwadrat (* liczba liczba))
(princ
(strcat
" "
(rtos liczba 2 0)
"
"
(rtos kwadrat 2 0)
);strcat
);princ
(terpri)
(setq liczba (1+ liczba))
);progn
);repeat
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
9/!Qumf!j!lpotusvldkf!tufsvkdf
25:
9/5/2/![bhojfepof!jotu
9/5/2/![bhojfepof!jotusvldkf!SF
hojfepof!jotusvldkf!SFQFBU
svldkf!SFQFBU
Zagniedanie instrukcji repeat jest identyczne jak instrukcji while, co zobrazowano na
poniszym przykadzie.
;*************************************************PROG_024
;Wykorzystanie zagniezdzonych instrukcji REPEAT.
;
;Wypisanie liczb od 1 do 100 w 10 rzedach po 10 kolumn.
;
;------------------------------------------------(textpage)
;---------(princ "\nWykorzystanie zagniezdzonych instrukcji REPEAT.")
(princ
(strcat
"\nWypisanie liczb od 1 do 100 "
"w 10 rzedach po 10 kolumn."
);strcat
);princ
(princ "\n\n")
;---------(setq rzad 1)
;
(repeat 10
(progn
;---------(setq
kolumna 1
liczba 1
);setq
;---------(repeat 10
(progn
;---------(princ (+ liczba (* 10 (- rzad 1))))
(princ " ")
;---------(setq
kolumna (1+ kolumna)
liczba (1+ liczba)
);setq
;---------);progn
);repeat
;---------(princ "\n")
(setq rzad (1+ rzad))
;---------);progn
);repeat
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
261
BvupMJTQ!!qsbluzd{oz!lvst
Po wykonaniu programu ekran bdzie wyglda identycznie, jak w programie
PROG_019.
Omwmy teraz wyrnione linie programu, ktre obrazuj zmiany w stosunku do kodu
z programu PROG_019:
Instrukcja (while (< rzad 11) .....), bdca ptl zewntrzn, zostaa zastpiona
instrukcj (repeat 10 .....) liczba powtrze ptli wynosi 10.
Instrukcja (while (< kolumna 11) .....), bdca ptl wewntrzn, zostaa
zastpiona instrukcj (repeat 10 .....) liczba powtrze ptli wynosi 10.
9/!Qumf!j!lpotusvldkf!tufsvkdf
262
2. Obliczane jest wyraenie warunkowe. Jeli jest rwne 0 praca ptli jest
przerywana.
3. Jeli powyej okazao si, e wyraenie byo rne od zera, wwczas wykonywane zostaj instrukcje bdce treci ptli.
4. Po wykonaniu treci ptli wykonana zostaje instrukcja inst_krok, po czym powtarzana jest akcja 2).
Pora teraz na wyjanienie, dlaczego w celu omwienia ptli for posuyem si przykadem
z jzyka C. Ot w standardowych funkcjach jzyka AutoLISP nie ma definicji ptli for!!!
Jest wprawdzie instrukcja repeat, lecz nie jest to jeszcze ptla for w caej okazaoci.
Powyszy problem da si jednak obej. Jzyk AutoLISP oferuje nam konstrukcj tzw.
listy-funkcji. Poniewa funkcja jest list, wic po prostu zbudujmy j jak list, a nastpnie wykonajmy jako funkcj. Pisanie programw wykorzystujcych takie sztuczki jest
moliwe tylko w LISPie. Inne jzyki nie pozwalaj na traktowanie obiektu raz jako
danej (lista), a raz jako czci programu (funkcja).
Temat listy-funkcji zostanie omwiony dokadnie podczas omawiania funkcji, teraz
wic zostanie zaprezentowana definicja ptli FOR, ktrej autorami s Panowie: Maciej
Horczyczak i Jacek Skierski ksika AutoLISP dla uytkownikw AutoCADa.
;*************************************************PROG_025
;Maciej Horczyczak & Jacek Skierski
;
;Petla FOR (jak w BASIC'u)
;(for 'zm_ster
;
war_pocz_zm_ster
war_kon_zm_ster
krok_zm_ster
;
'lista instrukcji)
;
;Przyklady wywolania:
;
;(for 'i 10 0 -3 '(print i))
;
;(for 'i 1 10 1
; '(progn
;
(print i)
;
(print (+ i 1))
;
);progn
;);for i
;
;------------------------------------------------(defun FOR ( zmster ip ik ki zakres / fun w )
(progn
(if (> ki 0)
(setq w (eval '<=))
(setq w (eval '>=))
);if
(setq fun (list (list '/ ) zakres))
(set zmster ip)
(while (w (eval zmster) ik)
(FUN)
263
BvupMJTQ!!qsbluzd{oz!lvst
(set zmster (+ ki (eval zmster)))
);while
(setq fun nil)
(princ)
);progn
);FOR
;
;*************************************************KONIEC
Qs{zlbe!2
W przykadzie tym, po pobraniu wartoci pocztkowej, kocowej oraz kroku ptli,
wypisujemy na ekran wybrane liczby.
;*************************************************PROG_026
;Wykorzystanie petli FOR - przyklad 1.
;
;------------------------------------------------;odszukanie i zaladowanie pliku PROG_025.LSP
;
(setq plik (findfile "prog_025.lsp"))
(if plik
(progn ;plik zostal znaleziony
(load plik)
);progn
(progn ;else - nia znaleziono pliku
(alert
(strcat
"Nie znaleziono pliku PROG_025.LSP!!!"
"\nWykonywanie programu przerwane."
);strcat
);alert
(exit)
);progn
);if
;---------;jesli plik prog_025 zostal znaleziony
;wykorzystanie petli for
;
(textpage) ;przejscie na ekran tekstowy
;
(princ "\nPrzyklad wykorzystania petli for.")
;
(initget (+ 1 2 4))
(setq x1 (getint "\nPodaj wartosc poczatkowa petli: "))
;
(initget (+ 1 2 4))
(setq x2 (getint "\nPodaj wartosc koncowa petli: "))
;
9/!Qumf!j!lpotusvldkf!tufsvkdf
264
(initget (+ 1 2 4))
(setq x3 (getint "\nPodaj krok petli: "))
;
(princ
(strcat
"\nWypisywanie od "
(rtos x1 2 0)
" do "
(rtos x2 2 0)
" z krokiem = "
(rtos x3 2 0)
".\n"
);strcat
);princ
;
(for 'i x1 x2 x3
'(progn
(princ i)
(terpri) ;przejscie do nowej linii
);progn
);for i
;
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
Wypisywanie od 1 do 10 z krokiem = 2.
1
3
5
7
9
Command:
265
BvupMJTQ!!qsbluzd{oz!lvst
Funkcja ta poszukuje okrelonego pliku (w naszym przypadku jest to plik
PROG_025.LSP) w bibliotecznej ciece poszukiwa AutoCADa. Jeli podany
plik zostanie znaleziony, funkcja zwraca pen nazw pliku wraz ze ciek
dostpu, w przeciwnym wypadku funkcja zwraca nil.
Warto zwracana przez funkcj findfile jest nastpnie podstawiana pod zmienn plik.
Jeli plik PROG_025.LSP zosta znaleziony, funkcja load powoduje jego
zaadowanie.
Jeli plik PROG_025.LSP nie zosta znaleziony, standardowa funkcja AutoLISPu
alert powoduje wypisanie w oknie dialogowym podanego acucha tekstu.
Funkcja exit wymusza zakoczenie biecego programu uytkowego. Wywoujemy j po wywietleniu komunikatu ostrzegawczego w oknie dialogowym.
Gdyby funkcja ta nie zostaa tutaj zastosowana, w trakcie realizacji dalszej
czci programu otrzymalibymy komunikat o bdzie gdy wystpiaby
prba wywoania niezdefiniowanej funkcji FOR.
Zapis (initget (+ 1 2 4)) jest rwnowany zapisowi (initget 5). Nie dopuszcza on
do podania pustego ENTER, liczby zerowej lub liczby ujemnej podczas najbliszego wywoania funkcji entsel, nentsel lub getxxx (za wyjtkiem getstring,
getenv i getvar).
To tutaj wywoujemy nasz ptl FOR. Oprcz podania wartoci pocztkowej,
kocowej oraz kroku ptli, pierwszym argumentem funkcji jest nazwa zmiennej
sterujcej prac ptli.
Nazwa zmiennej sterujcej prac ptli musi by poprzedzona apostrofem (tzn. musi
by kwotowana). Jeli o tym zapomnisz, program moe da nieoczekiwane rezultaty.
Qs{zlbe!3
Analizujc wygld ekranu w przykadzie pierwszym, z pewnoci zauwaye dodatkowe odstpy pomidzy wartoci pocztkow, kocow oraz krokiem ptli, np:
Podaj wartosc poczatkowa petli: 1
wolna_linia
Podaj wartosc koncowa petli: 10
Dzieje si tak dlatego, e funkcje typu getxxx musz by zakoczone naciniciem klawisza ENTER, i to wanie powoduje powstanie dodatkowej pustej linii.
9/!Qumf!j!lpotusvldkf!tufsvkdf
266
267
BvupMJTQ!!qsbluzd{oz!lvst
;
(for 'i x1 x2 x3
'(progn
(princ i)
(princ " ")
);progn
);for i
;
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
Wypisywanie od 1 do 10 z krokiem = 2.
1 3 5 7 9
Command:
Omwmy teraz wyrnione linie programu, obrazujce zmiany w stosunku do programu PROG_026:
Przy wypisywaniu na ekran tekstu "Podaj wartosc koncowa petli:", zosta pominity znak nowej linii, umieszczony na pocztku acucha. Tym samym
zostaa usunita pierwsza wolna linia.
Przy wypisywaniu na ekran tekstu "Podaj krok petli:", zosta pominity
znak nowej linii, umieszczony na pocztku acucha. Tym samym zostaa usunita druga wolna linia.
Zamiast funkcji terpri, powodujcej przejcie do nowej linii po wypisaniu
liczby, uywamy instrukcji princ, aby oddzieli od siebie poszczeglne liczby,
wypisywane w jednym rzdzie.
Qs{zlbe!4
Przykad ten pokazuje, jak za pomoc ptli FOR mona tworzy list lub wywietla jej
zawarto.
;*************************************************PROG_028
;Wykorzystanie petli FOR - przyklad 3.
;
;------------------------------------------------;odszukanie i zaladowanie pliku PROG_025.LSP
;
(setq plik (findfile "prog_025.lsp"))
9/!Qumf!j!lpotusvldkf!tufsvkdf
(if plik
(progn ;plik zostal znaleziony
(load plik)
);progn
(progn ;else - nia znaleziono pliku
(alert
(strcat
"Nie znaleziono pliku PROG_025.LSP!!!"
"\nWykonywanie programu przerwane."
);strcat
);alert
(exit)
);progn
);if
;---------;jesli plik prog_025 zostal znaleziony
;wykorzystanie petli for
;
(textpage) ;przejscie na ekran tekstowy
;
(princ "\nPrzyklad wykorzystania petli for.")
;
(initget (+ 1 2 4))
(setq
x1 (getint
268
);getint
);setq
;
(setq lista_1 (list))
;
;pobranie zmiennych i umieszczenie ich na liscie lista_1
(terpri)
(for 'i 1 x1 1
'(progn
;pobranie typu zmiennej
(initget "I R S")
(setq
typ (getkword
(strcat
"\Podaj typ zmiennej numer "
(rtos i 2 0)
" [I - integer, R - real, S - string]: "
);strcat
);getkword
);setq
(setq typ (strcase typ))
;
;pobranie wartosci zmiennej
(princ
(strcat
"Podaj wartosc zmiennej numer "
(rtos i 2 0)
": "
269
BvupMJTQ!!qsbluzd{oz!lvst
);strcat
);princ
(cond
((= typ "I")(setq zmienna (getint)))
((= typ "R")(setq zmienna (getreal)))
((= typ "S")(setq zmienna (getstring T)))
);cond
;
;umieszczenie zmiennej na liscie lista_1
(setq
lista_1 (append lista_1 (list zmienna))
);setq
;
);progn
);for i
;
;wyswietlenie utworzonej listy
(textpage) ;przejscie na ekran tekstowy
(princ lista_1)
(getstring T "\nNacisnij ENTER...")
(princ "\nA oto twoja lista wyswietlona funkcja PRIN1:\n")
(prin1 lista_1)
(getstring T "\nNacisnij ENTER...")
;
;wyswietlenie typu i wartosci poszczegolnych zmiennych
(textpage) ;przejscie na ekran tekstowy
(princ "Typy i wartosci zmiennych na liscie LISTA_1:")
(terpri) ;przejscie do nowej linii
(for 'i 1 x1 1
'(progn
;---------;wyswietlenie numeru zmiennej
(princ
(strcat
"\nZmienna numer "
(rtos i 2 0)
);strcat
);princ
;---------;wyswietlenie typu zmiennej
(setq typ (type (nth (- i 1) lista_1)))
(cond
((= typ 'INT)(setq typ "integer"))
((= typ 'REAL)(setq typ "real"))
((= typ 'STR)(setq typ "string"))
);cond
(princ
(strcat
"\nTyp zmiennej = "
typ
);strcat
);princ
;----------
9/!Qumf!j!lpotusvldkf!tufsvkdf
;wyswietlenie wartosci zmiennej
(setq wartosc (nth (- i 1) lista_1))
(princ "\nWartosc zmiennej = ")
(if (= typ "string")
(progn
(prin1 wartosc)
);progn
(progn ;else
(princ wartosc)
);progn
);if
;---------;wolna linia pomiedzy poszczegolnymi zmiennymi
(terpri)
;---------);progn
);for i
;
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
integer, R - real, S 10
26:
271
BvupMJTQ!!qsbluzd{oz!lvst
Zmienna numer 2
Typ zmiennej = real
Wartosc zmiennej = 1.25
Zmienna numer 3
Typ zmiennej = string
Wartosc zmiennej = "Marek Dudek"
Command:
9/!Qumf!j!lpotusvldkf!tufsvkdf
272
wwczas:
(type
(type
(type
(type
a)
b)
c)
d)
zwraca
zwraca
zwraca
zwraca
INT
REAL
STR
LIST
Tak wic, dla i=1, pobieramy zerowy element z listy, a dla i=3, pobieramy drugi
element z listy, itd.
Qs{zlbe!5
W przykadzie tym, wykorzystujemy ptl FOR do obliczenia i wypisania kwadratw
liczb cakowitych od 1 do 10.
;*************************************************PROG_029
;Wykorzystanie petli FOR - przyklad 4.
;
;Program do obliczania kwadratow liczb calkowitych
;od 1 do 10.
;------------------------------------------------;odszukanie i zaladowanie pliku PROG_025.LSP
;
(setq plik (findfile "prog_025.lsp"))
(if plik
(progn ;plik zostal znaleziony
(load plik)
273
BvupMJTQ!!qsbluzd{oz!lvst
);progn
(progn ;else - nia znaleziono pliku
(alert
(strcat
"Nie znaleziono pliku PROG_025.LSP!!!"
"\nWykonywanie programu przerwane."
);strcat
);alert
(exit)
);progn
);if
;------------------------------------------------(textpage) ;przejscie na ekran tekstowy
;---------(princ "\nKwadraty liczb calkowitych od 1 do 10.\n")
(princ "\nLiczba
Kwadrat liczby\n")
(for 'i 1 10 1
'(progn
(setq kwadrat (* i i))
(princ
(strcat
" "
(rtos i 2 0)
"
"
(rtos kwadrat 2 0)
);strcat
);princ
(terpri)
);progn
);for i
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
9/6/2/![bhojfe
9/6/2/![bhojfepof!jotusvld
[bhojfepof!jotusvldkf!GPS
pof!jotusvldkf!GPS
Konstrukcja zagniedonych ptli for jest podobna do ptli while czy repeat. Poniej
przedstawiono znany Ci ju program wypisujcy liczby od 1 do 100 w 10 rzdach po 10
kolumn.
9/!Qumf!j!lpotusvldkf!tufsvkdf
;*************************************************PROG_030
;Wykorzystanie zagniezdzonych instrukcji FOR.
;
;Wypisanie liczb od 1 do 100 w 10 rzedach po 10 kolumn.
;
;------------------------------------------------;odszukanie i zaladowanie pliku PROG_025.LSP
;
(setq plik (findfile "prog_025.lsp"))
(if plik
(progn ;plik zostal znaleziony
(load plik)
);progn
(progn ;else - nia znaleziono pliku
(alert
(strcat
"Nie znaleziono pliku PROG_025.LSP!!!"
"\nWykonywanie programu przerwane."
);strcat
);alert
(exit)
);progn
);if
;
;------------------------------------------------(textpage)
;---------(princ "\nWykorzystanie zagniezdzonych instrukcji FOR.")
(princ
(strcat
"\nWypisanie liczb od 1 do 100 "
"w 10 rzedach po 10 kolumn."
);strcat
);princ
(princ "\n\n")
;---------(for 'i 1 10 1
'(progn
;---------(for 'j 1 10 1
'(progn
;---------(princ (+ j (* 10 (- i 1))))
(princ " ")
;---------);progn
);for j
;---------(princ "\n")
;---------);progn
);for i
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
274
275
BvupMJTQ!!qsbluzd{oz!lvst
Wykonanie powyszego programu bdzie identyczne jak programw PROG_019
i PROG_024.
Omwmy teraz wyrnione linie programu.
Rozpoczynamy zewntrzn ptl FOR. Wykonujemy j 10 razy po zmiennej
i z krokiem 1.
Rozpoczynamy wewntrzn ptl FOR. Wykonujemy j 10 razy po zmiennej
j z krokiem 1.
Obliczamy warto liczby do wypisania na ekranie, wykorzystujc zmienne
i oraz j. Obliczon warto podstawiamy jako argument funkcji princ.
Oddzielamy dwoma spacjami poszczeglne liczby w wierszu.
Bdc ju poza ptl wewntrzn, przechodzimy do nowego wiersza, aby wypisa kolejne zestawy liczb.
9/!Qumf!j!lpotusvldkf!tufsvkdf
Oto przykad realizacji ptli do ... while ... w jzyku AutoLISP.
;*************************************************PROG_031
;Funkcja DO_WHILE stanowi przyklad realizacji petli
;do (instrukcje) while (warunek) w jezyku AutoLISP.
;
;Funkcja wywolywana jest z dwoma argumentami:
;instrukcje - lista kwotowanych instrukcji do wykonania
;warunek - kwotowany warunek, jaki nalezy spelnic,
;
aby opuscic petle DO_WHILE
;
;Przyklady wywolania funkcji:
;patrz funkcje C:FUN_1 - C:FUN_4
;
;------------------------------------------------;
(defun DO_WHILE (instrukcje warunek
/ jeszcze fun_instrukcje fun_warunek
wartosc
)
(progn
;---------(setq
jeszcze T
fun_instrukcje (list (list '/) instrukcje)
fun_warunek (list (list '/) warunek)
);setq
(while jeszcze
(progn
(FUN_INSTRUKCJE)
(setq wartosc (FUN_WARUNEK))
(if (= wartosc T)
(progn
(FUN_INSTRUKCJE)
);progn
(progn ;else - wartosc = nil
(setq jeszcze nil)
);progn
);if
);progn
);while jeszcze
;---------(princ)
;---------);progn
);DO_WHILE
;
;------------------------------------------------;Funkcja kontrolna C:FUN_1 - uzycie instrukcji DO_WHILE.
;Po wykonaniu funkcji x1 = 1, x2 = 2.
;
(defun C:FUN_1 ()
(progn
(setq
x1 1
276
277
BvupMJTQ!!qsbluzd{oz!lvst
x2 1
);setq
(
DO_WHILE
'(progn ;do
(setq x2 (1+ x2))
);progn
'(progn ;while
(/= x1 1)
);progn
)
(princ)
);progn
);C:FUN_1
;
;------------------------------------------------;Funkcja kontrolna C:FUN_2 - uzycie instrukcji WHILE.
;Po wykonaniu funkcji x1 = 1, x2 = 1.
;
(defun C:FUN_2 ()
(progn
(setq
x1 1
x2 1
);setq
(while (/= x1 1)
(progn
(setq x2 (1+ x2))
);progn
);while
(princ)
);progn
);C:FUN_2
;
;------------------------------------------------;Funkcja kontrolna C:FUN_3 - uzycie instrukcji DO_WHILE.
;Po wykonaniu funkcji x1 = 12.
;
(defun C:FUN_3 ()
(progn
(setq
x1 1
);setq
(
DO_WHILE
'(progn ;do
(setq x1 (1+ x1))
);progn
'(progn ;while
(< x1 11)
);progn
)
(princ)
);progn
9/!Qumf!j!lpotusvldkf!tufsvkdf
278
);C:FUN_3
;
;------------------------------------------------;Funkcja kontrolna C:FUN_4 - uzycie instrukcji WHILE.
;Po wykonaniu funkcji x1 = 11.
;
(defun C:FUN_4 ()
(progn
(setq
x1 1
);setq
(while (< x1 11)
(progn
(setq x1 (1+ x1))
);progn
);while
(princ)
);progn
);C:FUN_4
;
;------------------------------------------------;*************************************************KONIEC
Naley pamita o tym, e zarwno lista instrukcji do wykonania w ptli jak rwnie
warunek wyjcia z ptli musz by poprzedzone apostrofem (tzn. kwotowane) tak
wic ptl DO_WHILE mona przedstawi nastpujco:
(DO_WHILE
'(progn
lista_instrukcji
);progn
'(progn
warunek
);progn
)
279
BvupMJTQ!!qsbluzd{oz!lvst
(progn ;plik zostal znaleziony
(load plik)
);progn
(progn ;else - nia znaleziono pliku
(alert
(strcat
"Nie znaleziono pliku PROG_031.LSP!!!"
"\nWykonywanie programu przerwane."
);strcat
);alert
(exit)
);progn
);if
;------------------------------------------------(textpage) ;przejscie na ekran tekstowy
;---------(setq liczba 1)
(princ "\nKwadraty liczb calkowitych od 1 do 10.\n")
(princ "\nLiczba
Kwadrat liczby\n")
(DO_WHILE
'(progn ;do
(setq kwadrat (* liczba liczba))
(princ
(strcat
" "
(rtos liczba 2 0)
"
"
(rtos kwadrat 2 0)
);strcat
);princ
(terpri)
(setq liczba (1+ liczba))
);progn
'(progn ;while
(< liczba 10)
);progn
);DO_WHILE
;---------(princ)
;------------------------------------------------;*************************************************KONIEC
9/!Qumf!j!lpotusvldkf!tufsvkdf
27:
281
BvupMJTQ!!qsbluzd{oz!lvst
1. W moim edytorze jest komenda, ktra pozwala mi odszuka drugi nawias:
pokazuj nawias lewy (otwierajcy), a edytor odszukuje mi odpowiadajcy mu
nawias prawy (zamykajcy). Jeli nawet pogubi si z tymi nawiasami w dugim
programie, to dziki tej opcji atwo znale bd. Sprawd, czy i w Twoim
edytorze jest podobna komenda.
2. Mam sposb, ktry prawie cakowicie pozwala mi unikn bdu. Pisz
warunek, np. (while (< i 10), przechodz linijk niej, pisz instrukcj grupujc
(progn, przechodz 2 linijki niej, zamykam instrukcj grupujc );progn,
przechodz linijk niej, zamykam warunek );while, wracam 2 linijki wyej i
dopiero przystpuj do pisania listy instrukcji.
3. Poniej przedstawiono przykad zapisu nawiasw dla instrukcji while cyframi
oznaczono kolejne dziaania:
(while (< i 10)
(progn
lista_instrukcji
);progn
);while
Sposb drugi jest naprawd dobry. Od czasu, gdy go stosuj, nawet kilkakrotne
zagniedanie instrukcji while, if, repeat, for nie jest mi straszne, a liczba nie
zamknitych nawiasw spada prawie do zera. Ale nawet wtedy, gdy jaki nawias nie
zostaje zamknity, szybko odnajduj jego lokalizacj wykorzystujc sposb pierwszy.
Prosz Ci, wyprbuj sposb drugi to naprawd dziaa!!!
A tak na marginesie, instrukcje while, cond i repeat nie wymagaj stosowania instrukcji grupujcych progn ja jednak je stosuj dla zwikszenia czytelnoci programu.
Inaczej ma si sprawa z instrukcj warunkow if.
Przeanalizujmy par przykadw.
Qs{zlbe!2
(setq x 10)
(if (= x 10)
(princ "\nX rowna sie 10.")
);if
Qs{zlbe!3
(setq x 10)
(if (= x 10)
9/!Qumf!j!lpotusvldkf!tufsvkdf
282
(progn
(princ "\nX rowna sie 10.")
);progn
);if
Qs{zlbe!4
(setq x 5)
(if (= x 10)
(princ "\nX rowna sie 10.")
(princ "\nX nie rowna sie 10.")
);if
;else
W przykadzie tym, w wyraeniu if s 2 instrukcje nie zgrupowane funkcj progn, wobec tego interpreter zakada, e instrukcja ma zosta wykonana, gdy warunek (= x
10) jest prawdziwy ma warto T, natomiast instrukcja jest instrukcj typu else,
ktra ma zosta wykonana (i zostaje wykonana), gdy warunek (= x 10) jest faszywy
ma warto nil.
Qs{zlbe!5
(setq x 5)
(if (= x 10)
(progn
(princ "\nX rowna sie 10.")
);progn
(progn ;else
(princ "\nX nie rowna sie 10.")
);progn
);if
Qs{zlbe!6
(setq x 10)
(if (= x 10)
283
BvupMJTQ!!qsbluzd{oz!lvst
(progn
(princ "\nX rowna sie 10.")
(setq y x)
);progn
(progn ;else
(princ "\nX nie rowna sie 10.")
(setq y 0)
);progn
);if
Przykad ten jest przykadem, gdzie instrukcje grupujce progn staj si koniecznoci.
W obydwu blokach trzeba bowiem wykona wicej ni jedn instrukcj musz one
zatem zosta zgrupowane w jeden blok instrukcj grupujc progn.
Osobicie stosuj zapis z przykadw 2, 4 i 5, nawet wtedy, gdy w wyraeniu if jest
tylko jedna instrukcja. Powd? Przeledmy to na poniszym przykadzie.
Qs{zlbe!7
Zamy, e piszc program zapisujesz nastpujce wyraenie warunkowe:
(if (= x 10)
(setq y 0)
);if
W wyraeniu tym chciae, aby obie instrukcje zostay wykonane, gdy warunek (= x
10) bdzie prawdziwy. W rzeczywistoci wykonana zostanie tylko instrukcja . Z
braku instrukcji grupujcej progn instrukcja zostanie wykonana, gdy warunek (= x 10)
bdzie faszywy nie zostanie jednak wtedy wykonana instrukcja . Prawidowy
zapis wyraenia warunkowego if powinien wic wyglda tak:
(if (= x 10)
(progn
(setq y 0)
9/!Qumf!j!lpotusvldkf!tufsvkdf
284
(setq z 1.25)
);progn
);if
285
BvupMJTQ!!qsbluzd{oz!lvst