9/!Qumf!j!lpotusvldkf!tufsvk df 22:

Podobne dokumenty
Pętle. Dodał Administrator niedziela, 14 marzec :27

Programowanie w języku Python. Grażyna Koba

1 Podstawy c++ w pigułce.

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Wstęp do informatyki- wykład 7

Naukę zaczynamy od poznania interpretera. Interpreter uruchamiamy z konsoli poleceniem

4. Funkcje. Przykłady

Nazwa implementacji: Nauka języka Python wyrażenia warunkowe. Autor: Piotr Fiorek. Opis implementacji: Poznanie wyrażeń warunkowych if elif - else.

for (inicjacja_warunkow_poczatkowych; wyrazenie_warunkowe; wyrazenie_zwiekszajace) { blok instrukcji; }

Podstawy Programowania C++

Liczby losowe i pętla while w języku Python

for (inicjacja_warunkow_poczatkowych(końcowych); wyrazenie_warunkowe; wyrazenie_zwiekszajace(zmniejszające)) { blok instrukcji; }

7. Pętle for. Przykłady

Pzetestuj działanie pętli while i do...while na poniższym przykładzie:

Podstawy Programowania Podstawowa składnia języka C++

Lekcja : Tablice + pętle

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

Cw.12 JAVAScript w dokumentach HTML

JAVAScript w dokumentach HTML (2)

Jak zawsze wyjdziemy od terminologii. While oznacza dopóki, podczas gdy. Pętla while jest

Pętla for. Wynik działania programu:

Podstawy programowania w języku Visual Basic dla Aplikacji (VBA)

a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a[10]

x 2 = a RÓWNANIA KWADRATOWE 1. Wprowadzenie do równań kwadratowych 2. Proste równania kwadratowe Równanie kwadratowe typu:

3. Instrukcje warunkowe

1 Podstawy c++ w pigułce.

Pętla for. Matematyka dla ciekawych świata -19- Scilab. for i=1:10... end. for k=4:-1:1... end. k=3 k=4. k=1. k=2

Programowanie w Turbo Pascal

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Warto też w tym miejscu powiedzieć, że w C zero jest rozpoznawane jako fałsz, a wszystkie pozostałe wartości jako prawda.

Blockly Kodowanie pomoc.

do instrukcja while (wyrażenie);

WHILE (wyrażenie) instrukcja;

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

METODY KOMPUTEROWE W OBLICZENIACH INŻYNIERSKICH

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

lekcja 8a Gry komputerowe MasterMind

2. Zmienne i stałe. Przykłady Napisz program, który wypisze na ekran wynik dzielenia 281 i 117 w postaci liczby mieszanej (tj. 2 47/117).

Pętle. for, while, do... while, foreach. Materiał pomocniczy do kursu Podstawy programowania Autor: Grzegorz Góralski ggoralski.

Python wprowadzenie. Warszawa, 24 marca PROGRAMOWANIE I SZKOLENIA

Nazwa implementacji: Nauka języka Python pętla for. Autor: Piotr Fiorek

Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek].

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Programowanie - instrukcje sterujące

PODSTAWY INFORMATYKI 1 PRACOWNIA NR 6

Instrukcje warunkowe i skoku. Spotkanie 2. Wyrażenia i operatory logiczne. Instrukcje warunkowe: if else, switch.

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

OPERACJE WEJŚCIA / WYJŚCIA. wysyła sformatowane dane do standardowego strumienia wyjściowego (stdout)

Zapis algorytmów: schematy blokowe i pseudokod 1

Przedrostkowa i przyrostkowa inkrementacja i dekrementacja

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane

przedmiot kilka razy, wystarczy kliknąć przycisk Wyczaruj ostatni,

#include <stdio.h> int main( ) { int x = 10; long y = 20; double s; s = x + y; printf ( %s obliczen %d + %ld = %f, Wynik, x, y, s ); }

Wstęp do Programowania, laboratorium 02

#include <stdio.h> void main(void) { int x = 10; long y = 20; double s; s = x + y; printf ( %s obliczen %d + %ld = %f, Wynik, x, y, s ); }

Rekurencja (rekursja)

Informacja o języku. Osadzanie skryptów. Instrukcje, komentarze, zmienne, typy, stałe. Operatory. Struktury kontrolne. Tablice.

WHILE (wyrażenie) instrukcja;

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Każde wykonanie bloku instrukcji nazywamy pojedynczym przebiegiem lub iteracją pętli.

Być może jesteś doświadczonym programistą, biegle programujesz w Javie,

Umieszczanie kodu. kod skryptu

Wiadomości wstępne Środowisko programistyczne Najważniejsze różnice C/C++ vs Java

Mathcad c.d. - Macierze, wykresy 3D, rozwiązywanie równań, pochodne i całki, animacje

Instrukcje sterujące

Informatyka I. Wykład 3. Sterowanie wykonaniem programu. Instrukcje warunkowe Instrukcje pętli. Dr inż. Andrzej Czerepicki

Algorytm. a programowanie -

Programowanie i techniki algorytmiczne

JAVAScript w dokumentach HTML (1) JavaScript jest to interpretowany, zorientowany obiektowo, skryptowy język programowania.

Wstęp do programowania

Przykłady zastosowań funkcji tekstowych w arkuszu kalkulacyjnym

Pomorski Czarodziej 2016 Zadania. Kategoria C

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Podstawy programowania Laboratorium. Ćwiczenie 2 Programowanie strukturalne podstawowe rodzaje instrukcji

Instrukcje sterujące. wer. 11 z drobnymi modyfikacjami! Wojciech Myszka :53:

1 Powtórzenie wiadomości

Bloki anonimowe w PL/SQL

ALGORYTMY. 1. Podstawowe definicje Schemat blokowy

Administracja sieciowymi systemami operacyjnymi III Klasa - Linux

Układy VLSI Bramki 1.0

PoniŜej znajdują się pytania z egzaminów zawodowych teoretycznych. Jest to materiał poglądowy.

I. Podstawy języka C powtórka

Kilka prostych programów

Algorytmy i struktury danych

Wykorzystanie języka AutoLISP.

Wskazówki dotyczące zmiennych, tablic i procedur 1

KURS C/C++ WYKŁAD 2. char znak; znak = a ; Program 2 #include<stdio.h> void main() { char znak; while( (znak = getchar() )!= t ) putchar(znak); }

1 Wprowadzenie do algorytmiki

Informatyka I: Instrukcja 4.2

Schematy blokowe I. 1. Dostępne bloki: 2. Prosty program drukujący tekst.

Wykład II PASCAL - podstawy składni i zmienne, - instrukcje wyboru, - iteracja, - liczby losowe

Warsztaty dla nauczycieli

JAVAScript w dokumentach HTML (1)

Programowanie strukturalne i obiektowe. Funkcje

Część XV C++ Ćwiczenie 1

AutoLISP w środowisku VLISP

Wykład z Technologii Informacyjnych. Piotr Mika

Skrypty powłoki Skrypty Najcz ciej u ywane polecenia w skryptach:

Podstawy programowania. Wykład: 4. Instrukcje sterujące, operatory. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Transkrypt:

9/!Qumf!j!lpotusvldkf!tufsvk df 22: Jak już wcześniej powiedzieliśmy, w skład programów napisanych w języku AutoLISP wchodzą funkcje. Wewnątrz funkcji występują instrukcje. O sile języka w dużej mierze decydują mechanizmy służące do specyfikacji kolejności wykonywania instrukcji. Wszystkie nowoczesne języki programowania mają po kilka struktur sterujących, które pozwalają, aby pewne fragmenty programu były wykonywane tylko jeden raz lub wielokrotnie w zależności od spełnienia lub niespełnienia jakiegoś warunku. Inaczej mówiąc od prawdziwości lub fałszywości jakiegoś wyrażenia. Ponieważ temat prawda fałsz w AutoLISPie został już omówiony wcześniej (przy okazji omawiania operatorów), zostaną teraz omówione po kolei poszczególne konstrukcje sterujące stosowane w języku AutoLISP. Programy omówione w tym rozdziale PROG_012.LSP Przykład instrukcji warunkowej if. PROG_013.LSP Przykład instrukcji warunkowej if z zastosowaniem instrukcji złożonej. PROG_014.LSP Przykład instrukcji warunkowej if. Obliczenie pierwiastków równania kwadratowego wersja 1. PROG_015.LSP Przykład instrukcji warunkowej if. Obliczenie pierwiastków równania kwadratowego wersja 2. PROG_016.LSP Przykład użycia instrukcji while wersja1.

231 BvupMJTQ!!qsbluzd{oz!lvst PROG_017.LSP Przykład użycia instrukcji while wersja2. PROG_018.LSP Przykład użycia instrukcji while. Obliczenie i wypisanie kwadratów liczb całkowitych od 1 do 10. PROG_019.LSP Przykład zagnieżdżonej instrukcji while. Wypisanie liczb od 1 do 100 w 10 rzędach po 10 kolumn. PROG_020.LSP Przykład użycia instrukcji cond wersja1. PROG_021.LSP Przykład użycia instrukcji cond wersja2. PROG_022.LSP Przykład użycia instrukcji cond. Obliczenie pierwiastków równania kwadratowego. PROG_023.LSP Przykład użycia instrukcji repeat. Obliczenie i wypisanie kwadratów liczb całkowitych od 1 do 100. PROG_024.LSP Przykład użycia zagnieżdżonych instrukcji repeat. Wypisanie liczb od 1 do 100 w 10 rzędach po 10 kolumn. PROG_025.LSP Realizacja pętli FOR w AutoLISPie. PROG_026.LSP Użycie instrukcji FOR przykład 1. PROG_027.LSP Użycie instrukcji FOR przykład 2. PROG_028.LSP Użycie instrukcji FOR przykład 3. Tworzenie listy oraz wyświetlanie jej zawartości. PROG_029.LSP Użycie instrukcji FOR przykład 4. Obliczenie i wypisanie kwadratów liczb całkowitych od 1 do 10. PROG_030.LSP Użycie zagnieżdżonych instrukcji FOR. Wypisanie liczb od 1 do 100 w 10 rzędach po 10 kolumn.

9/!Qumf!j!lpotusvldkf!tufsvk df 232 PROG_031.LSP Realizacja pętli DO_WHILE w AutoLISPie. PROG_032.LSP Użycie instrukcji DO_WHILE. Obliczenie i wypisanie kwadratów liczb całkowitych od 1 do 10. Często zdarza się, że, w zależności od sytuacji, program musi dokonać wyboru, jaka jego sekcja ma być wykonywana. W takim przypadku możemy zastosować instrukcję warunkową if. Instrukcja if możemieć 2formy: lub (if wyrażenie (instrukcja_1) )if (if wyrażenie (instrukcja_1) (instrukcja_2) )if else Wyrażenie to tutaj coś, comajakąś wartość. Może być to po prostu obiekt wybrany przez nas do przechowywania zmiennej logicznej, ale może tobyć też naprawdę wyrażenie, które najpierw trzeba obliczyć, by w rezultacie tego poznać jego wartość. Najpierw zatem oblicza się wartość wyrażenia. Jeśli nie jest ona równa nil (prawda), to wykonywana jest instrukcja_1. Jeśli wartość wyrażenia jest równa nil (fałsz), to instrukcja_1 nie jest wykonywana. W drugiej wersji instrukcji if widzimy za napisem instrukcja_2 słowo komentarza else, co można przetłumaczyć jako: w przeciwnym razie. A zatem jeśli w tej drugiej sytuacji wartość wyrażenia jest różna od nil (prawda), to zostanie wykonana instrukcja_1, w przeciwnym razie, czyli gdy wartość wyrażenia jest równa nil (fałsz), zostanie wykonana instrukcja_2. Otoprostyprzykład: **************************************************PROG_012 Przyklad instrukcji warunkowej IF. przejscie na ekran tekstowy (textscr)

233 BvupMJTQ!!qsbluzd{oz!lvst pobranie wartosci zmiennej x 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 **************************************************KONIEC Wykonanie powyższego programu możebyć następujące: Command: (load "prog_012") Podaj liczbe calkowita: 2 Zmienna x ma wartosc inna niz 10. Command: Jeżeli użytkownik wprowadzi liczbę 10, ekran będzie wyglądał następująco: Command: (load "prog_012") Podaj liczbe calkowita: 10 Zmienna x ma wartosc 10. Command: Omówmy teraz wyróżnione linie programu: Funkcja textscr przełącza ekran AutoCADa na stronę tekstową działanie analogiczne jak klawisza funkcyjnego F1. Funkcja ta może być pomocna przy prowadzeniu dłuższego dialogu z użytkownikiem, ponieważ standardowo ekran graficzny AutoCADa wyświetla tylko 3 ostatnie linie tekstowe. W tym miejscu zmiennej x przypisujemy wartość całkowitą. Funkcją odpowiedzialną za przypisanie do zmiennej x wartości całkowitej jest funkcja getint omówimy ją sobie dokładnie w punkcie Pobieranie informacji od użytkownika. To tutaj stosujemy instrukcję warunkową if, która sprawdza wartość wyrażenia (= x 10) Ponieważ w pierwszym powyższym przykładzie użytkownik wprowadził z klawiatury cyfrę 2, wyrażenie (= x 10) zwraca nil (fałsz) i funkcja if wykonuje instrukcję instrukcja_2 (warunek na else). Gdyby użytkownik podał liczbę 10, wówczas ewaluacja wyrażenia (= x 10) daje T (prawda) i wykonana zostaje instrukcja instrukcja_1.

9/!Qumf!j!lpotusvldkf!tufsvk df 234 9/2/2/!Jotusvldkf!qsptuf!j!{p kf!qsptuf!j!{p pof Wjęzyku AutoLISP rolę symbolu końcowego instrukcji gra lewy skrajny nawias zamykający. Tak więc zapisy: oraz oraz oraz x 3) x 3 )setq x 3 )setq ( ) setq x 3 wjęzyku AutoLISP mają to samo znaczenie. Dzięki temu można w tym języku pisać grupy instrukcji nie troszcząc się o to, czy zmieszczą się w jednym wierszu. Nie zezwala na to np. większość realizacji języka BASIC. Jakżeczęsto zdarza się, że po napisaniu wiersza 100 IF A > 5 OR B = 1 OR C < 0 (jakiś długi ciąg operacji, który nie mieści się w jednym wierszu) musisz napisać to od nowa jako podprogram, aby uniknąć kłopotów! Z drugiej strony, jeżeli koniec wiersza nie ma żadnego znaczenia, to skąd interpreter AutoLISPu będzie wiedział, które instrukcje należy wykonać w razie spełnienia warunku? Często bowiem zdarza się, że chodzi nam o wykonanie warunkowe nie jednej instrukcji, a całego bloku instrukcji. Stosujemy wówczas instrukcję złożoną zwaną inaczej blokiem. Są to po prostu zwykłe instrukcje podane jako argumenty funkcji progn. instrukcja_1 instrukcja_2... instrukcja_n )progn Przyjęto zasadę, że wszędzie tam, gdzie można napisać instrukcję prostą, równie dobrze wolno umieścić instrukcję złożoną.

235BvupMJTQ!!qsbluzd{oz!lvst Konstrukcja: (if (warunek) instrukcja pusta )progn else lista_instrukcji )progn )if jest równoważna konstrukcji: (if (not (warunek)) lista_instrukcji )progn )if Oto przykład programu, w którym stosujemy instrukcje złożone: **************************************************PROG_013 Przyklad instrukcji warunkowej IF z zastosowaniem instrukcji zlozonej. ---------------------------------------- pobranie zmiennej x x (getint "\npodaj liczbe calkowita: ") )setq sprawdzenie warunku na x (if (= x 10) (princ "Zmienna x ma wartosc 10.") (princ "\ntrafiles.") )progn else (princ "Zmienna x ma wartosc inna niz 10.") (princ "\nnie trafiles.") )progn )if **************************************************KONIEC Oto przykładowy wygląd ekranu po wykonaniu tego programu: Command: (load "prog_013") Podaj liczbe calkowita: 10 Zmienna x ma wartosc 10. Trafiles. Command:

9/!Qumf!j!lpotusvldkf!tufsvk df 236 Jeżeli na zadane pytanie odpowiemy inaczej, to ekran może wyglądać tak: Command: (load "prog_013") Podaj liczbe calkowita: 5 Zmienna x ma wartosc inna niz 10. Nie trafiles. Command: Omówmy teraz wyróżnione linie programu: Pobieramy z klawiatury liczbę całkowitą (wykorzystując funkcję getint), a następnie liczbę tę podstawiamy pod zmienną x. Sprawdzamy wartość wyrażenia (= x 10). Wynik T (prawda) lub nil (fałsz), przekazujemy jako argument funkcji if. Wykorzystując instrukcję grupującą progn, budujemy instrukcję złożoną, która ma zostać wykonana, gdy wyrażenie (= x 10) jest prawdziwe zwraca T. Wykorzystując instrukcję grupującą progn, budujemy instrukcję złożoną else, która ma zostać wykonana, gdy wyrażenie (= x 10) jest fałszywe zwraca nil. Przypominam, że zróżnicowane odstępy od lewego marginesu (wypełnione białymi znakami), nie mają dla interpretera AutoLISPu żadnego znaczenia. Pomagają natomiast programiście. Dzięki nim program staje się bardziej czytelny. 9/2/3/![bhojf e pof!jot bhojf e pof!jotusvldkf!jg Po warunku if lub else może wystąpić dowolny typ instrukcji. Może tobyć instrukcja, która wprowadza lub wyprowadza dane, wykonuje działania matematyczne lub wywołuje funkcję użytkownika. Może tobyć także kolejna instrukcja if. O instrukcji if, która zawiera się wewnątrz innej instrukcji if, mówimy, że jest zagnieżdżona. Przykładowo, w poniższym kodzie druga instrukcja if jest zagnieżdżona w pierwszej: (if (> x 1) (if (< y 10) k1 1.25) )if )if Drugi warunek if testuje się tylko wówczas, gdy prawdziwy jest warunek pierwszy, tak więc zmiennej k1 jest przypisywana wartość 1.25 tylko wtedy, kiedy obydwa warunki są prawdziwe. To samo można zapisać następująco: (if (and (> x 1)(< y 10)) k1 1.25) )if Obydwa zapisy powodują wykonanie tego samego zadania, ale w drugim przykładzie, dzięki użyciu operatora logicznego and, zapis jest jaśniejszy. Nie trzeba rozszyfro-

237 BvupMJTQ!!qsbluzd{oz!lvst wywać, co wykonuje każda instrukcja if wystarczy odczytać instrukcję, byją zrozumieć Jeśli x jest większe niż 1iy jest mniejsze niż 10, to k1 wynosi 1.25. Generalnie, dwie następujące po sobie zagnieżdżone instrukcje if można zastąpić jedną z operatorem and. Z reguły mądrze jest ich unikać, ponieważ mogą nas doprowadzić do niejasnych sytuacji i trudnych do odczytania kodów. Poniżej przedstawiam przykład eksponujący zastosowanie zagnieżdżonej instrukcji warunkowej if. Tym razem jest to temat szkolny i jednocześnie klasyczny w wielu podręcznikach programowania, a mianowicie obliczenie pierwiastków równania kwadratowego o postaci: ax 2 + bx + c = 0 Najpierw należy obliczyć tzw. deltę: delta = b 2-4ac a potem, w zależności od wartości delty, trzeba podjąć jedną z trzech akcji: 1. delta < 0 wypisanie komunikatu o braku pierwiastków rzeczywistych 2. delta = 0 zastosowanie odpowiedniego wzoru w celu uzyskania wartości pierwiastka podwójnego, a następnie, po opatrzeniu odpowiednim komunikatem, wyprowadzenie jej na ekran 3. delta > 0 zastosowanie odpowiednich wzorów do uzyskania wartości dwóch różnych pierwiastków rzeczywistych i podanie ich w odpowiedniej postaci Program realizujący powyższe zadania możemy zrealizować wykorzystując zagnieżdżone instrukcje warunkowe if else. Oto program obliczający 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)) a (getreal "Podaj wartosc wspolczynnika a: ")) (initget 1) b (getreal "Podaj wartosc wspolczynnika b: ")) (initget 1) c (getreal "Podaj wartosc wspolczynnika c: ")) (terpri)

9/!Qumf!j!lpotusvldkf!tufsvk df 238 obliczenie delty delta (- (* b b)(* 4.0 a c)) )setq obliczenie pierwiastkow rownania (if (< delta 0) brak pierwiastkow rzeczywistych (princ "\ndla wspolczynnikow " (rtos a 2 4) ", " (rtos b 2 4) ", " (rtos c 2 4) "\nwielomian kwadratowy nie ma " "rozwiazan rzeczywistych." )strcat )princ )progn else - w tym miejscu dopuszczamy 2 sytuacje: delta = 0 i delta > 0 (if (= delta 0) podwojny pierwiastek rzeczywisty x1 (/ (- b)(* 2.0 a)) )setq (princ "\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 else - ostatnia, trzecia mozliwosc delta > 0-2 rozne pierwiastki rzeczywiste x1 (/ (- (- b)(sqrt delta))(* 2.0 a)) x2 (/ (+ (- b)(sqrt delta))(* 2.0 a)) )setq

239 BvupMJTQ!!qsbluzd{oz!lvst (princ "\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) **************************************************KONIEC Aotomożliwe przypadki wykonania programu: Przypadek 1 brak pierwiastków rzeczywistych Command: (load "prog_014") Obliczenie pierwiastkow rownania kwadratowego. Podaj wartosc wspolczynnika a: 1 Podaj wartosc wspolczynnika b: 1 Podaj wartosc wspolczynnika c: 1 Dla wspolczynnikow 1.0000, 1.0000, 1.0000 wielomian kwadratowy nie ma rozwiazan rzeczywistych. Command: Przypadek 2 podwójny pierwiastek rzeczywisty Command: (load "prog_014") Obliczenie pierwiastkow rownania kwadratowego. Podaj wartosc wspolczynnika a: 1 Podaj wartosc wspolczynnika b: -2 Podaj wartosc wspolczynnika c: 1 Dla wspolczynnikow 1.0000, -2.0000, 1.0000 wielomian kwadratowy ma podwojny pierwiastek rzeczywisty x1 = 1.0000 Command:

9/!Qumf!j!lpotusvldkf!tufsvk df 23: Przypadek 3 dwa różne pierwiastki rzeczywiste Command: (load "prog_014") Obliczenie pierwiastkow rownania kwadratowego. Podaj wartosc wspolczynnika a: 2 Podaj wartosc wspolczynnika b: -3 Podaj wartosc wspolczynnika c: 1 Dla wspolczynnikow 2.0000, -3.0000, 1.0000 wielomian kwadratowy ma 2 rozne pierwiastki rzeczywiste x1 = 0.5000 x2 = 1.0000 Command: Omówmy teraz wyróżnione linie programu: Funkcja textpage powoduje wyświetlenie ekranu tekstowego AutoCADa z jednoczesnym wyczyszczeniem jego zawartości. Funkcja initget ustala różne opcje, które mogą być użyte przez następującą po initget funkcję getxxx tutaj odnosi się to do wartości współczynnika a. W konkretnym przypadku bity kontrolne oznaczają: 1 nie pozwala na tzw. pusty ENTER 2 nie pozwala na wprowadzenie wartości zerowej unikniemy w ten sposób sprowadzenia równania kwadratowego do postaci liniowej bx + c = 0 Dokładniej o funkcji initget powiemy sobie w punkcie Pobieranie informacji od użytkownika. W liniach tych robimy założenia odnośnie wartości współczynników b i c. Mogą być one dowolne, za wyjątkiem pustego ENTER. Instrukcja grupująca progn określa nam instrukcje, które zostaną wykonane w przypadku, gdy delta będzie mniejsza od zera równanie nie posiada pierwiastków rzeczywistych. Funkcja strcat zwraca łańcuch będący złożeniem (konkatenacją) wszystkich swoich argumentów typu string. Otrzymany łańcuch podawany jest jako argument funkcji princ,którawyświetla go na ekranie tekstowym. Dokładniej o funkcji strcat powiemy sobie w punkcie Działania na łańcuchach. Jak już wspomniałem wcześniej, argumenty funkcji stcat muszą być łańcuchami (typ string). Ponieważ pierwiastki równania kwadratowego są zmiennymi typu rzeczywistego, należy wpierw poddać je konwersji na typ łańcuchowy. Kowersja ta przeprowadzana jest za pomocą funkcji rtos. W naszym konkretnym przypadku funkcja rtos zwraca łańcuch obrazujący format dziesiętny zmiennej z czterema cyframi po przecinku. Ten blok instrukcji ma zostać wykonany, gdy delta jest równa lub większa od zera.

241 BvupMJTQ!!qsbluzd{oz!lvst Tutaj dokonujemy kolejnego uściślenia warunku na deltę. Ten blok instrukcji ma zostać wykonany, gdy delta jest równa zero. W linii tej następuje zgrupowanie instrukcji w blok, który ma zostać wykonany, gdy delta jest większa od zera. Ponieważ zastosowanie zagnieżdżonych instrukcji warunkowych if prowadzi do otrzymania zawiłego kodu, poniższy przykład pokazuje sposób obejścia 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)) a (getreal "Podaj wartosc wspolczynnika a: ")) (initget 1) b (getreal "Podaj wartosc wspolczynnika b: ")) (initget 1) c (getreal "Podaj wartosc wspolczynnika c: ")) (terpri) obliczenie delty delta (- (* b b)(* 4.0 a c)) )setq obliczenie pierwiastkow rownania (if (< delta 0) brak pierwiastkow rzeczywistych (princ "\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!tufsvk df 242 (if (= delta 0) podwojny pierwiastek rzeczywisty x1 (/ (- b)(* 2.0 a)) )setq (princ "\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 x1 (/ (- (- b)(sqrt delta))(* 2.0 a)) x2 (/ (+ (- b)(sqrt delta))(* 2.0 a)) )setq (princ "\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) **************************************************KONIEC

243 BvupMJTQ!!qsbluzd{oz!lvst Wykonanie powyższego programu jest dla użytkownika identyczne jak programu PROG_014.LSP różnice widoczne są tylko z punktu widzenia programisty. Jak widać w powyższym kodzie, wykorzystując obliczoną wcześniej deltę, do obliczenia pierwiastków równania wykorzystano trzy proste instrukcje warunkowe if (bez realizacji warunku typu else): (if (< delta 0)... )progn )if (if (= delta 0)... )progn )if (if (> delta 0)... )progn )if Sam program stał się przez to bardziej przejrzysty i zrozumiały. Instrukcja while ma postać: (while wyrażenie instrukcja_1 )while wyrażenie Najpierw oblicza się wartość wyrażenia. Jeśli wynik jest równy nil (fałsz), wówczas instrukcja_1 nie jest wcale wykonywana. Jeśli jednak wartość wyrażenia jest różna od nil (prawda), wówczas wykonywana jest instrukcja_1, po czym ponownie obliczana jest wartość wyrażenia. Jeśli nadal wartość tego wyrażenia jest różna od nil, wówczas ponownie wykonywana jest instrukcja_1 i tak dalej, dopóki (while!) wyrażenie ma wartość różną od nil. Jeśli w końcu kiedyś obliczone wyrażenie będzie równe nil, wówczas dopiero pętla zostanie przerwana. Obliczenie wartości wyrażenia odbywa się przed wykonaniem instrukcji instrukcja_1. Instrukcja_1 może być instrukcją prostą lub złożoną.

9/!Qumf!j!lpotusvldkf!tufsvk df 244 Qs{zlbe!2 Należy zawsze pamiętać o umieszczeniu warunku wyjścia z pętli. Jeśli jednak zdarzy Ci się uruchomić nieskończoną pętlę, możesz ją bardzo prosto przerwać naciskając kombinację klawiszy Ctrl-C. A tak na marginesie kombinacja klawiszy Ctrl-C przerywa dowolną komendę AutoCADa lub funkcję AutoLISPu. Zastosowanie pętli while omówimy sobie na poniższych przykładach. W przykładzie tym, będąc wpętli while, pobieramy coraz to nowe wartości zmiennej x. Warunkiem opuszczenia pętli while jest nadanie zmiennej x wartości zero. *************************************************PROG_016 Wykorzystanie instrukcji WHILE - wersja 1. --------------------------------------- (textpage) przejscie na ekran tekstowy nadanie zmiennej x wartosci nil x nil) wejscie w petle while (while (/= x 0) pobranie nowej wartosci zmiennej x x (getint "Podaj nowa wartosc zmiennej x [0 - koniec]: " )getint )setq )progn )while --------------------------------------- *************************************************KONIEC A oto przykładowy wygląd ekranu po wykonaniu programu: Command: (load "prog_016") Podaj nowa wartosc zmiennej x [0 - koniec]: 1 Podaj nowa wartosc zmiennej x [0 - koniec]: -10 Podaj nowa wartosc zmiennej x [0 - koniec]: 0 Command: Omówmy teraz wyróżnione linie programu:

245BvupMJTQ!!qsbluzd{oz!lvst Qs{zlbe!3 Wchodzimy w pętlę while i rozpoczynamy pobieranie wartości zmiennej x. Wyrażeniem, powodującym dopuszczenie do wejścia w pętlę jest (/= x 0). Wyrażenie to jest prawdziwe (zwraca T), gdyż wcześniej zmiennej x została nadana wartość nil. Pobieramy nową wartość zmiennej x, po czym wracamy na początek pętli while, by ponownie porównać warunek (/= x 0). Jeśli warunek jest prawdziwy, pobieramy następną wartość zmiennej x i znowu skaczemy na początek pętli. Jeśli warunek jest fałszywy, omijamy pętlę while i wykonujemy dalszy ciąg instrukcji w tym przypadku jest to tylko instrukcja, powodująca niezauważalne zakończenie wykonywania programu. Program ten stanowi modyfikację programu PROG_016. Ukazuje on inny sposób kontroli wyrażenia, powodującego wyjściezpętli while. *************************************************PROG_017 Wykorzystanie instrukcji WHILE - wersja 2. --------------------------------------- (textpage) przejscie na ekran tekstowy nadanie zmiennej jeszcze wartosci T jeszcze T) wejscie w petle while (while jeszcze pobranie nowej wartosci zmiennej x x (getint "Podaj nowa wartosc zmiennej x [0 - koniec]: " )getint )setq zbadanie wartosci zmiennej x (if (= x 0) jeszcze nil) )progn )if )progn )while jeszcze --------------------------------------- *************************************************KONIEC

Qs{zlbe!4 9/!Qumf!j!lpotusvldkf!tufsvk df 246 Wykonanie programu jest identyczne jak dla programu PROG_016 różnice są widoczne jedynie dla programisty. Omówmy teraz wyróżnione linie programu: Inicjalizujemy zmienną jeszcze i nadajemy jej wartość T (prawda). Zmienna ta będzie sterować pętlą while. Ponieważ wcześniej zmiennej jeszcze nadano wartość T, wchodzimy w pętlę while. Pobieramy nową wartość zmiennej x. Sprawdzamy, czy zmienna x jest równa zero. Jeżeli zmienna x jest równa zero, ustawiamy wartość zmiennej jeszcze na nil, umożliwiając tym samym opuszczenie pętli while. W przykładzie tym, wykorzystujemy instrukcję while do obliczenia i wypisania na ekranie tekstowym kwadratów liczb całkowitych od 1 do 10. *************************************************PROG_018 Wykorzystanie instrukcji WHILE. Program do obliczania kwadratow liczb calkowitych od 1 do 10. --------------------------------------- (textpage) przejscie na ekran tekstowy liczba 1) (princ "\nkwadraty liczb calkowitych od 1 do 10.\n") (princ "\nliczba Kwadrat liczby\n") (while (< liczba 11) kwadrat (* liczba liczba)) (princ " " (rtos liczba 2 0) " " (rtos kwadrat 2 0) )strcat )princ (terpri) liczba (1+ liczba)) )progn )while --------------------------------------- *************************************************KONIEC

247 BvupMJTQ!!qsbluzd{oz!lvst Po wykonaniu programu ekran tekstowy będzie wyglądał następująco: Command: (load "prog_018") Kwadraty liczb calkowitych od 1 do 10. Liczba Kwadrat liczby 1 1 2 4 3 9 4 16 5 25 6 36 7 49 8 64 9 81 10 100 Command: Omówmy teraz wyróżnione linie programu: Ustawiamy wartość zmiennej liczba na 1. Tutaj rozpoczyna się pętla, która zostanie wykonana, ponieważ wartość zmiennej liczba jest mniejsza niż 11. Gdyby liczba już na początku była równa 11, wówczas pętla nie wykonałaby się ani razu. Obliczany kwadrat danej liczby. Wynik podstawiany jest pod zmienną kwadrat. Używając funkcji princ, strcat oraz rtos, wypisujemy w jednym wierszu daną liczbę oraz jej kwadrat. To tutaj następuje przejście do nowej linii. Zwiększamy wartość zmiennej liczba o 1. Gdybyśmy o tym zapomnieli, wówczas jedynym sposobem na opuszczenie pętli while byłoby przerwanie wykonywania programu poprzez naciśnięcie kombinacji klawiszy Ctrl-C. 9/3/2/![bhojf e pof!jotusv f e pof!jotusvldkf!xij ldkf!xijmf Aby zapewnić sobie dwa poziomy powtarzania, możemy zagnieździć pętle while. Można na przykład zastosować zewnętrzną pętlę w celu powtarzania całego programu, dopóki użytkownik nie zadecyduje inaczej, oraz wewnętrzną do sprawdzania poprawności danych wejściowych. Poniższy program pokazuje wykorzystanie zagnieżdżonych pętli while do wypisania na ekranie tekstowym liczb od 1 do 100 w 10 rzędach 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!tufsvk df 248 (textpage) (princ "\nwykorzystanie zagniezdzonych instrukcji WHILE.") (princ "\nwypisanie liczb od 1 do 100 " "w 10 rzedach po 10 kolumn." )strcat )princ (princ "\n\n") rzad 1) (while (< rzad 11) kolumna 1 liczba 1 )setq (while (< kolumna 11) (princ (+ liczba (* 10 (- rzad 1)))) (princ " ") kolumna (1+ kolumna) liczba (1+ liczba) )setq )progn )while kolumna (princ "\n") rzad (1+ rzad)) )progn )while rzad --------------------------------------- *************************************************KONIEC Wykonanie programu będzie następujące: Command: (load "prog_019") Wykorzystanie zagniezdzonych instrukcji WHILE. Wypisanie liczb od 1 do 100 w 10 rzedach po 10 kolumn. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

249 BvupMJTQ!!qsbluzd{oz!lvst 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 Command: Omówmy teraz wyróżnione linie programu. Ustawiamy wartość początkową zmiennej rzad. Wchodzimy w zewnętrzną pętlę while. Pętlę tę wykonujemy tak długo, dopóki zmienna rzad jest mniejsza od 11. Ustawiamy wartości początkowe zmiennych kolumna i liczba dla kolejnego rzędu liczb. Wchodzimy w wewnętrzną pętlę while. Pętlę tę wykonujemy tak długo, dopóki zmienna kolumna jest mniejsza od 11. Obliczamy aktualną wartość liczby, po czym wypisujemy ją używając instrukcji princ. Oddzielamy od siebie dwoma spacjami poszczególne liczby w rzędzie. Zwiększamy o 1 wartości zmiennych kolumna i liczba, zapewniając tymsamym dalszy prawidłowy przebieg pętli wewnętrznej. Będąc już poza pętlą wewnętrzną przechodzimy do nowego wiersza, umożliwiając tym samym prawidłowe wypisanie kolejnego rzędu liczb. Zwiększamyo1wartość zmiennej rzad, zapewniając tym samym dalszy prawidłowy przebieg pętli zewnętrznej. W pewnych okolicznościach trzeba w zależności od wyniku jakiegoś testu, wybrać jedną z wielu dróg. Konstrukcja if... else daje do wyboru tylko dwie możliwości dalszego postępowania, chociaż pozwala też stosować rodzaj zagnieżdżania jednych konstrukcji w innych, na przykład: if (warunek_1) czynnosc_1 else if (warunek_2) czynnosc_2 else

9/!Qumf!j!lpotusvldkf!tufsvk df 24: if (warunek_3) czynnosc_3 itd. Jest to jednak zdecydowanie nieznośny sposób rozwiązania tego problemu. W języku AutoLISP istnieje mechanizm, zwany instrukcją cond (zwrotnica), który pozwala wybrać jeden spośród wielu skoków. Format instrukcji cond jest następujący: (cond (test_1 result_1)... (test_n result_n)) Argumentami funkcji może być dowolna liczba list. Funkcja testuje wyrażenia test, wyznaczając wartość pierwszych elementów każdej kolejnej listy podrzędnej (w podanym porządku), aż do momentu, gdy wartość któregoś z nich okaże się różna od nil. Następnie wartościowane jest to wyrażenie result, które występuje po pozytywnie przetestowanym wyrażeniu test i zwracana jest wartość ostatniego wyrażenia listy podrzędnej. Zwykle jako ostatnie wyrażenie test używa się T (jest ono uwzględniane w przypadku braku pozytywnego wyniku testowania wszystkich poprzednich). Typowym przykładem zastosowania tej instrukcji może być program zarządzania danymi, którego działaniem steruje się za pośrednictwem menu. Użytkownik programu otrzymuje następujące menu: Mozliwe opcje programu: 1. Utworz nowy plik. 2. Dolacz jeden element do pliku. 3. Usun jeden element z pliku. 4. Wypisz jeden element z pliku. 5. Przeszukaj plik. 6. Zakoncz prace. Wybierz opcje [1-6]: Jest sześć funkcji przeznaczonych do wykonywania tych zadań oraz funkcja o nazwie MENU, zarządzająca pozostałymi funkcjami. A oto i program realizujący powyższe zadania: *************************************************PROG_020 Przyklad uzycia instrukcji COND - wersja 1. ================================================= definicje poszczegolnych funkcji programu --------------------------------------- (defun NOWY_PLIK () (princ "\nwybrales opcje NOWY PLIK.")

251 BvupMJTQ!!qsbluzd{oz!lvst cialo_funkcji )progn )NOWY_PLIK --------------------------------------- (defun DOPISZ_ELEMENT () (princ "\nwybrales opcje DOPISZ ELEMENT.") cialo_funkcji )progn )DOPISZ_ELEMENT --------------------------------------- (defun USUN_ELEMENT () (princ "\nwybrales opcje USUN ELEMENT.") cialo_funkcji )progn )USUN_ELEMENT --------------------------------------- (defun WYPISZ_ELEMENT () (princ "\nwybrales opcje WYPISZ ELEMENT.") cialo_funkcji )progn )WYPISZ_ELEMENT --------------------------------------- (defun SZUKAJ ()

9/!Qumf!j!lpotusvldkf!tufsvk df 252 (princ "\nwybrales opcje SZUKAJ.") cialo_funkcji )progn )SZUKAJ --------------------------------------- (defun ZAKONCZ_PRACE () (princ "\nwybrales opcje ZAKONCZ PRACE.") cialo_funkcji jeszcze nil) )progn )ZAKONCZ PRACE --------------------------------------- Funkcja glowna (defun MENU () jeszcze T) (while jeszcze (textpage) wypisanie zawartosci menu (princ "\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 opcja (getint

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 )progn )MENU --------------------------------------- koniec definicji funkcji ================================================= wywolanie funkcji MENU (MENU) ================================================= *************************************************KONIEC Wykonanie powyższego programu możebyć następujące: Command: (load "prog_020") Mozliwe opcje programu: 1. Utworz nowy plik. 2. Dolacz jeden element do pliku. 3. Usun jeden element z pliku. 4. Wypisz jeden element z pliku. 5. Przeszukaj plik. 6. Zakoncz prace. Wybierz opcje [1-6]: 3 Wybrales opcje USUN ELEMENT

9/!Qumf!j!lpotusvldkf!tufsvk df 254 Nacisnij ENTER... Mozliwe opcje programu: 1. Utworz nowy plik. 2. Dolacz jeden element do pliku. 3. Usun jeden element z pliku. 4. Wypisz jeden element z pliku. 5. Przeszukaj plik. 6. Zakoncz prace. Wybierz opcje [1-6]: 7 Niepoprawny przypadek. Nacisnij ENTER... Mozliwe opcje programu: 1. Utworz nowy plik. 2. Dolacz jeden element do pliku. 3. Usun jeden element z pliku. 4. Wypisz jeden element z pliku. 5. Przeszukaj plik. 6. Zakoncz prace. Wybierz opcje [1-6]: 6 Wybrales opcje ZAKONCZ PRACE Nacisnij ENTER... Command: Omówmy teraz wyróżnione linie programu: Używając funkcji defun, definiujemy poszczególne funkcje naszego programu. Funkcje te są to tylko funkcje prototypowe nie robią nic poza wypisaniem nazwy wybranej komendy (za wyjątkiem funkcji ZAKONCZ_PRACE). W linii tej, będącej instrukcją funkcji ZAKONCZ_PRACE, poprzez nadanie zmiennej jeszcze wartości nil, opuszczamy pętlę while. Definiujemy naszą funkcję główną MENU. Nadajemy zmiennej jeszcze wartość T (prawda), umożliwiając tym samym wejście w pętlę while. Wchodzimy w pętlę while. Używając funkcji princ oraz strcat, wypisujemy menu użytkownika. W linii tej, liczba całkowita, będąca odpowiedzią (wyborem) użytkownika, zostaje podstawiona pod zmienną opcja. To tutaj wykorzystujemy instrukcję cond, aby dokonać wyboru wielowariantowego. Jeśli zmienna opcja =1,tobędzie wywołana funkcja NOWY_PLIK, jeśli zaś zmienna opcja = 2, to zostanie wywołana funkcja DOPISZ_ELEMENT itd.

255 BvupMJTQ!!qsbluzd{oz!lvst W linii tej, widzimy, jak w instrukcji cond zastosować opcję domyślną. Jeżeli wartość zmiennej opcja będzie mniejsza niż 1lubwiększa niż 6, to instrukcja cond wybierze instrukcje występujące po stałej predefiniowanej T wypisze komunikat "Niepoprawny przypadek.", po czym zostanie ponowiony wybór opcji z menu. Wywołujemy wcześniej zdefiniowaną funkcję MENU. Postępowanie takie automatycznie wywołuje funkcję MENU zaraz po pomyślnym załadowaniu programu do interpretera AutoLISPu. Należy zwrócić szczególną uwagę na odpowiednią liczbę nawiasów, oddzielających od siebie poszczególne warunki. Na przykład zapis: (cond ((= x1 1) lista_instrukcji ) ((and (= x1 2)(/= x3 0)) lista_instrukcji ) )cond jest poprawny, podczas gdy zapis: (cond (= x1 1) lista_instrukcji ) (and (= x1 2)(/= x3 0)) lista_instrukcji ) )cond jest zapisem błędnym. W takim przypadku interpreter powinien zasygnalizować błąd zamknięcia nawiasów. Jeżeli jednak pomylisz się również w liczbie nawiasów w lista_ instrukcji tak, że ich liczba będzie zgodna, mogą powstać błędy trudne do zlokalizowania. Aby uniknąć takiego przypadku, możesz stosować następującą konstrukcję: (cond (przypadek 1 (= x1 1) lista_instrukcji_1 )progn )koniec przypadku 1 (rzypadek 2 (and (= x1 2)(/= x3 0)) lista_instrukcji_2 )progn

9/!Qumf!j!lpotusvldkf!tufsvk df 256 )koniec przypadku 2... (przypadek n (warunek_n) lista_instrukcji_n )progn )koniec przypadku n )cond Zapis taki jest przejrzysty i czytelny, można również łatwo zlokalizować odpowiadającą sobie parę nawiasów. Wróćmy jednak do naszego programu. Funkcja główna MENU wywoływana była z pętli while. Po wyborze i wykonaniu funkcji z menu 1 5, następowało ponowne wywołanie funkcji MENU. Co jednak zrobić, jeśli chcemy, aby funkcja MENU była wywoływana jednokrotnie (tzn. wykonywała jedną z funkcji podrzędnych, po czym opuszczała pętlę while)? Odpowiedź jest bardzo prosta. Wystarczy do każdej funkcji pomocniczej dopisać na końcu instrukcję ustalającą wartość zmiennej jeszcze na nil. Program PROG_021, znajdujący się na dołączonej dyskietce, zawiera odpowiednie zmiany, pozwalające na działanie w wyżej wymieniony sposób. Ostatnim przykładem użycia instrukcji cond będzie program obliczający pierwiastki równania 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)) a (getreal "Podaj wartosc wspolczynnika a: ")) (initget 1) b (getreal "Podaj wartosc wspolczynnika b: ")) (initget 1) c (getreal "Podaj wartosc wspolczynnika c: ")) (terpri) obliczenie delty

257 BvupMJTQ!!qsbluzd{oz!lvst delta (- (* b b)(* 4.0 a c)) )setq obliczenie pierwiastkow rownania (cond ((< delta 0) brak pierwiastkow rzeczywistych (princ "\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 x1 (/ (- b)(* 2.0 a)) )setq (princ "\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 x1 (/ (- (- b)(sqrt delta))(* 2.0 a)) x2 (/ (+ (- b)(sqrt delta))(* 2.0 a)) )setq (princ

9/!Qumf!j!lpotusvldkf!tufsvk df 258 "\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) **************************************************KONIEC Wykonanie powyższego programu jest identyczne, jak w programach PROG_014 i PROG_015, gdzie używaliśmy instrukcji warunkowej if. Omówmy teraz wyróżnione linie programu: Wchodzimy w instrukcję cond i rozpoczynamy sprawdzanie wartości zmiennej delta. Ten fragment programu wykonywany jest wówczas, gdy zmienna delta jest mniejsza od zera. Ten fragment programu wykonywany jest wówczas, gdy zmienna delta jest równa zero. Ten fragment programu wykonywany jest wówczas, gdy zmienna delta jest większa od zera. Pętla repeat posiada następujący format: (repeat number expr_1... expr_n) W funkcji tej argument number jest dowolną dodatnią liczbą typu integer. Funkcja dokonuje wartościowania każdego argumentu expr tyle razy, ile określa argument number i zwraca wartość ostatniego z nich.

259 BvupMJTQ!!qsbluzd{oz!lvst Funkcja ta jest podobna do być może znanej Ci z innych języków programowania funkcji for. Jej działanie prześledzimy na poniższym przykładzie. Będzie to modyfikacja programu PROG_018, który oblicza i wypisuje kwadraty liczb całkowitych od 1 do 10. W programie PROG_018, została do tego celu użyta funkcja while. W poniższym programie pokażę Ci, jak rozwiązać to zadanie przy pomocy pętli 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 liczba 1) (princ "\nkwadraty liczb calkowitych od 1 do 10.\n") (princ "\nliczba Kwadrat liczby\n") (repeat 10 zmiana w stosunku do PROG11 kwadrat (* liczba liczba)) (princ " " (rtos liczba 2 0) " " (rtos kwadrat 2 0) )strcat )princ (terpri) liczba (1+ liczba)) )progn )repeat --------------------------------------- *************************************************KONIEC Po wykonaniu programu ekran będzie wyglądał identycznie, jak w programie PROG_018. Omówmy teraz wyróżnione linie programu: Instrukcja (while (< liczba 11)...) została zastąpiona instrukcją (repeat 10...). Jest to jedyna zmiana dokonana w stosunku do programu PROG_018. Zastosowanie instrukcji while czy instrukcji repeat zależy od tego, co chcemy uzyskać. Instrukcję repeat stosujemy wówczas, gdy znamy liczbę powtórzeń pętli. Instrukcję while możemy stosować zarówno wtedy, gdy znamy liczbę powtórzeń pętli, jak również wtedy, gdy liczba powtórzeń nie jest znana, a zakończenie pętli zależne jest od spełnienia danego warunku.

9/!Qumf!j!lpotusvldkf!tufsvk df 25: 9/5/2/![bhojf e pof!jotu hojf e pof!jotusvldkf!sf svldkf!sfqfbu Zagnieżdżanie instrukcji repeat jest identyczne jak instrukcji while, co zobrazowano na poniższym przykładzie. *************************************************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 "\nwypisanie liczb od 1 do 100 " "w 10 rzedach po 10 kolumn." )strcat )princ (princ "\n\n") rzad 1) (repeat 10 kolumna 1 liczba 1 )setq (repeat 10 (princ (+ liczba (* 10 (- rzad 1)))) (princ " ") kolumna (1+ kolumna) liczba (1+ liczba) )setq )progn )repeat (princ "\n") rzad (1+ rzad)) )progn )repeat --------------------------------------- *************************************************KONIEC

261 BvupMJTQ!!qsbluzd{oz!lvst Po wykonaniu programu ekran będzie wyglądał identycznie, jak w programie PROG_019. Omówmy teraz wyróżnione linie programu, które obrazują zmiany w stosunku do kodu z programu PROG_019: Instrukcja (while (< rzad 11)...), będąca pętlą zewnętrzną, została zastąpiona instrukcją (repeat 10...) liczba powtórzeń pętli wynosi 10. Instrukcja (while (< kolumna 11)...), będąca pętlą wewnętrzną, została zastąpiona instrukcją (repeat 10...) liczba powtórzeń pętli wynosi 10. Jeśli programowałeś już w jakimś innym języku, jedną z pierwszych poznanych instrukcji była zapewne pętla for. Ma ona następującą formę (przykład z języka C): for (instr_ini wyraz_warun instr_krok) tresc_petli co w przykładzie może wyglądać choćby tak: for (i=0 i<10 i=i+1) { printf ("\njestem w petli for.") } Wyjaśnijmy sobie teraz, co oznaczają poszczególne człony: for (ang. dla...) oznacza: dla takich warunków rób... instr_ini jest to instrukcja wykonywana zanim pętla zostanie po raz pierwszy uruchomiona. W naszym przykładzie jest to podstawienie i=0. wyraz_warun jesttowyrażenie, które obliczane jest przed każdym obiegiem pętli. Jeśli jest ono różne od zera, to wykonywane zostają instrukcje będące treścią pętli. U nas wyrażeniem warunkowym jest wyrażenie i<10. Jeśli rzeczywiście i jest mniejsze od 10, wówczas wykonana zostaje instrukcja będąca treścią pętli, czyli wypisanie tekstu "\njestem w pętli for." instr_krok to instrukcja wykonywana na zakończenie każdego obiegu pętli. Jest to jakby ostatnia instrukcja, wykonywana bezpośrednio przed obliczeniem wyrażenia wyraz_warun. Unasjesttopoprostui=i+1. Praca tej pętli odbywa się więc jakby według takiego harmonogramu: 1. Najpierw wykonują się instrukcje inicjalizujące pracę pętli.

9/!Qumf!j!lpotusvldkf!tufsvk df 262 2. Obliczane jest wyrażenie warunkowe. Jeśli jest równe 0 praca pętli jest przerywana. 3. Jeśli powyżej okazało się, że wyrażenie było różne od zera, wówczas wykonywane zostają instrukcje będące treścią pętli. 4. Po wykonaniu treści pętli wykonana zostaje instrukcja inst_krok, po czym powtarzana jest akcja 2). Pora teraz na wyjaśnienie, dlaczego w celu omówienia pętli for posłużyłem się przykładem z języka C. Otóż w standardowych funkcjach języka AutoLISP nie ma definicji pętli for!!! Jest wprawdzie instrukcja repeat, lecz nie jest to jeszcze pętla for w całej okazałości. Powyższy problem da się jednak obejść. Język AutoLISP oferuje nam konstrukcję tzw. listy-funkcji. Ponieważ funkcja jest listą, więc po prostu zbudujmy ją jak listę, anastępnie wykonajmy jako funkcję. Pisanie programów wykorzystujących takie sztuczki jest możliwe tylko w LISPie. Inne języki nie pozwalają na traktowanie obiektu raz jako danej (lista), a raz jako części programu (funkcja). Temat listy-funkcji zostanie omówiony dokładnie podczas omawiania funkcji, teraz więc zostanie zaprezentowana definicja pętli FOR, której autorami są Panowie: Maciej Horczyczak i Jacek Skierski książka AutoLISP dla użytkowników 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 ' (print i) (print (+ i 1)) )progn )for i --------------------------------------- (defun FOR ( zmster ip ik ki zakres / fun w ) (if (> ki 0) w (eval '<=)) w (eval '>=)) )if fun (list (list '/ ) zakres)) (set zmster ip) (while (w (eval zmster) ik) (FUN)

263 BvupMJTQ!!qsbluzd{oz!lvst Qs{zlbe!2 (set zmster (+ ki (eval zmster))) )while fun nil) )progn )FOR *************************************************KONIEC O definicji pętli FOR powiemy sobie podczas omawiania definiowania własnych funkcji, teraz tylko podam kilka przykładów jej wykorzystania. W przykładzie tym, po pobraniu wartości początkowej, końcowej oraz kroku pętli, wypisujemy na ekran wybrane liczby. *************************************************PROG_026 Wykorzystanie petli FOR - przyklad 1. --------------------------------------- odszukanie i zaladowanie pliku PROG_025.LSP plik (findfile "prog_025.lsp")) (if plik plik zostal znaleziony (load plik) )progn else - nia znaleziono pliku (alert "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)) x1 (getint "\npodaj wartosc poczatkowa petli: ")) (initget (+ 1 2 4)) x2 (getint "\npodaj wartosc koncowa petli: "))

9/!Qumf!j!lpotusvldkf!tufsvk df 264 (initget (+ 1 2 4)) x3 (getint "\npodaj krok petli: ")) (princ "\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 ' (princ i) (terpri) przejscie do nowej linii )progn )for i --------------------------------------- *************************************************KONIEC Wykonanie programu możebyć następujące: Command: (load "prog_026") Przyklad wykorzystania petli for. Podaj wartosc poczatkowa petli: 1 Podaj wartosc koncowa petli: 10 Podaj krok petli: 2 Wypisywanie od 1 do 10 z krokiem = 2. 1 3 5 7 9 Command: Omówmy teraz wyróżnione linie programu: Wykorzystując standardową funkcję AutoLISPu findfile, poszukujemy pliku z definicją pętli FOR. Format funkcji findfile jest następujący: (findfile filename)

265BvupMJTQ!!qsbluzd{oz!lvst Funkcja ta poszukuje określonego pliku (w naszym przypadku jest to plik PROG_025.LSP) w bibliotecznej ścieżce poszukiwań AutoCADa. Jeśli podany plik zostanie znaleziony, funkcja zwraca pełną nazwę pliku wraz ze ścieżką dostępu, w przeciwnym wypadku funkcja zwraca nil. Wartość zwracana przez funkcję findfile jest następnie podstawiana pod zmienną plik. Jeśli plik PROG_025.LSP został znaleziony, funkcja load powoduje jego załadowanie. Jeśli plik PROG_025.LSP nie został znaleziony, standardowa funkcja AutoLISPu alert powoduje wypisanie w oknie dialogowym podanego łańcucha tekstu. Funkcja exit wymusza zakończenie bieżącego programu użytkowego. Wywołujemy ją po wyświetleniu komunikatu ostrzegawczego w oknie dialogowym. Gdyby funkcja ta nie została tutaj zastosowana, w trakcie realizacji dalszej części programu otrzymalibyśmy komunikat o błędzie gdyż wystąpiłaby próba wywołania niezdefiniowanej funkcji FOR. Zapis (initget (+ 1 2 4)) jest równoważny zapisowi (initget 5). Nie dopuszcza on do podania pustego ENTER, liczby zerowej lub liczby ujemnej podczas najbliższego wywołania funkcji entsel, nentsel lub getxxx (za wyjątkiem getstring, getenv i getvar). To tutaj wywołujemy naszą pętlę FOR. Oprócz podania wartości początkowej, końcowej oraz kroku pętli, pierwszym argumentem funkcji jest nazwa zmiennej sterującej pracą pętli. Nazwa zmiennej sterującej pracą pętli musi być poprzedzona apostrofem (tzn. musi być kwotowana). Jeśli o tym zapomnisz, program może dać nieoczekiwane rezultaty. Instrukcja progn grupuje nam instrukcje, które należy wykonać wpętli. Instrukcja grupująca progn musi być także kwotowana. Wypisujemy na ekranie tekstowym liczby spełniające podane wymagania. Qs{zlbe!3 Analizując wygląd ekranu w przykładzie pierwszym, z pewnością zauważyłeś dodatkowe odstępy pomiędzy wartością początkową,końcową oraz krokiem pętli, np: Podaj wartosc poczatkowa petli: 1 wolna_linia Podaj wartosc koncowa petli: 10 Dzieje się tak dlatego, że funkcje typu getxxx muszą być zakończone naciśnięciem klawisza ENTER, i to właśnie powoduje powstanie dodatkowej pustej linii.

9/!Qumf!j!lpotusvldkf!tufsvk df 266 W poniższym przykładzie, usuniemy te linie. Dodatkowo, spowodujemy, by wybrane liczby zostały zapisane w jednym rzędzie (a nie w jednej kolumnie, jak w przykładzie pierwszym). A oto i nasz program po modernizacji: *************************************************PROG_027 Wykorzystanie petli FOR - przyklad 2. --------------------------------------- odszukanie i zaladowanie pliku PROG_025.LSP plik (findfile "prog_025.lsp")) (if plik plik zostal znaleziony (load plik) )progn else - nia znaleziono pliku (alert "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)) x1 (getint "\npodaj wartosc poczatkowa petli: ")) (initget (+ 1 2 4)) x2 (getint "Podaj wartosc koncowa petli: ")) (initget (+ 1 2 4)) x3 (getint "Podaj krok petli: ")) (princ "\nwypisywanie od " (rtos x1 2 0) " do " (rtos x2 2 0) " z krokiem = " (rtos x3 2 0) ".\n" )strcat )princ

267 BvupMJTQ!!qsbluzd{oz!lvst Qs{zlbe!4 (for 'i x1 x2 x3 ' (princ i) (princ " ") )progn )for i --------------------------------------- *************************************************KONIEC Wykonanie powyższego programu możebyć następujące: Command: (load "prog_027.lsp") Przyklad wykorzystania petli for. Podaj wartosc poczatkowa petli: 1 Podaj wartosc koncowa petli: 10 Podaj krok petli: 2 Wypisywanie od 1 do 10 z krokiem = 2. 1 3 5 7 9 Command: Omówmy teraz wyróżnione linie programu, obrazujące zmiany w stosunku do programu PROG_026: Przy wypisywaniu na ekran tekstu "Podaj wartosc koncowa petli:", został pominięty znak nowej linii, umieszczony na początku łańcucha. Tym samym została usunięta pierwsza wolna linia. Przy wypisywaniu na ekran tekstu "Podaj krok petli:", został pominięty znak nowej linii, umieszczony na początku łańcucha. Tym samym została usunięta druga wolna linia. Zamiast funkcji terpri, powodującej przejście do nowej linii po wypisaniu liczby, używamy instrukcji princ, aby oddzielić od siebie poszczególne liczby, wypisywane w jednym rzędzie. Przykład ten pokazuje, jak za pomocą pętli FOR można tworzyć listę lub wyświetlać jej zawartość. *************************************************PROG_028 Wykorzystanie petli FOR - przyklad 3. --------------------------------------- odszukanie i zaladowanie pliku PROG_025.LSP plik (findfile "prog_025.lsp"))

9/!Qumf!j!lpotusvldkf!tufsvk df 268 (if plik plik zostal znaleziony (load plik) )progn else - nia znaleziono pliku (alert "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)) x1 (getint "\npodaj liczbe zmiennych do umieszczenia na liscie: " )getint )setq lista_1 (list)) pobranie zmiennych i umieszczenie ich na liscie lista_1 (terpri) (for 'i 1 x1 1 ' pobranie typu zmiennej (initget "I R S") typ (getkword "\Podaj typ zmiennej numer " (rtos i 2 0) " [I - integer, R - real, S - string]: " )strcat )getkword )setq typ (strcase typ)) pobranie wartosci zmiennej (princ "Podaj wartosc zmiennej numer " (rtos i 2 0) ": "

269 BvupMJTQ!!qsbluzd{oz!lvst )strcat )princ (cond ((= typ "I") zmienna (getint))) ((= typ "R") zmienna (getreal))) ((= typ "S") zmienna (getstring T))) )cond umieszczenie zmiennej na liscie lista_1 lista_1 (append lista_1 (list zmienna)) )setq )progn )for i wyswietlenie utworzonej listy (textpage) przejscie na ekran tekstowy (princ "Oto twoja lista wyswietlona funkcja PRINC:\n") (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 ' wyswietlenie numeru zmiennej (princ "\nzmienna numer " (rtos i 2 0) )strcat )princ wyswietlenie typu zmiennej typ (type (nth (- i 1) lista_1))) (cond ((= typ 'INT) typ "integer")) ((= typ 'REAL) typ "real")) ((= typ 'STR) typ "string")) )cond (princ "\ntyp zmiennej = " typ )strcat )princ