lisp 15

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

626

Wy

świetlanie informacji na ekranie jest użyteczne, ale niesie też ze sobą pewne ograni-

czenia. Nawet je

śli wstrzymamy działanie programu, aby zyskać na czasie przy odczy-

tywaniu z ekranu, to po przewini

ęciu informacji poza pole widzenia, aby ją odczytać

musimy ponownie uruchomi

ć program czy też wybraną funkcję.

A oprócz tego program utrzymuje warto

ść zmiennych tylko wtedy, gdy jest urucho-

miony; wprowadzona informacja zniknie po jego zatrzymaniu.

Aby informacja została zapisana na stałe lub by móc rozpowszechnia

ć wyniki własnej

pracy w

śród innych użytkowników, należy ją wydrukować. Z kolei przechowanie infor-

macji na dysku b

ędzie niezbędne wówczas, gdy zechcemy tylko raz wprowadzić dane

i móc z nich korzysta

ć wielokrotnie w późniejszym terminie.

Programy omówione w tym rozdziale.

PROG_109.LSP
Funkcja testuj

ąca okno dialogowe getfiled.

PROG_110.LSP
Zastosowanie funkcji getfiled do edycji pliku tekstowego.

PROG_111.LSP
Funkcja testuj

ąca okno dialogowe getfiled oraz funkcję findfile.

background image

627

BvupMJTQ!—!qsbluzd{oz!lvst

PROG_112.LSP
Funkcja dziel

ąca łańcuch z wartością zmiennej środowiskowej na listę podłańcuchów.

PROG_113.LSP
Przykład zastosowania funkcji read-char i write-char.
Test zapisu do pliku znak po znaku.

PROG_114.LSP
Przykład zastosowania funkcji read-line i write-line.
Test zapisu do pliku wierszami.

PROG_115.LSP
Przykład zapisu do pliku wierszami z zastosowaniem funkcji write-line.

PROG_116.LSP
Przykład zapisu do pliku informacji, które przed zapisem umieszczane s

ą na jednej liście.

PROG_117.LSP
Przykład zapisu do pliku wierszami z zastosowaniem funkcji FPRINTF, zawartej
w pliku PRINTF.LLB.

PROG_118.LSP
Zapis do pliku przykładowych linii z zastosowaniem funkcji princ, prin1, write-line
oraz FPRINTF.

PROG_119.LSP
Zapis danych w postaci rekordów.

PROG_120.LSP
Przykład zastosowania funkcji read-char i write-char.
Wy

świetlenie zawartości pliku znak po znaku.

PROG_121.LSP
Przykład zastosowania funkcji read-line i write-line.
Wy

świetlenie zawartości pliku wiersz po wierszu.

PROG_122.LSP
Przykład zastosowania funkcji read-line.
Odbiór zbioru danych dla MES.

PROG_123.LSP
Odczyt danych zapisanych do pliku w postaci jednej listy.

PROG_124.LSP
Przykład zastosowania funkcji SSCANF z biblioteki SCANF1.LLB.
Odbiór zbioru danych dla MES.

PROG_125.LSP
Odczyt danych w postaci rekordów.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

628

PROG_126.LSP
Przykład dodawania danych do pliku.

PROG_127.LSP
Wydruk pliku na drukark

ę lub ekran.

Dane wej

ściowe nie przechodzą bezpośrednio na dysk lub drukarkę, kiedy zastosujemy

polecenie wyprowadzenia. Zamiast tego, s

ą przesyłane do specjalnego obszaru pamięci,

nazwanego buforem. Po zapełnieniu buforu dane s

ą przenoszone na dysk lub drukarkę.

Dane wprowadzone z dysku tak

że są przenoszone do buforu; są tam przetrzymywane,

mog

ą więc być przypisane zmiennej lub wyświetlone.

Aby przeniesienie informacji do i z buforu było mo

żliwe musi istnieć łącze komuni-

kacyjne mi

ędzy programem a systemem operacyjnym komputera. Tym łączem jest plik.

Plikiem (ang. file) w najprostszym rozumieniu mo

żna nazwać ciąg danych tego samego

typu składowanych w pami

ęci zewnętrznej (tj. pamięci masowej) komputera.

Fizycznym przykładem pami

ęci zewnętrznej może być pamięć dyskowa lub taśmowa.

Przykładem ci

ągu danych może być zestaw liczb, linii tekstu, struktur (rekordów), itd.

W pewnych sytuacjach, ze wzgl

ędu na szybkość dostępu do danych, plik może być

równie

ż tymczasowo składowany w pamięci operacyjnej komputera (tzw. RAM-dysk).

Ka

żdy plik musi mieć zdolność przyjmowania i oddawania ciągów bajtów (znaków).

Z powy

ższych założeń wynika, że klawiatura i ekran są także plikami. Program

komunikuje si

ę z otoczeniem poprzez plik, który jest abstrakcją urządzenia

wej

ściowego lub wyjściowego. Wynika stąd, że programista nie musi, w zasadzie,

zastanawia

ć

si

ę

z jakim urz

ądzeniem jego program będzie się w przyszłości porozumiewał: pisanie

i czytanie z pliku wygl

ąda zawsze tak samo, bez względu na rodzaj urządzenia, które

jest z plikiem zwi

ązane. Oczywiście istnieją tu pewne wyjątki: np. drukarka lub monitor

s

ą zdecydowanie urządzeniami wyjścia i nie można z nich czytać; podobnie klawiatura

jest urz

ądzeniem wejścia i pisanie do niej nie miałoby większego sensu.

Bajty tworz

ące plik mogą być interpretowane w różny sposób. Z punktu widzenia

operacji wej

ścia lub wyjścia rozróżnia się dwa rodzaje plików: pliki tekstowe

(znakowe) i pliki binarne. Z uwagi na to,

że AutoLISP obsługuje jedynie pliki tekstowe,

w dalszej cz

ęści tego rozdziału będziemy się zajmować wyłącznie nimi.

Ka

żdy plik identyfikowany jest przez nazwę. AutoLISP udostępnia szereg funkcji

ułatwiaj

ących posługiwanie się plikami. W poniższej tabeli dokonano ich krótkiej

charakterystyki.

background image

629

BvupMJTQ!—!qsbluzd{oz!lvst

Tabela 15.1. Funkcje do obsługi plików tekstowych

(close file-desc)

Funkcja zamyka plik.

(load filename [onfailure])

Funkcja wczytuje plik z wyra

żeniami AutoLISPu.

(open filename mode)

Funkcja otwiera plik, udost

ępniając jego deskryptor funkcjom We/Wy AutoLISPu.

(prin1 [expr [file-desc]])

Funkcja drukuje komunikat na ekranie tekstowym lub w otwartym pliku dyskowym.

(princ [expr [file-desc]])

Funkcja drukuje komunikat na ekranie tekstowym lub w otwartym pliku dyskowym.

(print [expr [file-desc]])

Funkcja drukuje komunikat na ekranie tekstowym lub w otwartym pliku dyskowym.

(read-char [file-desc])

Funkcja odczytuje pierwszy znak z klawiatury lub otwartego pliku.

(read-line [file-desc])

Funkcja odczytuje ła

ńcuch tekstowy, znak z klawiatury lub otwartego pliku.

(write-char num [file-desc])

Funkcja zapisuje jeden znak, podany w kodzie ASCII, na ekranie lub w otwartym pliku.

(write-line string [file-desc])

Funkcja zapisuje ła

ńcuch alfanumeryczny na ekranie lub w otwartym pliku.

Nazwy plików w systemie MS-DOS zbudowane s

ą z co najwyżej ośmiu znaków, liter

lub cyfr (minimum jeden znak). Nazwa pliku jest uzupełniona co najwy

żej trzy-

znakowym rozszerzeniem (opcja). Mi

ędzy nazwą a rozszerzeniem (zawsze) występuje

kropka. Pełna nazwa pliku mo

że się składać z minimum 1 znaku i kropki. Następujące

znaki nie mog

ą występować w nazwach plików:

< > = , : ; . * ? [ ] ( ) / \ +

Nazwa pliku powinna informowa

ć o jego zawartości lub pełnionej funkcji, a roz-

szerzenie o typie pliku. Niektórym rodzajom plików przypisano obligatoryjnie
rozszerzenia:

.EXE i .COM
pliki zawieraj

ące programy wykonywalne.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

62:

.BAT
pliki zawieraj

ące zbiór poleceń systemu operacyjnego, tzw. pliki wsadowe.

Niektóre rozszerzenia nie s

ą obligatoryjne, ale przyjęły się zwyczajowo lub identyfikują

okre

ślone programy, np.:

.BAK
kopia pliku, zbiór zapasowy.

.BAS
program

źródłowy w języku Basic.

.C .CPP
program

żródłowy w języku C, C++.

.DBF
zbiór danych w formacie dBase.

.DWG
pliki rysunkowe AutoCADa.

.LSP
program

źródłowy w języku AutoLISP.

.PAS
program

źródłowy w języku Pascal.

.SYS
plik systemowy lub sterownik programowy.

Na równi z nazwami plików wyst

ępują w niektórych poleceniach nazwy urządzeń

wej

ścia/wyjścia. Nazwy te jednoznacznie identyfikują urządzenia:

CON
(ang. console) klawiatura i monitor.

AUX lub COMn
port komunikacji szeregowej (n = 1, 2, 3 lub 4) w zale

żności od konfiguracji

komputera.

PRN lub LPT1
pierwszy port komunikacji równoległej.

LPT2 lub LPT3
drugi lub trzeci port komunikacji równoległej.

NUL
urz

ądzenie nie istniejące — symulowane (czasem istnieje potrzeba skierowania gdzieś

informacji bez wywoływania skutków).

Nazw

ę pliku (wraz z ew. ścieżką dostępu do pliku) pobieramy w języku AutoLISP

wykorzystuj

ąc funkcję biblioteczną getstring lub getfiled. Do odszukania pliku stosu-

jemy tak

że funkcję biblioteczną findfile.

background image

631

BvupMJTQ!—!qsbluzd{oz!lvst

26/3/2/

26/3/2/

26/3/2/

26/3/2/ Qpcjfs

Qpcjfs

Qpcjfs

Qpcjfsbojf!ob{xz!qmj

bojf!ob{xz!qmj

bojf!ob{xz!qmj

bojf!ob{xz!qmjlv!{b!qpnpd

lv!{b!qpnpd

lv!{b!qpnpd

lv!{b!qpnpd

gvoldkj!H

gvoldkj!H

gvoldkj!H

gvoldkj!HFUTUSJOH

FUTUSJOH

FUTUSJOH

FUTUSJOH

Funkcja posiada format:

(getstring

[cr][prompt])

Funkcja ta powoduje przerw

ę, która umożliwia użytkownikowi wprowadzenie nazwy

pliku. Gdy jest to konieczne, nazw

ę pliku poprzedzamy jego ścieżką dostępu. Podczas

wykorzystania funkcji getstring do pobrania nazwy pliku, nie mo

żna używać argu-

mentu cr (lub nale

ży podać ten argument jako nil) — uniemożliwiamy wtedy podanie

w nazwie pliku spacji.

Poni

żej podano przykładowe wywołania funkcji getstring, odpowiedzi użytkownika

oraz przykłady otwarcia i zamkni

ęcia plików.

Command: (setq x1 (getstring "\nPodaj nazwe pliku: "))

↵↵

Podaj nazwe pliku: c:\t1.dat

↵↵

"c:\\t1.dat"

Command: (setq plik (open x1 "w"))

↵↵

<File: #5707c>

Command: (if plik (close plik))

↵↵

nil
Command:

Wyst

ępujący w nazwie pliku pojedynczy lewy ukośnik (\) podlega konwersji na dwa

lewe uko

śniki (\\). Konwersja taka umożliwia podanie prawidłowej ścieżki dostępu do

pliku. Funkcja otwarcia pliku open zwraca wska

źnik do niego (deskryptor pliku), plik

zostanie wi

ęc zamknięty funkcją close występującą w instrukcji warunkowej if plik.

Command: (setq x2 (getstring "\nPodaj nazwe pliku: "))

↵↵

Podaj nazwe pliku: c:/t2.dat

↵↵

"c:/t2.dat"

Command: (setq plik (open x2 "w"))

↵↵

<File: #56f98>

Command: (if plik (close plik))

↵↵

nil
Command:

Wyst

ępujący w nazwie pliku pojedynczy prawy ukośnik (/) umożliwia drugą metodę

podania prawidłowej

ścieżki dostępu do pliku. Plik ten zostanie również otwarty,

a nast

ępnie zamknięty.

Command: (setq x3 (getstring "\nPodaj nazwe pliku: "))

↵↵

Podaj nazwe pliku: c:\\t3.dat

↵↵

"c:\\\\t3.dat"
Command: (setq plik (open x3 "w"))

↵↵

nil
Command: (if plik (close plik))

↵↵

nil
Command:

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

632

W powy

ższym przykładzie, w nazwie pliku użyto dwóch lewych ukośników (\\).

Podlegaj

ą one konwersji na cztery lewe ukośniki (\\\\). Tak podana ścieżka dostępu do

pliku jest bł

ędna — funkcja open zwraca nil, nie zostanie więc wykonana funkcja

zamkni

ęcia pliku close (if plik zwraca nil).

Command: (setq x4 (getstring "\nPodaj nazwe pliku: "))

↵↵

Podaj nazwe pliku: c://t4.dat

↵↵

"c://t4.dat"

Command: (setq plik (open x4 "w"))

↵↵

nil

Command: (if plik (close plik))

↵↵

nil
Command:

W powy

ższym przykładzie, w nazwie pliku użyto dwóch prawych ukośników (//)

i w takiej postaci zwraca je te

ż funkcja getstring. Tak podana ścieżka dostępu do pliku

jest bł

ędna — funkcja otwarcia pliku open zwróci nil, nie zostanie tym samym wyko-

nana funkcja zamkni

ęcia pliku close.

2

22

26/3/3/

6/3/3/

6/3/3/

6/3/3/ Qpcjfsb

Qpcjfsb

Qpcjfsb

Qpcjfsbojf!ob{xz!qmj

ojf!ob{xz!qmj

ojf!ob{xz!qmj

ojf!ob{xz!qmjlv!{b!qpnpd

lv!{b!qpnpd

lv!{b!qpnpd

lv!{b!qpnpd

gvoldkj!H

gvoldkj!H

gvoldkj!H

gvoldkj!HFUGJMFE

FUGJMFE

FUGJMFE

FUGJMFE

Funkcja posiada format:

(getfiled

title default ext flags)

Funkcja wy

świetla okno dialogowe zawierające nazwy plików we wskazanym katalogu.

Zmieniaj

ąc katalog powodujemy uaktualnienie listy plików w nim zawartych. Plik

mo

żna wskazać na liście (w tym przypadku musi to być plik już istniejący — nawet

je

śli jest to plik pusty), lub można wpisać jego nazwę (z opcjonalną ścieżką dostępu)

w polu dialogowym File: (Plik:) — w tym przypadku wpisujemy nazw

ę pliku już

istniej

ącego lub nazwę nowego pliku do utworzenia.

Funkcja getfiled wywoływana jest z czterema argumentami:

title

Ła

ńcuch określający nagłówek okna (jest on wypisywany w belce tytułowej okna). Mo-

żesz podać dowolny łańcuch do wyświetlenia w belce tytułowej okna. Gdy długość
ła

ńcucha przekracza 46 znaków, koniec łańcucha jest obcinany. Podanie pustego łańcu-

cha — "" — jako argumentu funkcji nie wy

świetla żadnego napisu w belce tytułowej.

default

Ła

ńcuch określający domyślną nazwę pliku wraz z rozszerzeniem i ew. ścieżką dostępu.

Je

śli w nazwie pliku podana jest ścieżka dostępu, to zawartość wskazywanego przez nią

katalogu zostanie wy

świetlona w oknie. Bez podania ścieżki funkcja getfiled wyświetli

zawarto

ść bieżącego katalogu. Jeżeli podana zostanie podstawowa nazwa pliku to

zostanie umieszczona w polu edycyjnym File: (Plik:). Je

żeli plik o wskazanej nazwie już

background image

633

BvupMJTQ!—!qsbluzd{oz!lvst

istnieje, to zostanie on pod

świetlony na liście plików. Dostępny jest również przycisk

Default (Standard), który pozwala na natychmiastowy wybór pliku domy

ślnego.

ext

Ła

ńcuch określający rozszerzenie pliku. Jeżeli zostanie podany łańcuch pusty — "" —

to wy

świetlone zostaną wszystkie pliki znajdujące się w katalogu. Jeżeli wystąpi

okre

ślone rozszerzenie, to na liście znajdą się wyłącznie pliki, które mają takie samo

rozszerzenie.

flags

Liczba całkowita (znacznik bitowy) steruj

ąca działaniem okna dialogowego. Aby

jednocze

śnie ustalić większą liczbę warunków, należy po prostu zsumować wartości

(w dowolnej kolejno

ści), tworząc wartość argumentu flags z zakresu od 0 do 15.

Warto

ści i znaczenie argumentu flags są następujące:

1. oznacza

żądanie utworzenia nowego pliku,

2. blokuje przycisk Type it (Wpisz),

3. pozwala u

żytkownikowi wprowadzić dowolne rozszerzenie nazwy pliku,

4. wykonuje szukanie pliku o podanej nazwie w

ścieżce poszukiwania bibliotek

AutoCADa,

Po otrzymaniu od u

żytkownika poprawnej nazwy pliku (wyjście z okna dialogowego

przyciskiem OK), funkcja getfiled zwraca ła

ńcuch z nazwą pliku. W przypadku wyjścia

z okna dialogowego przyciskiem Cancel, funkcja getfiled zwraca nil.

Oto kilka przykładowych wywoła

ń funkcji getfiled z linii komend.

Command: (getfiled "" "" "" 2)

↵↵

Nale

ży wskazać plik już istniejący. Belka tytułowa okna dialogowego jest pusta, nie

wyst

ępuje domyślna nazwa pliku, rozszerzenie pliku może być dowolne. Przyciski

Type it (Napisz) oraz Default (Standard) s

ą zablokowane.

Command: (getfiled "Wybierz Plik" "" "" 3)

↵↵

Mo

żemy wskazać plik już istniejący lub wpisać nazwę nowego pliku. W przypadku,

gdy plik istnieje ju

ż na dysku, jesteśmy o tym informowani przy pomocy dodatkowego

okna dialogowego. Opuszczaj

ąc okno dodatkowe przyciskiem OK, wybieramy opcję

przepisania pliku, wybieraj

ąc zaś przycisk Cancel wracamy do głównego okna dialogo-

wego funkcji getfiled.

Wybór pliku istniej

ą

cego do zapisu mo

ż

e oznacza

ć

dwie mo

ż

liwo

ś

ci:

nowe dane całkowicie zast

ą

pi

ą

stare — plik otwarty w trybie "w" (write —

do zapisu),

nowe dane zostan

ą

dopisane do ko

ń

ca pliku — plik otwarty w trybie "a" (ap-

pend — do dopisywania).

Command: (getfiled "Wybierz Plik LSP" "" "lsp" 3)

↵↵

Mo

żemy wskazać plik już istniejący lub wpisać nazwę nowego pliku. Wybranie pliku

o rozszerzeniu innym ni

ż LSP powoduje zablokowanie możliwości opuszczenia okna

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

634

przyciskiem OK — w dole okna wypisywany jest wówczas komunikat ostrzegawczy
o złym typie rozszerzenia wybranego pliku.

Command: (getfiled "Wybierz plik LSP" "" "lsp" 7)

↵↵

Domy

ślne rozszerzenie pliku to LSP, mamy jednak możliwość jego zmiany. Osiągamy

to dodaj

ąc do argumentu flags cyfrę 4.

Poni

żej podano przykład programu do testowania funkcji getfiled. Program działa w pętli,

wywołuj

ąc każdorazowo funkcję getfiled. Po opuszczeniu okna przyciskiem OK w linii

komend wypisywany jest wybrany plik wraz z rozszerzeniem i

ścieżką dostępu.

;*************************************************PROG_109
;Funkcja testujaca okno dialogowe GETFILED.
;
(princ "\nLadowanie programu testujacego funkcje GETFILED.")
;
(defun C:TESTUJ_GETFILED (/ jeszcze plik status odp)

(progn

;----------
(setq jeszcze T)
(while jeszcze

(progn

;----------

(setq plik (getfiled "Wybierz Plik" "" "" 3))

(setq status (getvar "diastat"))

(if (= status 1)

(progn

;wybrano przycisk OK

(princ "\nWybrales: ")
(princ plik)

);progn

;

(progn

;else - wybrano przycisk Cancel

(princ "\nWybor niewazny.")

);progn

);if

(initget 1 "T t N n")

(setq odp (getkword "\nCzy konczymy [T/N]? "))

(setq odp (strcase odp))

(if (= odp "T")

(progn

;----------
(setq jeszcze nil)
;----------

);progn

);if

;----------

);progn

);while jeszcze
;----------
(princ)
;----------

);progn

);TESTUJ_GETFILED

background image

635

BvupMJTQ!—!qsbluzd{oz!lvst

;
(defun C:TG ()

(progn

;----------
(C:TESTUJ_GETFILED)
(princ)
;----------

);progn

);C:TG
;
(princ "\nProgram zaladowany.")
(princ "\nKomenda TG uruchamia testowanie.")
(princ)
;
;*************************************************KONIEC

Omówmy teraz wyró

żnione linie i bloki programu.

Wywołujemy funkcję getfiled, podstawiając jej wartość zwrotną pod zmienną

plik. Mo

żemy wybrać plik już istniejący lub wpisać nazwę nowego pliku.

Wykorzystując zmienną systemową AutoCADa DIASTAT badamy, czy okno

dialogowe funkcji getfiled zostało opuszczone przyciskiem OK (status = 1), czy
te

ż przyciskiem Cancel (status = 0).

Ten blok instrukcji jest wykonywany wówczas, gdy zmienna status ma wartość

1 (wybrano przycisk OK). Wypisujemy wówczas w linii komend wybrany plik.

Ten blok instrukcji jest wykonywany wówczas, gdy zmienna status ma wartość

0 (wybrano przycisk Cancel).

Ustawiamy bity i słowa kluczowe funkcji initget, obowiązujące podczas

wywołania funkcji getkword.

Użytkownik decyduje, czy chce zakończyć wykonywanie programu. Wartość

zwrotn

ą funkcji getkword podstawiamy pod zmienną odp.

Zamieniamy wszystkie litery w zmiennej odp na duże.
Ten blok instrukcji wykonywany jest wówczas, gdy użytkownik zadecydował

o zako

ńczeniu wykonywania programu. Ustawiamy wówczas wartość zmiennej

jeszcze na nil, umo

żliwiając tym samym opuszczenie pętli while.

Poni

żej zaprezentowany zostanie program wykorzystujący funkcję getfiled, edytor

Nortona oraz komend

ę NE utworzoną w pliku ACAD.PGP. Zadaniem programu jest

pobranie nazwy pliku tekstowego za pomoc

ą funkcji getfiled, a następnie umożliwienie

edycji wybranego pliku edytorem Nortona. Po zako

ńczeniu edycji pliku wracamy

z powrotem do

środowiska AutoCADa. W przypadku powtórnego wywołania funkcji

w tej samej sesji rysunkowej, program ma proponowa

ć jako nazwę domyślną ostatnio

edytowany plik. Dodatkowo, nale

ży zdefiniować zmianną globalną glob_ext, będącą

filtrem rozszerzenia plików wy

świetlanych przez funkcję getfiled. Zmienną tę należy

ustawi

ć na wartość "LSP". W przypadku, gdy wartością zmiennej glob_ext jest pusty

ła

ńcuch, funkcja getfiled wyświetla wszystkie pliki.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

636

;*************************************************PROG_110
;Wykorzystanie funkcji GETFILED do edycji pliku tekstowego.
;
;UWAGA1
;Funkcja korzysta z edytora Norton Edytor, ktorego
;wywolanie zapisane jest w pliku ACAD.PGP.
;
;UWAGA 2
;Funkcja korzysta ze zmiennej globalnej glob_$_file_name,
;oznaczajacej sciezke dostepu i nazwe ostatnio
;edytowanego pliku (w biezacej sesji).
;
;-------------------------------------------------
;Ustawienie zmiennej globalnej GLOB_EXT oznaczajacej
;domyslne rozszerzenie plikow.
;
;UWAGA
;Podanie pustego lancucha "" oznacza zadanie wyswietlenia
;wszystkich plikow
;

(setq glob_ext "lsp")

;-------------------------------------------------
;

(defun C:EDIT ( / plik czy_istnieje file_hdlg)

(progn

;----------
;sprawdzenie zmiennej glob_$_file_name
;

(if (= glob_$_file_name nil)

(progn

(setq glob_$_file_name "")

);progn
(progn

;else

(if (/= (type (eval glob_$_file_name)) 'STR)

(progn

(setq glob_$_file_name "")

);progn

);if

);progn

);if

;----------
;pobranie nazwy pliku
;

(if (= glob_$_file_name "")

(progn

(setq

plik (getfiled

"Wybierz Plik Do Edycji"
""
glob_ext
(+ 1 2)

);getfiled

);setq

);progn

background image

637

BvupMJTQ!—!qsbluzd{oz!lvst

(progn

;else

(setq

plik (getfiled

"Wybierz Plik Do Edycji"
glob_$_file_name
glob_ext
(+ 1 2)

);getfiled

);setq

);progn

);if

;----------
;jesli okno dialogowe zostalo opuszczone poprzez
;wybranie przycisku OK, wywolanie edytora tekstu
;

(if plik

(progn

;----------
;sprawdzenie, czy podano nazwe istniejacego pliku
;czy nalezy utworzyc nowy plik
;

(setq

czy_istnieje (findfile plik)

);setq
;----------

(if czy_istnieje

(progn

;edycja istniejacego pliku

(setq glob_$_file_name plik)
(command "ne" plik)

);progn
(progn

;else - utworzenie nowego pliku

(setq glob_$_file_name plik)
(setq file_hdlg (open plik "w"))
(close file_hdlg)
(command "ne" plik)

);progn

);if

;----------

);progn

);if
;----------
(princ)
;----------

);progn

);C:EDIT
;
;-------------------------------------------------
;

(defun C:ED ()

(progn

;----------
(C:EDIT)
(princ)
;----------

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

638

);progn

);C:ED
;
;-------------------------------------------------
;*************************************************KONIEC

Omówmy teraz wyró

żnione linie i bloki programu.

Ustawiamy wartość zmiennej globalnej glob_ext, będącej filtrem rozszerzenia

plików wy

świetlanych w oknie dialogowym getfiled.

Definiujemy zewnętrzną komendę AutoCADa EDIT, pobierającą nazwę pliku

do edycji i wywołuj

ącą edytor Nortona.

W bloku tym sprawdzamy wartość zmiennej globalnej glob_$_file_name.

Zmienna ta wskazuje

ścieżkę dostępu i nazwę ostatnio edytowanego pliku. Jeśli

warto

ścią zmiennej jest nil, oznacza to, że funkcja EDIT jest wywoływana po

raz pierwszy w bie

żącej sesji. Ustawiamy wówczas wartość zmiennej glob_$

_file_name na pusty string. Je

śli wartością zmiennej nie jest nil, sprawdzamy

dodatkowo, czy jest to zmienna typu ła

ńcuchowego. Jeśli nie, ustawiamy war-

to

ść zmiennej glob_$_file_name na pusty string.

W bloku tym wywołujemy funkcję getfiled, umożliwiając użytkownikowi

wybór pliku do edycji. Sposób wywołania funkcji getfiled zale

ży od wartości

zmiennej globalnej glob_$_file_name. W przypadku, gdy jest to pusty string,
oznacza to,

że komendę EDIT wywołujemy po raz pierwszy w bieżącej sesji.

Nie proponujemy wówczas warto

ści domyślnej nazwy pliku. W przypadku, gdy

warto

ść zmiennej globalnej glob_$_file_name nie jest pustym stringiem, jest ona

podstawiana jako argument default funkcji getfiled. Wystarczy wówczas po
wy

świetleniu okna dialogowego wybrać przycisk OK, aby uruchomić edytor

Nortona z ostatnio edytowanym plikiem.

Ta instrukcja warunkowa if jest wykonywana wówczas, jeśli okno dialogowe

getfiled opuszczono poprzez wybranie przycisku OK.

Sprawdzamy, czy użytkownik wybrał plik już istniejący na dysku czy też należy

utworzy

ć nowy plik.

Jeśli wybrano plik już istniejący na dysku, ustawiamy wartość zmiennej glob_$

_file_name na nazw

ę pliku wraz ze ścieżką dostępu, po czym wywołujemy

edytor Nortona.

Je

śli wybrano edycję nowego pliku, ustawiamy wartość zmiennej glob_$_file

_name na nazw

ę pliku wraz ze ścieżką dostępu, otwieramy plik w trybie do

zapisu, zamykamy plik (tworzymy tym samym pusty plik na dysku), po czym
wywołujemy edytor Nortona. Musimy tak zrobi

ć dlatego, ponieważ Norton

Edytor wywoływany z wn

ętrza AutoCADa nie rozpoznaje prawidłowo ścieżki

dost

ępu do pliku, który dopiero należy utworzyć (zapisuje taki plik w katalogu,

z którego został uruchomiony AutoCAD). Utworzenie pustego pliku na dysku,
a nast

ępnie jego edycja rozwiązuje ten problem.

Definiujemy zewnętrzną komendę AutoCADa ED, wywołującą komendę EDIT.

Tym samym mamy dwie komendy realizuj

ące to samo zadanie: ED oraz EDIT.

background image

639

BvupMJTQ!—!qsbluzd{oz!lvst

26/

26/

26/

26/3/4/

3/4/

3/4/

3/4/ Tqsbx

Tqsbx

Tqsbx

Tqsbxe{bojf!jtuojfojb!qmj

e{bojf!jtuojfojb!qmj

e{bojf!jtuojfojb!qmj

e{bojf!jtuojfojb!qmjlv!{b!qpnpd

lv!{b!qpnpd

lv!{b!qpnpd

lv!{b!qpnpd

gvoldkj!GJ

gvoldkj!GJ

gvoldkj!GJ

gvoldkj!GJOEGJMF

OEGJMF

OEGJMF

OEGJMF

Funkcja findfile posiada format:

(findfile

filename)

Funkcja poszukuje okre

ślonego pliku w bibliotecznej ścieżce poszukiwań AutoCADa

i w razie sukcesu zwraca pełn

ą nazwę pliku wraz ze ścieżką dostępu.

Funkcja ta umo

żliwia napisanie aplikacji poszukującej pliku o podanej nazwie.

Aplikacja mo

że określać katalog do przeszukania, albo może korzystać z bieżącej

bibliotecznej

ścieżki poszukiwań AutoCADa.

W poni

ższym fragmencie kodu funkcja findfile poszukuje pliku w ścieżce bibliotek

AutoCADa:

(setq file_name "test1.dwg")
(setq plik (findfile file_name))
(if plik

(progn

(setq file_name plik)

);progn
(progn

;else

(princ (strcat "\nNie znaleziono pliku " file_name "."))

);progn

);if plik

Je

śli wywołanie findfile zakończy się sukcesem, zmiennej plik zostanie przypisany

ła

ńcuch tekstowy z nazwą pliku z pełną ścieżką dostępu, na przykład:

"c:/acad/testy/test1.dwg"

Przy podawaniu

ś

cie

ż

ki dost

ę

pu w systemie DOS wewn

ą

trz procedury w Auto-

LISPie, uko

ś

nik lewy "\" musi by

ć

poprzedzony przez drugi uko

ś

nik lewy "\\".

Zamiast dwóch uko

ś

ników lewych "\", w charakterze separatora nazw

katalogów mo

ż

na stosowa

ć

jeden uko

ś

nik prawy "/".

Funkcja findfile zwraca nil w nast

ępujących przypadkach:

podano bł

ędną ścieżkę dostępu do pliku,

podano bł

ędną nazwę pliku,

podano nazw

ę pliku, który należy dopiero utworzyć.

Funkcj

ę findfile można wykorzystać w połączeniu z funkcją getfiled. Funkcja getfiled,

je

żeli została opuszczona poprzez wybranie przycisku OK, zwraca poprawną ścieżkę

dost

ępu do pliku wraz z nazwą pliku i jego rozszerzeniem. Wartość zwrotna funkcji

getfiled mo

że być następnie podana jako argument funkcji findfile. Aplikacja może

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

63:

wówczas wychwyci

ć, czy użytkownik wybrał plik istniejący na dysku, czy też należy

utworzy

ć podany plik.

Poni

ższy program pokazuje sposób wykorzystania funkcji findfile w połączeniu

z funkcj

ą getfiled. Program działa w pętli, wywołując każdorazowo funkcję getfiled. Po

opuszczeniu okna przyciskiem OK w linii komend wypisywany jest wybrany plik wraz
z rozszerzeniem i

ścieżką dostępu. Dodatkowo wywoływana jest funkcja findfile, aby

okre

ślić, czy plik zwrócony przez funkcję getfiled istnieje już na dysku czy jest to plik

wymagaj

ący utworzenia. Odpowiedni komunikat dopisywany jest w linii komend do

nazwy wybranego pliku.

;*************************************************PROG_111
;Funkcja testujaca okno dialogowe GETFILED
;oraz funkcje FINDFILE.
;
(princ "\nLadowanie programu testujacego funkcje ")
(princ "GETFILED i FINDFILE.")
;
(defun C:TESTUJ_GETFILED_FINDFILE

(/ jeszcze plik status czy_istnieje odp)

(progn

;----------
(setq jeszcze T)
(while jeszcze

(progn

;----------
(setq plik (getfiled "Wybierz Plik" "" "" 3))
(setq status (getvar "diastat"))
(if (= status 1)

(progn

;wybrano przycisk OK

(princ "\nWybrales: ")
(princ plik)
;

(setq czy_istnieje (findfile plik))

(if czy_istnieje

(progn

;istniejacy plik

(princ "

Plik istniejacy.")

);progn

;

(progn

;else - nowy plik

(princ "

Nowy plik.")

);progn

);if

);progn
;
(progn

;else - wybrano przycisk Cancel

(princ "\nWybor niewazny.")

);progn

);if
(initget 1 "T t N n")
(setq odp (getkword "\nCzy konczymy [T/N]? "))
(setq odp (strcase odp))
(if (= odp "T")

background image

641

BvupMJTQ!—!qsbluzd{oz!lvst

(progn

;----------
(setq jeszcze nil)
;----------

);progn

);if
;----------

);progn

);while jeszcze
;----------
(princ)
;----------

);progn

);TESTUJ_GETFILED_FINDFILE
;
(defun C:TGF ()

(progn

;----------
(C:TESTUJ_GETFILED_FINDFILE)
(princ)
;----------

);progn

);C:TGF
;
(princ "\nProgram zaladowany.")
(princ "\nKomenda TGF uruchamia testowanie.")
(princ)
;
;*************************************************KONIEC

Poniewa

ż program ten stanowi modyfikację programu testującego funkcję getfiled,

omówione zostan

ą tylko nowe elementy programu.

Jeśli funkcja getfiled została opuszczona poprzez wybranie przycisku OK,

wykorzystujemy funkcj

ę findfile aby zbadać, czy wybrano plik istniejący czy też

plik, który nale

ży utworzyć.

Ten blok instrukcji jest wykonywany wówczas, gdy funkcja getfiled zwróciła

nazw

ę pliku istniejącego.

Ten blok instrukcji jest wykonywany wówczas, gdy funkcja getfiled zwróciła

nazw

ę nowego pliku.

26/

26/

26/

26/3/5/

3/5/

3/5/

3/5/ Gvoldk

Gvoldk

Gvoldk

Gvoldkb!SFUVSO`Q

b!SFUVSO`Q

b!SFUVSO`Q

b!SFUVSO`QBUI!

BUI!

BUI!

BUI!—

—!sp{t{fs{f

!sp{t{fs{f

!sp{t{fs{f

!sp{t{fs{fojf

ojf

ojf

ojf

tdjf-lj!qpt

tdjf-lj!qpt

tdjf-lj!qpt

tdjf-lj!qpt{vljxbojb!qmjl

{vljxbojb!qmjl

{vljxbojb!qmjl

{vljxbojb!qmjl.x

.x

.x

.x

Funkcja findfile przeszukuje okre

ślony katalog lub katalogi AutoCADa określone

zmienn

ą środowiskową ACAD. Biblioteczna ścieżka poszukiwań jest przeszukiwana

w nast

ępującej kolejności:

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

642

katalog bie

żący,

katalog zawieraj

ący plik bieżącego rysunku,

katalogi okre

ślone przez zmienną środowiskową ACAD,

katalog zawieraj

ący plik ACAD.EXE.

W zale

ż

no

ś

ci od bie

żą

cego

ś

rodowiska, dwa lub wi

ę

cej tych katalogów , mo

ż

e

by

ć

w rzeczywisto

ś

ci tym samym katalogiem.

Pisz

ąc programy, chcemy czasami wykorzystywać katalogi, których nie chcemy załą-

cza

ć do bibliotecznej ścieżki poszukiwań AutoCADa. Powyższy problem można roz-

wi

ązać na dwa sposoby:

umie

ścić w pliku LSP zmienne określające katalogi dla danego programu, np:

(setq

kat_1 "c:\programy\app1\"
kat_2 "c:\programy\app1\demo\"
kat_3 "c:\temp\"

);setq

W przypadku zmiany potrzebnych katalogów, musimy dokona

ć modyfikacji

zmiennych w pliku LSP.

posługuj

ąc się zmienną środowiskową DOSu SET, ustawiamy katalogi dla

programu, np:

set app1=c:\programy\app1;c:\programy\app1\demo;c:\temp

W przypadku zmiany potrzebnych katalogów, dokonujemy jedynie modyfikacji
zmiennej

środowiskowej app1.

Poni

żej przedstawiono funkcję RETURN_PATH, która pobiera zawartość określonej

zmiennej

środowiskowej oraz rozbija ją na listę łańcuchów, z których każdy jest pełną

ścieżką dostępu do plików użytkownika, aplikacji itp.

;*************************************************PROG_112
;Funkcja rozbija zmienna srodowiskowa na liste lancuchow.
;Koniec lancucha - gdy napotkamy znak srednika.
;
;Funkcja wywolywana jest z jednym argumentem:
;env_var - lancuch z nazwa zmiennej srodowiskowej.
;
;Wartosc zwrotna funkcji:
;lista lancuchow lub nil, gdy podana zmienna nie istnieje
;lub ma pusta wartosc.
;
;Przyklad wywolania funkcji:
;(setq sciezka_1 (RETURN_PATH "PAFEC12"))
;
(defun RETURN_PATH (env_var /

lista path dlugosc licznik substring
znak koniec_lancucha

background image

643

BvupMJTQ!—!qsbluzd{oz!lvst

)

(progn

;----------
(setq

lista nil

path (getenv env_var)

);setq

(if (/= path nil)

(progn

;----------

(setq dlugosc (strlen path))

(if (> dlugosc 0)

(progn

;----------
(setq

licznik 1
substring ""

);setq

(repeat dlugosc

(progn

;----------

(setq znak (substr path licznik 1))

;----------

(if (= znak ";")

(progn

(setq

koniec_lancucha

(substr

substring
(strlen substring)

);substr

);setq
(if (and

(/= koniec_lancucha "\\")
(/= koniec_lancucha "/")

);and

(progn

;----------
(setq

substring

(strcat substring "\\")

);setq
;----------

);progn

);if
(setq

lista (append lista (list substring))
substring ""

);setq

);progn

;

(progn

;else

(setq substring (strcat substring znak))

);progn

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

644

);if
;----------

(setq licznik (1+ licznik))

;----------

);progn

);repeat dlugosc
;----------

(if (/= substring "")

(progn

;----------
(setq

koniec_lancucha

(substr

substring
(strlen substring)

);substr

);setq
(if (and

(/= koniec_lancucha "\\")
(/= koniec_lancucha "/")

);and

(progn

;----------
(setq

substring

(strcat substring "\\")

);setq
;----------

);progn

);if
(setq lista (append lista (list substring)))
;----------

);progn

);if

;----------

);progn

);if
;----------

);progn

);if
;----------
;zwrot listy lancuchow zmiennej systemowej
;lub zwrot wartosci nil
lista
;----------

);progn

);RETURN_PATH
;
;*************************************************KONIEC

background image

645

BvupMJTQ!—!qsbluzd{oz!lvst

Omówmy teraz wyró

żnione linie i bloki programu.

Wykorzystując funkcję AutoLISPu getenv, pobieramy wartość zmiennej syste-

mowej przekazanej w argumencie env_var i podstawiamy j

ą pod zmienną path.

Format funkcji getenv jest nast

ępujący:

(getenv

variable-name)

Funkcja ta zwraca warto

ść typu string w postaci łańcucha alfanumerycznego

przypisanego do systemowej zmiennej

środowiskowej. Argument variable-name

jest ła

ńcuchem określającym nazwę zmiennej, której wartość ma być odczytana.

Je

śli taka zmienna nie istnieje, to funkcja getenv zwraca nil.

Jeśli zmienna systemowa została ustawiona (dotyczy to także przypadku set

variable= ), przyst

ępujemy do jej przetwarzania.

Obliczamy długość łańcucha reprezentującego zmienną systemową.
Jeśli długość zmiennej systemowej jest większa od zera, rozpoczynamy przetwa-

rzanie zmiennej na list

ę podłańcuchów. Zmienną licznik (kolejne znaki w

zmiennej systemowej) ustawiamy na 1, zmienn

ą substring (łańcuch oznaczający

kolejne

ścieżki dostępu do plików) ustawiamy na początek jako łańcuch pusty.

Wchodzimy w pętlę repeat i rozpoczynamy przetwarzanie zmiennej systemowej.
Pobieramy kolejny znak z łańcucha reprezentującego zmienną systemową.
Ten blok instrukcji jest wykonywany wówczas, gdy znak jest separatorem końca

ścieżki dostępu — ";". Sprawdzamy wówczas, czy ścieżka dostępu kończy się
uko

śnikiem (prawym lub lewym). Jeśli nie, dodajemy ukośnik na koniec łań-

cucha w zmiennej substring. Nast

ępnie dołączamy łańcuch do listy podłańcu-

chów oraz ustawiamy zmienn

ą substring na pusty łańcuch — jesteśmy gotowi

do szukania kolejnej

ścieżki dostępu.

Ten blok instrukcji jest wykonywany wówczas, gdy znak nie jest separatorem końca

ścieżki dostępu — dołączamy go wówczas na koniec łańcucha w zmiennej substring.

Zwiększamy zmienną licznik o 1, umożliwiając tym samym przetworzenie

kolejnego znaku zmiennej

środowiskowej.

Ten blok instrukcji wykonywany jest już po wyjściu z pętli repeat, a więc po

przetworzeniu całej zmiennej

środowiskowej. Jeśli ostatnim znakiem zmiennej

nie b

ędzie znak separatora końca ścieżki — ";" — ostatni podłańcuch będzie się

znajdował w zmiennej substring, nie zostanie on jednak automatycznie dodany
do listy podła

ńcuchów. Tak więc, gdy zmienna substring nie jest łańcuchem

pustym, sprawdzamy, czy

ścieżka dostępu kończy się ukośnikiem (prawym lub

lewym). Je

śli nie, dodajemy ukośnik na koniec łańcucha po czym dołączamy

ła

ńcuch na koniec zmiennej lista.

Dla lepszego zrozumienia działania funkcji, w poni

ższej tabeli podano 7 przykładów

jej wywołania. Poszczególne wiersze tabeli zawieraj

ą:

ustawienie zmiennej systemowej path_x,

warto

ść zwrotną funkcji getenv,

warto

ść zwrotną funkcji RETURN_PATH.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

646

Tabela 15.2. Przykłady wywołania funkcji RETURN_PATH

brak ustawienia zmiennej path_1
(getenv "path_1")

=> nil

(setq s1 (RETURN_PATH "path_1"))

=> nil

set path_2=
(getenv "path_2")

=> nil

(setq s2 (RETURN_PATH "path_2"))

=> nil

set path_3=c:\kat_1
(getenv "path_3")

=> "c:\\kat_1"

(setq s3 (RETURN_PATH "path_3"))

=> ("c:\\kat_1\\")

set path_4=c:\kat_1;c:\kat_2
(getenv "path_4")

=> "c:\\kat_1;c:\\kat_2"

(setq s4 (RETURN_PATH "path_4"))

=> ("c:\\kat_1\\" "c:\\kat_2\\")

set path_5=c:\kat_1\;c:\kat_2\
(getenv "path_5")

=> "c:\\kat_1\\;c:\\kat_2\\"

(setq s5 (RETURN_PATH "path_5"))

=> ("c:\\kat_1\\" "c:\\kat_2\\")

set path_6=c:/kat_1/;c:/kat_2/
(getenv "path_6")

=> "c:/kat_1/;c:kat_2/"

(setq s6 (RETURN_PATH "path_6"))

=> ("c:/kat_1/" "c:/kat_2/")

set path_7=c:\kat_1;c:\kat_1\temp;c:\kat_2;c:\kat_2\temp
(getenv "path_7")

=> "c:\\kat_1;c:\\kat1\\temp;c:\\kat_2;c:\\kat_2\\temp"

(setq s7 (RETURN_PATH "path_7"))

=> ("c:\\kat_1\\" "c:\\kat_1\\temp\\" "c:\\kat_2\\"

"c:\\kat_2\\temp\\")

Plik, czyli ł

ącze między programem a komputerem, otwiera się za pomocą funkcji

open, korzystaj

ąc ze składni pokazanej poniżej:

(setq plik (open filename mode))

background image

647

BvupMJTQ!—!qsbluzd{oz!lvst

Pierwszy z argumentów funkcji open — filename (nazwa_pliku) — jest ła

ńcuchem

zawier

ącym nazwę pliku (wraz z rozszerzeniem i ew. ścieżką dostępu), która musi

spełnia

ć konwencje związane z nazywaniem plików obowiązujące w danym kompu-

terze (systemie operacyjnym). W systemie DOS jej długo

ść nie może przekroczyć 8

znaków z opcjonalnym, co najwy

żej trzyznakowym rozszerzeniem. Aby dane wyjścio-

we wydrukowa

ć zamiast wysłać je do pliku na dysku, trzeba jako nazwy pliku użyć

"LPT1" lub "PRN" (w cudzysłowach). W ten sposób dane b

ędą automatucznie

wysyłane na drukark

ę.

Drugi argument funkcji open — mode (tryb) — jest ła

ńcuchem określającym typ

operacji, któr

ą będziemy wykonywać na pliku (koniecznie małe litery). Może to być:

"r" Wskazuje,

że mamy zamiar odczytać informacje z pliku do komputera. Jeśli

plik nie istnieje jeszcze na dysku, to wyst

ąpi błąd wykonania programu.

"w" Wskazuje,

że mamy zamiar zapisać dane na dysku lub drukarce. Jeśli plik

jeszcze nie istnieje, to system operacyjny go utworzy. Je

śli jednak plik już jest

na dysku, to wszystkie zawarte w nim informacje zostan

ą zatarte.

"a" Wskazuje,

że mamy zamiar dodać dane do końca pliku. Jeśli plik jeszcze nie

istnieje, to system operacyjny go utworzy. Je

śli plik już jest na dysku, to

wyprowadzane dane zostan

ą dodane na koniec pliku, bez zacierania jego

zawarto

ści.

Przykładowo, poni

ższy zapis:

(setq plik (open "obudowa1.dat" "r"))

otwiera plik OBUDOWA1.DAT do odczytu, umo

żliwiając dostęp do jego zawartości dla

funkcji Wej

ścia/Wyjścia AutoLISPu. Funkcja open zwraca deskryptor pliku, który jest

przeznaczony do wykorzystywania przez inne funkcje Wej

ścia/Wyjścia. Z tego

wzgl

ędu musi być on przypisany do symbolu za pomocą funkcji setq (w naszym

przykładzie deskryptor pliku podstawiany jest pod zmiann

ą plik).

Po zapisaniu lub odczytaniu danych z pliku trzeba zamkn

ąć połączenie między plikiem

a komputerem. W tym celu korzysta si

ę z funkcji close o składni:

(close

file-desc)

Zamkni

ęcie pliku upewnia nas, że wszystkie informacje w buforze zostały zapisane

w pliku. Je

śli zakończymy program przed zamknięciem pliku, to każda nie zapisana

informacja b

ędąca ciągle w buforze może nie zostać wyprowadzona i w konsekwencji

stracona. Znak ko

ńca pliku może nie zostać poprawnie wstawiony, wskutek czego sys-

tem operacyjny nie b

ędzie mógł w późniejszym czasie uzyskać dostępu do pliku.

Oprócz tego po zamkni

ęciu pliku możemy zwolnić wskaźnik do pliku, którego można

wobec tego u

żyć do innego pliku.

Ka

żda funkcja współpracująca z plikiem powinna zawierać następujące instrukcje, jak

poni

ższa przykładowa sekwencja:

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

648

(setq plik (open nazwa_pliku tryb))

;otwarcie pliku

.....

;przetwarzanie pliku

(close plik)

;zamkniecie pliku

Otwarcie pliku mo

że być rozumiane jako nawiązanie połączenia z wybranym plikiem

w celu umo

żliwienia przepływu strumienia danych, natomiast zamknięcie pliku jako

przerwanie tego poł

ączenia. Liczba jednocześnie otwartych plików uzależniona jest od

szczegółów zwi

ązanych z otoczeniem programu (np. ograniczeń narzuconych przez

wykorzystywany system operacyjny lub takie czy inne jego skonfigurowanie).

Dane mo

żna przenosić do i z plików na różne sposoby:

Aby zapisa

ć dane w pliku lub na drukarce pojedynczo znak po znaku,

korzystamy z funkcji write-char.

Aby odczyta

ć dane z pliku pojedynczo znak po znaku, korzystamy z funkcji

read-char.

Aby zapisa

ć dane w pliku lub na drukarce łańcuchami (wierszami), korzystamy

z funkcji write-line.

Aby odczyta

ć dane z pliku łańcuchami (wierszami), korzystamy z funkcji read-line.

Aby zapisa

ć sformatowane znaki, łańcuchy i liczby, korzystamy z funkcji

PRINTF, SPRINTF lub FPRINTF, zawartych w pliku PRINTF.LLB. Plik ten
pochodzi z pakietu SDK2 (Software Developer's Kit) i znajduje si

ę na

doł

ączonej do książki dyskietce.

Aby odczyta

ć sformatowane znaki, łańcuchy i liczby, korzystamy z funkcji

SSCANF, zawartej w pliku SCANF1.LLB.

Je

śli chcemy zapisać dane w pliku, mamy do dyspozycji następujące funkcje: write-

char, write-line, princ, prin1, print lub funkcje grupy PRINTF. Plik otwieramy albo
w trybie do zapisu ("w"), albo w trybie dopisywania ("a"). Poni

żej przedstawiono

przykłady zastosowa

ń poszczególnych funkcji.

26/5/2/![b

26/5/2/![b

26/5/2/![b

26/5/2/![bqjt!ebozd

qjt!ebozd

qjt!ebozd

qjt!ebozdi!qpkfez

i!qpkfez

i!qpkfez

i!qpkfezod{p!{obl!qp!{oblv

od{p!{obl!qp!{oblv

od{p!{obl!qp!{oblv

od{p!{obl!qp!{oblv

Przenoszenie danych po jednym znaku na raz to najbardziej podstawowa forma operacji
na pliku. Nie jest to pewnie najpraktyczniejszy sposób post

ępowania z informacją, ale

mo

że pokazać jak korzystać z plików. Na przykład poniższy program zapisuje

wprowadzane znaki w pliku, dopóki nie naci

śniemy spacji lub klawisza Enter.

;*************************************************PROG_113
;Przyklad uzycia funkcji READ-CHAR i WRITE-CHAR.
;Test zapisu do pliku znak po znaku.

background image

649

BvupMJTQ!—!qsbluzd{oz!lvst

;Koniec zapisu - Enter lub spacja.
;Zapis do pliku $FILE_01.DAT.
;
;-------------------------------------------------
;
(defun ZAPISZ_DO_PLIKU_ZNAKAMI

(/ plik file_desc jeszcze1 znak)

(progn

;----------

(setq

plik "$file_01.dat"
file_desc (open plik "w")

);setq

;
(if (= file_desc nil)

(progn

(princ

(strcat

"\nNie mona otworzyc pliku "
plik
" do zapisu."
"\nPrzerwanie wykonywania funkcji."

);strcat

);princ

);progn

;

(progn

;else

(setq jeszcze1 T)
;

(while jeszcze1

(progn

;----------
(princ "Wprowadz znak ")
(princ "[ENTER lub spacja - koniec]: ")

(setq znak (read-char))

(if (= znak 10)

(progn

(setq jeszcze1 nil)

);progn
;
(progn

;else

(write-char znak file_desc)
(OPROZNIJ_BUFOR)

);progn

);if

;----------

);progn

);while jeszcze1

;
(close file_desc)

);progn

);if
;----------
(princ)

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

64:

;----------

);progn

);ZAPISZ_DO_PLIKU_ZNAKAMI
;
;-------------------------------------------------
;Funkcja oproznia bufor klawiatury umozliwiajac
;kolejny odczyt funkcja READ-CHAR.
;
(defun OPROZNIJ_BUFOR ()

(progn

;----------
(while (/= (read-char) 10)

(progn

;----------
;nie rob nic
;----------

);progn

);while
;----------
(princ)
;----------

);progn

);OPROZNIJ_BUFOR
;
;-------------------------------------------------
;
(defun C:TEST ()

(progn

;----------
(ZAPISZ_DO_PLIKU_ZNAKAMI)
(princ)
;----------

);progn

);C:TEST
;
;-------------------------------------------------
;
(princ "\Program zaladowany. ")
(princ "Komenda TEST uruchamia testowanie.")
(princ)
;
;*************************************************KONIEC

Wykonanie programu mo

że być następujące:

Command: (load "prog_113")

↵↵

Program zaladowany. Komenda TEST uruchamia testowanie.

Command: test

↵↵

Wprowadz znak [ENTER lub spacja - koniec]: T

↵↵

Wprowadz znak [ENTER lub spacja - koniec]: e

↵↵

Wprowadz znak [ENTER lub spacja - koniec]: s

↵↵

Wprowadz znak [ENTER lub spacja - koniec]: t

↵↵

Wprowadz znak [ENTER lub spacja - koniec]: zapisu

↵↵

background image

651

BvupMJTQ!—!qsbluzd{oz!lvst

Wprowadz znak [ENTER lub spacja - koniec]: do

↵↵

Wprowadz znak [ENTER lub spacja - koniec]: pliku

↵↵

Wprowadz znak [ENTER lub spacja - koniec]:

↵↵

Command:

Zawarto

ść pliku $FILE_01.DAT będzie następująca:

Testzdp

Omówmy teraz wyró

żnione linie i bloki programu.

W bloku tym podstawiamy pod zmienną plik nazwę pliku, w którym będziemy

zapisywa

ć wprowadzone dane. Następnie otwieramy plik do zapisu oraz podsta-

wiamy warto

ść zwrotną funkcji open pod zmienną file_desc.

Ten blok instrukcji jest wykonywany wówczas, jeżeli wystąpił błąd otwarcia

pliku. Wypisujemy wówczas odpowiedni komunikat w obszarze komend oraz
ko

ńczymy działanie funkcji.

Ten blok instrukcji jest wykonywany wówczas, gdy funkcja open zwróciła

deskryptor pliku (plik został otwarty do zapisu).

W bloku tym wchodząc w pętlę while, rozpoczynamy pobieranie i przetwarzanie

znaków wpisanych przez u

żytkownika.

Wykorzystując funkcję read-char pobieramy ciąg znaków z klawiatury i wybie-

ramy pierwszy znak z ci

ągu, podstawiając go pod zmienną znak.

W bloku tym badamy, czy został wprowadzony znak spacji lub ENTER.

Zarówno spacja, jak i ENTER daje w funkcji read-char ten sam kod znaku
równy 10.

Je

śli kod wprowadzonego znaku jest równy 10, ustawiamy zmienną jeszcze1 na

nil, umo

żliwiając tym samym wyjście z pętli while.

Je

śli kod wprowadzonego znaku jest różny od 10, zapisujemy znak do pliku

wykorzystuj

ąc funkcję write-char, a następnie czyścimy bufor klawiatury przy

pomocy funkcji OPROZNIJ_BUFOR.

Ko

ńcząc omawianie programu, należy jeszcze powiedzieć parę zdań na temat celowości

stosowania funkcji OPROZNIJ_BUFOR. Funkcja read-char odczytuje jeden znak
z wej

ściowego bufora klawiatury lub z otwartego pliku o podanym deskryptorze i zwra-

ca kod ASCII odczytanego znaku. Je

żeli wejściowy bufor klawiatury jest pusty, to

read-char czeka na wprowadzenie czegokolwiek z klawiatury i naci

śnięcie klawisza

ENTER. Przykładowo, je

żeli bufor klawiatury jest pusty, to

Command: (read-char)

↵↵

oczekuje na wprowadzenie dowolnego ła

ńcucha znaków zakończonego spacją lub

ENTER. Je

żeli zostanie teraz wpisane słowo TEST, zakończone spacją lub ENTER, to

read-char zwróci 84 (kod ASCII litery T). Nast

ępne cztery wywołania read-char

dadz

ą odpowiednio 69, 83, 84 i 10 (kod znaku nowej linii). Po kolejnym wywołaniu

funkcji read-char nast

ąpi ponowne oczekiwanie na wprowadzenie znaków.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

652

Poniewa

ż w programie użytkownik powinien wprowadzić każdorazowo jeden znak, aby

uchroni

ć się od przypadku pełnego bufora klawiatury przy kolejnym wywołaniu funkcji

read-char, zbudowano funkcj

ę OPROZNIJ_BUFOR, której zadaniem jest opróźnie-

nie bufora klawiatury. Funkcja read-char jest w niej wywoływana tak długo, dopóki
nie zwróci znaku nowej linii. Dlatego podanie przez u

żytkownika wyrazów zapisu

↵↵

do

↵↵

pliku

↵↵

spowodowało zapis w pliku liter zdp oraz automatyczne wyczyszczenie

bufora klawiatury po ka

żdym ciągu znaków.

Niedogodno

ści stosowania funkcji read-char są następujące:

brak mo

żliwości zapisu poszczególnych wyrazów (tj. umieszczania spacji

pomi

ędzy wyrazami),

brak mo

żliwości przejścia do nowej linii.

2

22

26/5/3/![bqjt!

6/5/3/![bqjt!

6/5/3/![bqjt!

6/5/3/![bqjt!ebozdi!1b2d

ebozdi!1b2d

ebozdi!1b2d

ebozdi!1b2dvdibnj

vdibnj

vdibnj

vdibnj

Zapis oraz odczyt danych ła

ńcuchami stanowi podstawowy typ operacji na plikach.

Przy zapisie do pliku danych ła

ńcuchami możemy wykorzystać następujące funkcje:

princ, prin1, write-line oraz FPRINTF. Poni

żej przedstawiono przykład zapisu do

pliku z wykorzystaniem funkcji write-line.

Funkcja ta ma format:

(write-line

string [file-desc])

Funkcja zapisuje ła

ńcuch alfanumeryczny string na ekranie lub do otwartego pliku wska-

zywanego przez deskryptor file-desc. Funkcja automatycznie dodaje znak nowej linii.

;*************************************************PROG_114
;Przyklad uzycia funkcji READ-LINE i WRITE-LINE.
;Test zapisu do pliku wierszami.
;Po kazdym wierszu dodawany jest automatycznie
;znak nowej linii.
;Koniec zapisu - nacisniecie klawisza F2 a potem Enter.
;Zapis do pliku $FILE_02.DAT.
;
;-------------------------------------------------
;
(defun ZAPISZ_DO_PLIKU_WIERSZAMI

(/ plik file_desc wiersz)

(progn

;----------
(setq

plik "$file_02.dat"
file_desc (open plik "w")

);setq
;
(if (= file_desc nil)

(progn

(princ

background image

653

BvupMJTQ!—!qsbluzd{oz!lvst

(strcat

"\nNie mona otworzyc pliku "
plik
" do zapisu."
"\nPrzerwanie wykonywania funkcji."

);strcat

);princ

);progn
;
(progn

;else

(setq jeszcze T)
;

(while jeszcze

(progn

;----------
(princ "Wprowadz wiersz tekstu ")
(princ "[F2 i Enter - koniec]: ")

(setq wiersz (read-line))

(if (= wiersz "\274")

(progn

(setq jeszcze nil)

);progn
;
(progn

;else

(write-line wiersz file_desc)

);progn

);if

;----------

);progn

);while jeszcze
;
(close file_desc)

);progn

);if
;----------
(princ)
;----------

);progn

);ZAPISZ_DO_PLIKU_WIERSZAMI
;
;-------------------------------------------------
;
(defun C:TEST ()

(progn

;----------
(ZAPISZ_DO_PLIKU_WIERSZAMI)
(princ)
;----------

);progn

);C:TEST
;
;-------------------------------------------------
;
(princ "\Program zaladowany. ")

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

654

(princ "Komenda TEST uruchamia testowanie.")
(princ)
;
;*************************************************KONIEC

Wykonanie powy

ższego programu może być następujące:

Command: (load "prog_114")

↵↵

Program zaladowany. Komenda TEST uruchamia testowanie.

Command: test

↵↵

Wprowadz wiersz tekstu [F2 i Enter - koniec]: Test zapisu

wiersza 1

↵↵

Wprowadz wiersz tekstu [F2 i Enter - koniec]: Test zapisu

wiersza 2

↵↵

Wprowadz wiersz tekstu [F2 i Enter - koniec]: Test zapisu

wiersza 3

↵↵

Wprowadz wiersz tekstu [F2 i Enter - koniec]: F2

↵↵

Command:

Zawarto

ść pliku $FILE_02.DAT będzie następująca:

Test zapisu wiersza 1
Test zapisu wiersza 2
Test zapisu wiersza 3

Omówmy teraz wyró

żnione linie i bloki programu:

Wchodzimy w pętlę while — rozpoczynamy pobieranie i przetwarzanie wpro-

wadzonych linii tekstu.

Wykorzystując funkcję read-line pobieramy kolejny wiersz tekstu.
Jeśli użytkownik nacisnął klawisz F2 a po nim Enter, przerywamy działanie

funkcji, w przeciwnym wypadku zapisujemy wprowadzony wiersz do pliku wy-
korzystuj

ąc funkcję write-line.

Przedstawione powy

żej przykłady użycia funkcji write-char oraz write-line pokazują

nam sposoby zapisu danych do pliku, gdzie dane podaje bezpo

średnio użytkownik.

Najcz

ęściej jednak dane do zapisu są przygotowywane przez poszczególne funkcje na

podstawie danych podanych przez u

żytkownika, odczytanych z pliku, obliczonych przez

funkcje programu itp. Przykładem takiego zbioru danych niech b

ędzie zapis konstrukcji

dla programu obliczeniowego metod

ą elementów skończonych. Zbiór danych wejścio-

wych dla programu obliczeniowego ma zazwyczaj budow

ę modułową, gdzie poszcze-

gólne moduły odzwierciedlaj

ą zapis matematyczny modelu konstrukcji. Najważniejszymi

modułami opisuj

ącymi konstrukcję są moduły: węzły, elementy oraz charakterystyki

elementów, z których to modułów zajmiemy si

ę dokładnie dwoma pierwszymi.

Przystosowanie programu AutoCAD do budowy siatki MES polega na budowie modelu
konstrukcji oraz jego utwierdzeniu i obci

ążeniu. Zbiorem wyjściowym z programu jest

zbiór tekstowy ASCII w formacie wymaganym przez dany program obliczeniowy MES.
Program pracuj

ący w środowisku AutoCADa musi mieć również możliwość wczytania

tak utworzonego zbioru i odtworzenia na jego podstawie modelu konstrukcji.

background image

655

BvupMJTQ!—!qsbluzd{oz!lvst

Poni

żej podano format zbioru danych dla programu metody elementów skończonych

PAFEC FE. Nie jest to jeszcze zbiór kompletny, jest on jednak wystarczaj

ący do poka-

zania sposobu zapisu w

ęzłów i elementów do pliku.

C
C
CONTROL
PHASE=9
STRESS
CONTROL.END
C
C
NODES
NODE.NUMBER

X

Y

Z

1

1000.000

2000.000

0.000

2

8000.000

6000.000

0.000

...................................

C END.OF.NODES
C
C
ELEMENTS
NUMBER

GROUP.NUMBER

ELEMENT.TYPE

PROPERTIES

TOPOLOGY

1

1

34000

1

1 2

...............................................

C END.OF.ELEMENTS
C
C
END.OF.DATA

Zbiór danych ma budow

ę modułową. Koniec zbioru zaznaczony jest przez linię

END.OF.DATA — dane znajduj

ące się poniżej tej linii nie będą brane pod uwagę.

Komentarze zaczynaj

ą się od litery C, po której następuje co najmniej jedna spacja.

Koniec modułu zaznaczony jest lini

ą C END.OF.module_name np. dla modułu NODES

jest to linia C END.OF.NODES. Moduł NODES (w

ęzły) składa się z numeru węzła

oraz jego współrz

ędnych podanych w układzie globalnym. Moduł ELEMENTS (ele-

menty) składa si

ę z numeru elementu, jego grupy, typu (belka, płyta, powłoka, element

3-d), wła

ściwości oraz topologii (numery węzłów, na których rozpięty jest element).

Dla potrzeb budowy modelu siatki MES pod AutoCADem dane o w

ęzłach oraz ele-

mentach składowane s

ą na dwóch globalnych listach glob_lista_wezlow oraz glob

_lista_elementow. Podczas zapisu zbioru danych odpowiednie warto

ści z tych list (nie

wszystkie) s

ą pobierane, formatowane do odpowiedniej postaci i zapisywane do pliku.

Struktura danych siatki MES w programie AutoCAD przedstawia si

ę następująco:

przykładowe dane dla pojedynczego w

ęzła

(1 "1" "2" (1.0 1.0 0.0) (0 1 5) (0) (0)
gdzie:

1

— numer w

ęzła

"1"

— identyfikator w

ęzła

"2"

— identyfikator opisu w

ęzła

(1.0 1.0 0.0)

— współrz

ędne węzła w układzie globalnym

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

656

(0 1 5)

— numery elementów przynale

żnych do węzła

(0)

— w

ęzeł nie należy do żadnego elementu

(0)

— numery utwierdze

ń w węźle

(0)

— brak utwierdze

ń w węźle

(0)

— numery obci

ążeń w węźle

(0)

— brak obci

ążeń w węźle

przykładowe dane dla pojedynczego elementu

(1 "B" "C" (2.0 4.5 0.0) 1 34000 1 1 2)
gdzie:

1

— numer elementu

"B"

— identyfikator elementu

"C"

— identyfikator opisu elementu

(2.0 4.5 0.0)

— współrz

ędne globalne środka ciężkości elementu

1

— grupa elementu

34000

— typ elementu

1

— wła

ściwości elementu

1 2

— topologia elementu

Poni

żej przedstawiono program do zapisu siatki MES. Dane w postaci list węzłów

i elementów zostały przygotowane w oparciu o model ustroju pr

ętowego (w zadaniu nie

wyst

ępują elementy płytowe).

;*************************************************PROG_115
;Przyklad zapisu do pliku wierszami z wykorzystaniem
;funkcji WRITE-LINE.
;Zapis do pliku $FILE_03.DAT.
;
;=================================================
;Funkcja zatrzymujaca realizacje programu,
;dopoki uzytkownik nie nacisnie ENTER...
;
(defun CZEKAJ ()

(progn

;----------
(getstring "\nNacisnij ENTER...")
(princ)
;----------

);progn

);CZEKAJ
;
;=================================================
;Funkcja dokonuje konwersji liczby calkowitej
;lub rzeczywistej na lancuch o odpowiedniej postaci.
;
;Funkcja wywolywana jest z trzema argumentami:
;value - wartosc podlegajaca konwersji
;integer - liczba miejsc czesci calkowitej
;

UWAGA

;

W przypadku blednego podania argumentu czesc

;

calkowita nie jest obcinana - patrz

background image

657

BvupMJTQ!—!qsbluzd{oz!lvst

;

przyklad wywolania nr 3

;decimal - liczba miejsc czesci ulamkowej
;
;Wartosc zwrotna funkcji:
;lancuch z liczba po konwersji
;
;Przyklady wywolania funkcji:
;(setq
;

x1

3.25

;

x2 12.5

;);setq
;(setq x1k (FORMAT_VALUE x1 5 4)) => x1k = "

3.2500"

1

;(setq x1k (FORMAT_VALUE x1 2 1)) => x1k = " 3.2"

2

;(setq x2k (FORMAT_VALUE x2 1 2)) => x2k = "12.50"

3

;
(defun FORMAT_VALUE (value integer decimal /

dl_calk liczba_spacji spaces

)

(progn

;----------
(setq dl_calk (strlen (rtos value 2 0)))
(if (< dl_calk integer)

(progn

(setq

liczba_spacji (- integer dl_calk)
spaces ""

);setq
(repeat liczba_spacji

(progn

(setq spaces (strcat spaces " "))

);progn

);repeat liczba_spacji
(setq

value (strcat

spaces (rtos value 2 decimal)

);strcat

);setq

);progn
;
(progn

;else

(setq value (rtos value 2 decimal))

);progn

);if
;----------
;wartosc zwrotna funkcji
value
;----------

);progn

);FORMAT_VALUE
;
;=================================================
;Funkcja tworzaca globalne listy wezlow i elementow.
;
(defun UTWORZ_LISTY_DANYCH ()

(progn

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

658

;----------
(setq

glob_lista_wezlow

'(

(1 "1" "2" (1.0 1.0 0.0) (0 1 5) (0) (0))
(2 "3" "4" (3.0 8.0 0.0) (0 1 2 7) (0) (0))
(3 "5" "6" (6.0 1.0 0.0) (0 2 3 5 6) (0) (0))
(4 "7" "8" (9.0 8.0 0.0) (0 3 4 7) (0) (0))
(5 "9" "A" (11.0 1.0 0.0) (0 4 6) (0) (0))
;ponizszy wezel nie jest uwzgledniony w

konstrukcji

;sluzy on jedynie do testowania zapisu do pliku
(100000 "id1" "id2"

(1000000.0 1000000.0 1000000.0) (0) (0) (0)

)

)

glob_lista_elementow

'(

(1 "B" "C" (2.0 4.5 0.0) 1 34000 1 1 2)
(2 "D" "E" (4.5 4.5 0.0) 1 34000 1 2 3)
(3 "F" "10" (7.5 4.5 0.0) 1 34000 1 3 4)
(4 "11" "12" (10.0 4.5 0.0) 1 34000 1 4 5)
(5 "13" "14" (3.5 1.0 0.0) 2 34000 2 1 3)
(6 "15" "16" (8.5 1.0 0.0) 2 34000 2 3 5)
(7 "17" "18" (6.0 8.0 0.0) 3 34000 3 2 4)

)

);setq
;----------
(princ)
;----------

);progn

);UTWORZ_LISTY_DANYCH
;
;=================================================
;Funkcja zapisujaca w pliku modul sterujacy
;programem obliczajacym.
;
(defun ZAPISZ_MODUL_CONTROL ()

(progn

;----------
(princ "\nZapis modulu CONTROL.")
(write-line

(strcat

"CONTROL\n"
"PHASE=9\n"
"STRESS\n"
"CONTROL.END"

);strcat
file_id

);write-line
(princ "

Zapisano.")

;----------
(princ)
;----------

);progn

background image

659

BvupMJTQ!—!qsbluzd{oz!lvst

);ZAPISZ_MODUL_CONTROL
;
;=================================================
;Funkcja zapisujaca w pliku dane o wezlach.
;
(defun ZAPISZ_WEZLY

(/ dlugosc licznik opis_wezla numer wspolrzedne

wsp_x wsp_y wsp_z linia

)

(progn

;----------
(if (> (length glob_lista_wezlow) 0)

(progn

;----------
(princ "\nZapis wezlow.

")

(write-line "NODES" file_id)
(write-line

"NODE.NUMBER

X

Y

Z"

file_id

);write-line
;
(setq

dlugosc (length glob_lista_wezlow)
licznik 0

);setq
(repeat dlugosc

(progn

;----------
(setq

opis_wezla (nth licznik glob_lista_wezlow)
numer (nth 0 opis_wezla)
wspolrzedne (nth 3 opis_wezla)

);setq
;
(setq numer (FORMAT_VALUE numer 5 0))
;
(setq

wsp_x (nth 0 wspolrzedne)
wsp_x (FORMAT_VALUE wsp_x 6 4)
wsp_y (nth 1 wspolrzedne)
wsp_y (FORMAT_VALUE wsp_y 6 4)
wsp_z (nth 2 wspolrzedne)
wsp_z (FORMAT_VALUE wsp_z 6 4)

);setq
;
(setq

linia ""
linia (strcat

numer
"

"

wsp_x
"

"

wsp_y
"

"

wsp_z

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

65:

);strcat

);setq
;
(write-line linia file_id)
;----------
(setq licznik (1+ licznik))
;----------

);progn

);repeat dlugosc
;
(write-line "C END.OF.NODES" file_id)
(princ "

Zapisano.")

;----------

);progn

);if
;----------
(princ)
;----------

);progn

);ZAPISZ_WEZLY
;
;=================================================
;Funkcja zapisujaca w pliku dane o elementach.
;
(defun ZAPISZ_ELEMENTY

(/ dlugosc licznik opis_elementu numer grupa typ

wlasciwosci wezel_1 wezel_2 linia

)

(progn

;----------
(if (> (length glob_lista_elementow) 0)

(progn

;----------
(princ "\nZapis elementow.

")

(write-line "ELEMENTS" file_id)
(write-line

(strcat

"NUMBER

GROUP.NUMBER

ELEMENT.TYPE

"

"PROPERTIES

TOPOLOGY"

);strcat
file_id

);write-line
;
(setq

dlugosc (length glob_lista_elementow)
licznik 0

);setq
(repeat dlugosc

(progn

;----------
(setq

opis_elementu

(nth licznik glob_lista_elementow)

numer (nth 0 opis_elementu)
numer (FORMAT_VALUE numer 6 0)

background image

661

BvupMJTQ!—!qsbluzd{oz!lvst

grupa (nth 4 opis_elementu)
grupa (FORMAT_VALUE grupa 3 0)
typ (nth 5 opis_elementu)
typ (FORMAT_VALUE typ 4 0)
wlasciwosci (nth 6 opis_elementu)
wlasciwosci (FORMAT_VALUE wlasciwosci 3 0)
wezel_1 (nth 7 opis_elementu)
wezel_1 (FORMAT_VALUE wezel_1 1 0)
wezel_2 (nth 8 opis_elementu)
wezel_2 (FORMAT_VALUE wezel_2 1 0)

);setq
;
(setq

linia ""
linia (strcat

numer
"

"

grupa
"

"

typ
"

"

wlasciwosci
"

"

wezel_1
"

"

wezel_2

);strcat

);setq
;
(write-line linia file_id)
;----------
(setq licznik (1+ licznik))
;----------

);progn

);repeat dlugosc
;
(write-line "C END.OF.ELEMENTS" file_id)
(princ "

Zapisano.")

);progn

);if
;----------
(princ)
;----------

);progn

);ZAPISZ_ELEMENTY
;
;=================================================
;Funkcja glowna do zapisu danych w pliku.
;
(defun ZAPISZ_ZBIOR_DANYCH (/ file_id)

(progn

;----------
(setq file_id (open glob_filename_dat "w"))
(write-line

(strcat

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

662

"C Zbior danych programu PAFEC FE\n"
"C przygotowany przez program AutoCAD.\n"
"C\nC"

);strcat
file_id

);write-line
(ZAPISZ_MODUL_CONTROL)
(write-line "C\nC" file_id)
(ZAPISZ_WEZLY)
(write-line "C\nC" file_id)
(ZAPISZ_ELEMENTY)
(write-line "C\nC" file_id)
(write-line "END.OF.DATA" file_id)
(close file_id)
;----------
(princ)
;----------

);progn

);ZAPISZ_ZBIOR_DANYCH
;
;=================================================
;Ten fragment programu wykonywany jest
;automatycznie po jego zaladowaniu.
;
(setq glob_filename_dat "$file_03.dat")
(UTWORZ_LISTY_DANYCH)
(textpage)
(princ "\nListy danych do zapisu.")
(princ "\n\nLista wezlow.\n")
(prin1 glob_lista_wezlow)
(princ "\n\nLista elementow.\n")
(prin1 glob_lista_elementow)
(princ "\n")
(CZEKAJ)
(ZAPISZ_ZBIOR_DANYCH)
(princ "\n")
(CZEKAJ)
(graphscr)
(princ)
;
;=================================================
;*************************************************KONIEC

Wykonanie programu b

ędzie następujące:

Command: (load "prog_115")

↵↵

Listy danych do zapisu.

Lista wezlow.
((1 "1" "2" (1.0 1.0 0.0) (0 1 5) (0) (0))(2 "3" "4" (3.0
8.0 0.0) (0 1 2 7) (0) (0))(3 "5" "6" (6.0 1.0 0.0) (0 2 3 5
6) (0) (0))(4 "7" "8" (9.0 8.0 0.0) (0 3 4 7) (0) (0))(5 "9"

background image

663

BvupMJTQ!—!qsbluzd{oz!lvst

"A" (11.0 1.0 0.0) (0 4 6) (0) (0))(100000 "id1"
"id2"(1000000.0 1000000.0 1000000.0) (0) (0) (0)))

Lista elementow.

((1 "B" "C" (2.0 4.5 0.0) 1 34000 1 1 2)(2 "D" "E" (4.5 4.5
0.0) 1 34000 1 2 3)(3 "F" "10" (7.5 4.5 0.0) 1 34000 1 3
4)(4 "11" "12" (10.0 4.5 0.0) 1 34000 1 4 5)(5 "13" "14"
(3.5 1.0 0.0) 2 34000 2 1 3)(6 "15" "16" (8.5 1.0 0.0) 2
34000 2 3 5)(7 "17" "18" (6.0 8.0 0.0) 3 34000 3 2 4))

Nacisnij ENTER...

↵↵

Zapis modulu CONTROL.

Zapisano.

Zapis wezlow.

Zapisano.

Zapis elementow.

Zapisano.

Nacisnij ENTER...

↵↵

Command:

Zawarto

ść pliku $FILE_03.DAT będzie następująca:

C Zbior danych programu PAFEC FE
C przygotowany przez program AutoCAD.
C
C
CONTROL
PHASE=9
STRESS
CONTROL.END
C
C
NODES
NODE.NUMBER

X

Y

Z

1

1.0000

1.0000

0.0000

2

3.0000

8.0000

0.0000

3

6.0000

1.0000

0.0000

4

9.0000

8.0000

0.0000

5

11.0000

1.0000

0.0000

100000

1000000.0000

1000000.0000

1000000.0000

C END.OF.NODES
C
C
ELEMENTS
NUMBER

GROUP.NUMBER

ELEMENT.TYPE

PROPERTIES

TOPOLOGY

1

1

34000

1

1

2

2

1

34000

1

2

3

3

1

34000

1

3

4

4

1

34000

1

4

5

5

2

34000

2

1

3

6

2

34000

2

3

5

7

3

34000

3

2

4

C END.OF.ELEMENTS

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

664

C
C
END.OF.DATA

Program składa si

ę z następujących funkcji:

D[FLBK

D[FLBK

D[FLBK

D[FLBK

Funkcja zatrzymuje realizacj

ę programu do czasu naciśnięcia klawisza ENTER.

GPSNBU

GPSNBU

GPSNBU

GPSNBU`WBMVF

`WBMVF

`WBMVF

`WBMVF

Funkcja dokonuje konwersji liczby całkowitej lub rzeczywistej na ła

ńcuch o odpo-

wiedniej postaci. W porównaniu z funkcj

ą rtos ma tę zaletę, że możemy dodać spacje

przed cz

ęść całkowitą, uzyskując dla różnych liczb tę samą długość łańcucha. Poniżej

podano kilka wywoła

ń funkcji format_value oraz rtos.

(FORMAT_VALUE 1.25 5 2)

=>

"

1.25"

(rtos 1.25 2 2)

=>

"1.25"

(FORMAT_VALUE 300.123 3 0)

=>

"300"

(rtos 300.123 2 0)

=>

"300"

(FORMAT_VALUE 1250.5 1 4)

=>

"1250.5000"

(rtos 1250.5 1 4)

=>

"1250.5000"

(FORMAT_VALUE -10.75 6 4)

=>

"

-10.7500"

(rtos -10.75 2 4)

=>

"-10.7500"

VU

VU

VU

VUXPS[`MJ

XPS[`MJ

XPS[`MJ

XPS[`MJTUZ`EBOZ

TUZ`EBOZ

TUZ`EBOZ

TUZ`EBOZDI

DI

DI

DI

Funkcja tworzy globalne listy w

ęzłów i elementów.

[BQJT[`

[BQJT[`

[BQJT[`

[BQJT[`NPEVM`

NPEVM`

NPEVM`

NPEVM`DPOUSPM

DPOUSPM

DPOUSPM

DPOUSPM

Funkcja zapisuje w pliku moduł steruj

ący programem obliczeniowym.

[BQJT[`X

[BQJT[`X

[BQJT[`X

[BQJT[`XF[MZ

F[MZ

F[MZ

F[MZ

Funkcja zapisuje w pliku moduł danych o w

ęzłach.

[BQJ

[BQJ

[BQJ

[BQJT[`FMFNFO

T[`FMFNFO

T[`FMFNFO

T[`FMFNFOUZ

UZ

UZ

UZ

Funkcja zapisuje w pliku moduł danych o elementach.

background image

665

BvupMJTQ!—!qsbluzd{oz!lvst

[BQJT[`[

[BQJT[`[

[BQJT[`[

[BQJT[`[CJPS`EB

CJPS`EB

CJPS`EB

CJPS`EBOZDI

OZDI

OZDI

OZDI

Funkcja główna do zapisu danych w pliku, wywołuj

ąca funkcje do zapisu poszcze-

gólnych modułów.

Funkcje do zapisu w

ęzłów i elementów działają według następującego algorytmu:

w p

ętli repeat przeglądaj listy węzłów (elementów),

pobierz opis kolejnego w

ęzła (elementu),

wybierz warto

ści, które mają się pojawić w zbiorze danych,

warto

ści numeryczne przekształć na łańcuchy o odpowiedniej długości,

utwórz linie danych, ł

ącząc ze sobą wybrane łańcuchy przedzielone odpowiednią

ilo

ścią spacji,

zapisz linie danych w pliku.

26/5/

26/5/

26/5/

26/5/4/![bqjt!ebo

4/![bqjt!ebo

4/![bqjt!ebo

4/![bqjt!ebozdi!x!qptu

zdi!x!qptu

zdi!x!qptu

zdi!x!qptubdj!mjtuz

bdj!mjtuz

bdj!mjtuz

bdj!mjtuz

Poni

żej przedstawiono program zapisujący wszystkie dane w postaci jednej listy. Tak

utworzony zbiór danych nie mo

że być bezpośrednio wczytany przez program PAFEC

FE, jest to jednak przykład na zapis zbioru danych w postaci innej ni

ż w poprzednim

zadaniu.

;*************************************************PROG_116
;Przyklad zapisu do pliku informacji, ktore przed
;zapisem umieszczane sa na jednej liscie.
;Zapis do pliku $FILE_04.DAT.
;
;=================================================
;Funkcja zatrzymujaca realizacje programu,
;dopoki uzytkownik nie nacisnie ENTER...
;
(defun CZEKAJ ()

(progn

;----------
(getstring "\nNacisnij ENTER...")
(princ)
;----------

);progn

);CZEKAJ
;
;=================================================
;Funkcja tworzaca globalne listy wezlow i elementow.
;
(defun UTWORZ_LISTY_DANYCH ()

(progn

;----------
(setq

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

666

glob_lista_wezlow

'(

(1 "1" "2" (1.0 1.0 0.0) (0 1 5) (0) (0))
(2 "3" "4" (3.0 8.0 0.0) (0 1 2 7) (0) (0))
(3 "5" "6" (6.0 1.0 0.0) (0 2 3 5 6) (0) (0))
(4 "7" "8" (9.0 8.0 0.0) (0 3 4 7) (0) (0))
(5 "9" "A" (11.0 1.0 0.0) (0 4 6) (0) (0))
;ponizszy wezel nie jest uwzgledniony w

konstrukcji

;sluzy on jedynie do testowania zapisu do pliku
(100000 "id1" "id2"

(1000000.0 1000000.0 1000000.0) (0) (0) (0)

)

)

glob_lista_elementow

'(

(1 "B" "C" (2.0 4.5 0.0) 1 34000 1 1 2)
(2 "D" "E" (4.5 4.5 0.0) 1 34000 1 2 3)
(3 "F" "10" (7.5 4.5 0.0) 1 34000 1 3 4)
(4 "11" "12" (10.0 4.5 0.0) 1 34000 1 4 5)
(5 "13" "14" (3.5 1.0 0.0) 2 34000 2 1 3)
(6 "15" "16" (8.5 1.0 0.0) 2 34000 2 3 5)
(7 "17" "18" (6.0 8.0 0.0) 3 34000 3 2 4)

)

);setq
;----------
(princ)
;----------

);progn

);UTWORZ_LISTY_DANYCH
;
;=================================================
;Funkcja zapisujaca dane w jednej liscie
;
(defun ZAPISZ_ZBIOR_DANYCH

(/ file_id modul_control lista_wezlow dlugosc licznik

opis_wezla numer wspolrzedne lista_elementow
opis_elementu grupa typ wlasciwosci wezel_1
wezel_2 lista_wspolna

)

(progn

;----------
(setq file_id (open glob_filename_dat "w"))
;
;utworzenie listy modulu CONTROL

(setq

modul_control

(list

'CONTROL
"CONTROL"
"PHASE=9"
"STRESS"
"CONTROL.END"

);list

background image

667

BvupMJTQ!—!qsbluzd{oz!lvst

);setq

;
;utworzenie listy wezlow

(setq lista_wezlow (list 'NODES))

(if (> (length glob_lista_wezlow) 0)

(progn

;----------
(setq

dlugosc (length glob_lista_wezlow)
licznik 0

);setq
(repeat dlugosc

(progn

;----------
(setq

opis_wezla (nth licznik glob_lista_wezlow)
numer (nth 0 opis_wezla)
wspolrzedne (nth 3 opis_wezla)
opis_wezla (list numer wspolrzedne)
lista_wezlow

(append lista_wezlow (list opis_wezla))

);setq
;----------
(setq licznik (1+ licznik))
;----------

);progn

);repeat dlugosc
;----------

);progn

);if

;
;utworzenie listy elementow

(setq lista_elementow (list 'ELEMENTS))

(if (> (length glob_lista_elementow) 0)

(progn

;----------
(setq

dlugosc (length glob_lista_wezlow)
licznik 0

);setq
(repeat dlugosc

(progn

;----------
(setq

opis_elementu

(nth licznik glob_lista_elementow)

numer (nth 0 opis_elementu)
grupa (nth 4 opis_elementu)
typ (nth 5 opis_elementu)
wlasciwosci (nth 6 opis_elementu)
wezel_1 (nth 7 opis_elementu)
wezel_2 (nth 8 opis_elementu)
opis_elementu

(list

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

668

numer
grupa
typ
wlasciwosci
wezel_1
wezel_2

);list

lista_elementow

(append lista_elementow (list

opis_elementu))

);setq
;----------
(setq licznik (1+ licznik))
;----------

);progn

);repeat dlugosc
;----------

);progn

);if

;
;utworzenie wspolnej listy danych

(setq

lista_wspolna

(list

modul_control
lista_wezlow
lista_elementow

);list

);setq

;
;zapis wspolnej listy danych

(princ "'" file_id)

(prin1 lista_wspolna file_id)

;
(close file_id)
;----------
(princ)
;----------

);progn

);ZAPISZ_ZBIOR_DANYCH
;
;=================================================
;Ten fragment programu wykonywany jest
;automatycznie po jego zaladowaniu.
;
(setq glob_filename_dat "$file_04.dat")
(UTWORZ_LISTY_DANYCH)
(textpage)
(princ "\nListy danych do zapisu.")

(princ "\n\nLista wezlow.\n")
(prin1 glob_lista_wezlow)
(princ "\n\nLista elementow.\n")
(prin1 glob_lista_elementow)
(princ "\n")

background image

669

BvupMJTQ!—!qsbluzd{oz!lvst

(CZEKAJ)
(princ "Zapis zbioru danych.")
(ZAPISZ_ZBIOR_DANYCH)
(princ "

Zapisano.")

(CZEKAJ)
(graphscr)
(princ)
;
;=================================================
;*************************************************KONIEC

Wykonanie programu b

ędzie następujące:

Command: (load "prog_116")

↵↵

Listy danych do zapisu.

Lista wezlow.
((1 "1" "2" (1.0 1.0 0.0) (0 1 5) (0) (0))(2 "3" "4" (3.0
8.0 0.0) (0 1 2 7) (0) (0))(3 "5" "6" (6.0 1.0 0.0) (0 2 3 5
6) (0) (0))(4 "7" "8" (9.0 8.0 0.0) (0 3 4 7) (0) (0))(5 "9"
"A" (11.0 1.0 0.0) (0 4 6) (0) (0))(100000 "id1"
"id2"(1000000.0 1000000.0 1000000.0) (0) (0) (0)))

Lista elementow.

((1 "B" "C" (2.0 4.5 0.0) 1 34000 1 1 2)(2 "D" "E" (4.5 4.5
0.0) 1 34000 1 2 3)(3 "F" "10" (7.5 4.5 0.0) 1 34000 1 3
4)(4 "11" "12" (10.0 4.5 0.0) 1 34000 1 4 5)(5 "13" "14"
(3.5 1.0 0.0) 2 34000 2 1 3)(6 "15" "16" (8.5 1.0 0.0) 2
34000 2 3 5)(7 "17" "18" (6.0 8.0 0.0) 3 34000 3 2 4))

Nacisnij ENTER...

↵↵

Zapis zbioru danych.

Zapisano.

Nacisnij ENTER...

↵↵

Command:

Z uwagi na to,

że wszystkie dane w zbiorze $FILE_04.DAT zapisane są w jednej linii,

nie podam w tym miejscu wydruku pliku danych.

Omówmy teraz wyró

żnione linie i bloki programu.

Tworzymy listę modułu CONTROL o postaci

(CONTROL "CONTROL" "PHASE=9" "STRESS" "CONTROL.END")

Tworzymy listę węzłów o postaci

(NODES (1 (1.0 1.0 0.0)) ... (100000 (1000000.0 1000000.0
1000000.0)))

Tworzymy listę elementów o postaci

(ELEMENTS (1 1 34000 1 1 2) ... (6 2 34000 2 3 5))

Tworzymy wspólną listę danych o postaci

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

66:

((CONTROL ...)(NODES ...)(ELEMENTS ...))

Zapisujemy do pliku znak zapobiegający ewaluacji listy podczas wczytywania

pliku funkcj

ą load.

Zapisujemy do pliku wspólną listę danych.

26/5/5/!

26/5/5/!

26/5/5/!

26/5/5/!Gpsnbupxbo

Gpsnbupxbo

Gpsnbupxbo

Gpsnbupxboz!{bqjt!ebozd

z!{bqjt!ebozd

z!{bqjt!ebozd

z!{bqjt!ebozdi

i

i

i

Na dyskietce doł

ączonej do książki znajduje się plik PRINTF.LLB, zawierający nastę-

puj

ące funkcje:

(printf _$args)

(fprintf _$args _$var)

(sprintf _$var _$args)

Funkcje te mog

ą wyświetlać dane dowolnego typu i współpracować z wieloma

argumentami. Oprócz tego mog

ą formatować pojawiające się dane. Wartością zwrotną

ka

żdej funkcji jest sformatowany łańcuch lub nil w przypadku błędu. Funkcje te umie-

szczaj

ą sformatowane dane w różnych miejscach, co zbiorczo przedstawiono poniżej.

Funkcja

Gdzie umieszcza wprowadzane dane

printf

na ekranie

fprintf

w pliku okre

ślonym argumentem _$var

sprintf

w zmiennej okre

ślonej argumentem _$var

Przy zapisie do zmiennej zmienna musi by

ć

zmienn

ą

kwotowan

ą

, np.

'x

Argument _$args wskazuje tzw. ła

ńcuch formatujący. Łańcuch ten jest taki sam, jak

ka

żdy inny łańcuch. Różnica polega na sposobie traktowania niektórych sekwencji

znaków tego ła

ńcucha przez omawiane tu funkcje. Pewne specjalne sekwencje (o któ-

rych mowa dalej) s

ą bowiem zastępowane odpowiednio (tzn. zgodnie ze wskazaniami

zawartymi w tych sekwencjach) danymi znajduj

ącymi się w parametrach nieustalonych

(tj. tych wymienionych po ła

ńcuchu formatującym) — np. w łańcuchu:

"%s ma %d lat."

sekwencja %s zostanie zast

ąpiona łańcuchem znaków wskazanym parametrem

nieustalonym, za

ś %d dziesiętną postacią kolejnego parametru nieustalonego funkcji.

Poni

żej pokazano przykład użycia funkcji printf.

background image

671

BvupMJTQ!—!qsbluzd{oz!lvst

(setq

imie "Jacek"
wiek 25

);setq
(printf '("%s ma %d lat." imie wiek))

Powy

ższe wywołanie funkcji printf spowoduje wypisanie na ekranie napisu:

Jacek

ma 25 lat.

Jak wida

ć, każdej sekwencji znaków formatujących odpowiada jeden parametr nie-

ustalony funkcji: %s — imie, %d — wiek. Zachowanie równo

ści liczby sekwencji

formatuj

ących i parametrów nieustalonych jest niezbędne dla prawidłowego działania

omawianych funkcji.

Sekwencja formatuj

ąca określa typ odpowiadającego jej parametru, wskazując tym sa-

mym omawianym funkcjom wła

ściwy sposób jego traktowania, np. napotkanie se-

kwencji %s informuje,

że odpowiedni parametr wskazuje łańcuch znaków. Zgodność

typu wskazanego sekwencj

ą formatującą z typem odpowiadającego jej parametru jest

kolejnym warunkiem niezb

ędnym dla prawidłowego działania omawianych funkcji.

Ogólny format sekwencji formatuj

ących przedstawia się następująco:

%[flagi][szeroko

ść

][.precyzja]znak-typu

Wszystkie sekwencje formatuj

ące rozpoczynają się znakiem %. Kolejne elementy określają:

flagi

— typ justowania

szeroko

ść

— liczb

ę wysyłanych znaków

precyzja

— liczb

ę cyfr znaczących

znak-typu

— typ argumentu

Omawianie kolejnych elementów sekwencji formatuj

ących rozpoczniemy od tyłu.

[o

[o

[o

[oblj!uzqv

blj!uzqv

blj!uzqv

blj!uzqv

Pole znak-typu okre

śla typ argumentu i postać, w jakiej zostanie on przedstawiony. W po-

ni

ższej tabeli przedstawiono typy akceptowane przez funkcje printf, fprintf i sprintf.

Tabela 15.3. Typ i posta

ć argumentu znak-typu funkcji grupy printf

Typ

Argument wej

ściowy

Wyprowadzana posta

ć tego argumentu po

przeformatowaniu

c

znak (ła

ńcuch lub

0<int<256)

pojedynczy znak

d

całkowity

liczba całkowita w układzie dziesi

ętnym, ze znakiem

e

zmiennoprzecinkowy

warto

ść ze znakiem przedstawiona w postaci

wykładniczej ze znakiem e dla wykładnika

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

672

Tabela 15.3. Typ i posta

ć argumentu znak-typu funkcji grupy printf (c.d.)

Typ

Argument wej

ściowy

Wyprowadzana posta

ć tego argumentu po

przeformatowaniu

E

zmiennoprzecinkowy

warto

ść ze znakiem przedstawiona w postaci

wykładniczej ze znakiem E dla wykładnika

f

zmiennoprzecinkowy

warto

ść dziesiętna ze znakiem

g

zmiennoprzecinkowy

jak typ f lub jak typ e

G

zmiennoprzecinkowy

jak typ f lub jak typ E

i

całkowity

liczba całkowita w układzie dziesi

ętnym, ze znakiem

o

całkowity

liczba całkowita w układzie ósemkowym, bez znaku

s

ła

ńcuch

znaki z ła

ńcucha

t

lista 3 liczb rzeczywistych

3 liczby rzeczywiste

u

całkowity

liczba całkowita w układzie dziesi

ętnym, bez znaku

x

całkowity

liczba całkowita w układzie szesnastkowym, bez
znaku; do jej zapisania printf u

żywa liter: a, b, c, d,

e, f

X

całkowity

liczba całkowita w układzie szesnastkowym, ze
znakiem; do jej zapisania printf u

żywa liter: A, B, C,

D, E, F

%

znak "%"

Tq

Tq

Tq

Tqfdzgjlbups!

fdzgjlbups!

fdzgjlbups!

fdzgjlbups!qsfdz{kj

qsfdz{kj

qsfdz{kj

qsfdz{kj

Pole [.precyzja] okre

śla maksymalną ilość znaków wyprowadzanego łańcucha lub ilość

cyfr po kropce wyprowadzanej liczby zmiennoprzecinkowej.

Tqfdz

Tqfdz

Tqfdz

Tqfdzgjlbups!t{fsplp

gjlbups!t{fsplp

gjlbups!t{fsplp

gjlbups!t{fsplp*dj

*dj

*dj

*dj

Pole [szeroko

ść] określa minimalną ilość znaków, które mają być wyprowadzone.

Je

żeli wynikowa wartość ma więcej znaków niż określono wyrażeniem [szerokość], to

ilo

ść znaków na wyjściu jest automatycznie, odpowiednio powiększana.

Gmbhj

Gmbhj

Gmbhj

Gmbhj

Je

żeli w polu [flagi] nie użyto znaku "–", wynik konwersji będzie wyrównany do

prawej strony i uzupełniony spacjami z lewej, je

żeli zaś użyto go — wyrównywany do

lewej strony i uzupełniony spacjami z prawej.

Argument _$args, wyst

ępujący we wszystkich trzech funkcjach, jest kwotowaną listą

dziel

ącą się na łańcuch sterujący oraz listę danych, np. '("X1 = %d, X2 = %d" x1 x2).

background image

673

BvupMJTQ!—!qsbluzd{oz!lvst

Pierwsza cz

ęść nazywa się łańcuchem sterującym lub formatującym. Łańcuch sterujący,

ten w cudzysłowie, wskazuje, gdzie maj

ą się pojawić dane w wyświetlanym wierszu.

Zawiera dowolny tekst, który chcemy wy

świetlić, wraz ze znakami-wypełniaczami,

nazwanymi specyfikatorami formatowania, wskazuj

ącymi typ i położenie danych.

Druga cz

ęść argumentu to lista danych, zawierająca wartości, stałe lub zmienne, które

chcemy wy

świetlić. Poszczególne elementy listy danych oddzielamy od siebie spacją.

Kiedy interpreter AutoLISPu tworzy ła

ńcuch wynikowy, wstawia daną z listy w miej-

scu zajmowanym przez specyfikator formatu.

Aby zapozna

ć się z funkcją printf w działaniu, proponuję przeanalizowanie kilku

przykładów zamieszczonych w poni

ższej tabeli.

Tabela 15.4. Przykłady wywołania funkcji printf

(printf '("Test dzialania funkcji PRINTF."))
Test działania funkcji PRINTF."Test dzialania funkcji
PRINTF."

Je

śli w łańcuchu sterującym nie występują specyfikatory formatu, funkcja printf działa

analogicznie do funkcji princ.

(printf '("Przejscie do nowego wiersza.\n"))
Przejscie do nowego wiersza.
"Przejscie do nowego wiersza.\n"

Funkcja printf nie dodaje automatycznie polecenia przej

ścia do nowego wiersza po

wy

świetleniu danych. Po wyświetleniu łańcucha kursor pozostaje w tym samym wierszu po

ostatnim znaku. Je

śli chcemy, aby kursor znalazł się w następnym wierszu, w łańcuchu

steruj

ącym musi znaleźć się kod \n.

(printf '("Wypisz to\nw trzech\nwierszach.\n"))
Wypisz to
w trzech
wierszach.
"Wypisz to\nw trzech\nwierszach.\n"

Kod przej

ścia do nowego wiersza \n umieszczamy w tym miejscu, w którym chcemy rozpocząć

nowy wiersz (niekoniecznie na ko

ńcu).

(setq znak "A")
(printf '("%c\n" znak))
A
"A"

Chc

ąc wyświetlić pojedynczy znak, posługujemy się kodem formatującym %c.

(printf '("%c\n" 65))
A
"A"

Zmienna typu znakowego mo

że także zostać zadeklarowana jako liczba całkowita z przedziału

od 0 do 256.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

674

Tabela 15.4. Przykłady wywołania funkcji printf (c.d.)

(printf '("Kod ASCII znaku %c wynosi %d.\n" znak (ascii
znak)))
Kod ASCII znaku A wynosi 65.
"Kod ASCII znaku A wynosi 65.\n"

Lista danych mo

że zawierać wywołania funkcji bibliotecznych AutoLISPu lub funkcji

u

żytkownika (w przykładzie wywołujemy funkcję AutoLISPu ascii). Ważne jest, aby wartość

zwrotna wywołanej funkcji była zgodna ze specyfikatorem formatu.

(setq x 123.45)
(printf '("%f\n" x))
123.4500
"123.4500"

Je

żeli w specyfikatorze formatu nie podano liczby wyświetlanych miejsc dziesiętnych, zostaną

przyj

ęte bieżące ustawienia komendy UNITS.

(printf '("%.2f\n" x))
123.45
"123.45"

Korzystaj

ąc ze specyfikatora szerokości i precyzji pola możemy dostosować sposób

wy

świetlania liczb i tekstu.

Aby okre

ślić liczbę miejsc dziesiętnych, korzystamy z formatu %.nf gdzie n jest liczbą

potrzebnych miejsc.

(printf '("%8.2f\n" x))

123.45

"

123.45"

Mo

żemy również sterować całkowitą szerokością pola — liczbą miejsc, jakie zajmie cała

wy

świetlana wartość — korzystając z formatu %N.nf gdzie N oznacza całkowitą szerokość

pola przeznaczonego na wy

świetlenie liczby (jest to suma pól części całkowitej, jednego pola

na kropk

ę oraz pól części dziesiętnej). Sama liczba 123.45 zajmuje 6 znaków — kropka

dziesi

ętna też liczy się za znak. Nie wykorzystane znaki (2 pola) pojawią się jako puste miejsce

przed liczb

ą.

(printf '("%08.2f\n" x))
00123.45
"00123.45"

Mo

żemy również dodatkową przestrzeń przed liczbą wypełnić zerami zamiast spacjami.

Osi

ągamy to dopisując 0 przed liczbą mówiącą o szerokości pola — %08.2f.

(printf '("%-8.2f\n" x))
123.45
"123.45

"

Aby wyrówna

ć wartości do lewej, tzn. umieścić je po lewej stronie pola, trzeba wstawić znak

minus po % — %-8.2f. Dodatkowe spacje pojawi

ą się po wartości.

(printf '("%-08.2f\n" x))
123.4500
"123.4500"

Je

śli zażądamy wypełnienia dodatkowych wolnych pól zerami, i jednocześnie ustawimy

lewostronne wyrównanie w polu, specyfikator precyzji pola zostanie zignorowany.

background image

675

BvupMJTQ!—!qsbluzd{oz!lvst

Tabela 15.4. Przykłady wywołania funkcji printf (c.d.)

(printf '("%2.1f\n" x))
123.5
"123.5"

Je

śli specyfikator szerokości pola jest mniejszy niż liczba cyfr całkowitych liczby, jest on

ignorowany.

(setq x1 "Test dzialania " x2 "funkcji PRINTF.")
(printf '("%s%s\n" x1 x2))
Test dzialania funkcji PRINTF.
"Test dzialania funkcji PRINTF.\n"

Ł

ączymy dwa łańcuchy podane w zmiennych x1 i x2.

(printf '("%20s%s\n" x1 x2))

Test dzialania funkcji PRINTF.

"

Test dzialania funkcji PRINTF.\n"

Ł

ączymy dwa łańcuchy podane w zmiennych x1 i x2, przy czym szerokość łańcucha w

zmiennej x1 ustawiamy na 20 pól. Wolne pola zostan

ą uzupełnione spacjami z lewej.

(printf '("%-20s%s\n" x1 x2))
Test dzialania

funkcji PRINTF.

"Test dzialania

funkcji PRINTF.\n"

Ł

ączymy dwa łańcuchy podane w zmiennych x1 i x2, przy czym szerokość łańcucha w

zmiennej x1 ustawiamy na 20 pól. Wolne pola zostan

ą uzupełnione spacjami z prawej.

(printf '("%5s%5s\n" x1 x2))
Test dzialania funkcji PRINTF.
"Test dzialania funkcji PRINTF.\n"

Je

śli specyfikatory szerokości pól są mniejsze od ich rzeczywistej szerokości, są one

ignorowane.

(printf '("%20.5s%20.7s\n" x1 x2))

Test dzialania

funkcji PRINTF.

"

Test dzialania

funkcji PRINTF.\n"

W przypadku, gdy podano specyfikatory szeroko

ści pól większe od ich rzeczywistej szerokości,

specyfikatory precyzji s

ą ignorowane.

(printf '("%10.5s%10.7s\n" x1 x2))
Test funkcji
"Test funkcji\n"

W przypadku, gdy podano specyfikatory szeroko

ści pól mniejsze od ich rzeczywistej

szeroko

ści, łańcuchy są obcinane na długość zgodną z podanymi specyfikatorami precyzji.

(printf '("%.5s%.7s\n" x1 x2))
Test funkcji
"Test funkcji\n"

Efekt działania jak wy

żej.

(setq cena 130.25)
(printf '("Cena wynosi %f nowych zlotych.\n" cena))
Cena wynosi 130.2500 nowych zlotych.
"Cena wynosi 130.2500 nowych zlotych.\n"

Przykład wł

ączenia specyfikatora formatu liczby rzeczywistej w łańcuch tekstu. Ponieważ nie

podano pola precyzja, zostan

ą przyjęte bieżące ustawienia.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

676

Tabela 15.4. Przykłady wywołania funkcji printf (c.d.)

(printf '("Cena wynosi .2f nowych zlotych.\n" cena))
Cena wynosi 130.25 nowych zlotych.
"Cena wynosi 130.25 nowych zlotych.\n"

To samo z podaniem specyfikatora precyzji.

(printf '("Cena wynosi %5f nowych zlotych.\n" cena))
Cena wynosi 130.2500 nowych zlotych.
"Cena wynosi 130.2500 nowych zlotych.\n"

Je

żeli nie podano specyfikatora formatu, minimalna wielkość pola szerokość jest równa sumie

liczby pól cz

ęści całkowitej, pola kropki oraz liczby pól części dziesiętnej.

(printf '("Cena wynosi %10.2f nowych zlotych.\n" cena))
Cena wynosi

130.25 nowych zlotych.

"Cena wynosi

130.25 nowych zlotych.\n"

W przykładzie tym rezerwujemy 10 pól na zmienn

ą rzeczywistą. Ponieważ zmienna po

przeformatowaniu zajmuje 6 pól, dodatkowe 4 spacje zostan

ą wstawione przed zmienną

zgodnie z podanym sposobem wyrównania.

(printf '("Cena wynosi %010.2f nowych zlotych.\n" cena))
Cena wynosi 0000130.25 nowych zlotych.
"Cena wynosi 0000130.25 nowych zlotych.\n"

Jak wy

żej, z żądaniem wypełnienia pustych pól zerami.

(setq x1 1.25 y1 2.5 x2 1000.0 y2 125.766)
(printf '("X1 = %10.4f Y1 = %10.4f\nX2 = %10.4f Y2 =
%10.4f\n" x1 y1 x2 y2))
X1 =

1.2500 Y1 =

2.5000

X2 =

1000.0000 Y2 =

125.7660

"X1 =

1.2500 Y1 =

2.5000\nX2 =

1000.0000 Y2 =

125.7660\n"

Przykład wyrównania liczb w kolumnach.

(printf '("%s%10.4f%10s%10.4f\n%s%10.4f%10s%10.4f\n" "X1 =
" x1 "Y1 = " y1 "X2 = " x2 "Y2 = " y2))
X1 =

1.2500

Y1 =

2.5000

X2 =

1000.0000

Y2 =

125.7660

"X1 =

1.2500

Y1 =

2.5000\nX2 =

1000.0000

Y2 =

125.7660\n"

Jak wy

żej, z dodatkowym odsunięciem kolumn. Do odsunięcia kolumn zalecam użycie spacji

zamiast znaku tabulacji.

(setq p1 '(2 4 6))
(printf '("Wspolrzedne punktu P1: %-8.2///t" "X=" "Y=" "Z="
p1)
Wspolrzedne punktu P1: X=2.00

Y=4.00

Z=6.00

"Wspolrzedne punktu P1: X=2.00

Y=4.00

Z=6.00

\n"

Wypisanie współrz

ędnych punktu z wyrównaniem lewostronnym.

(setq x1 -1.25 x2 34.0 x3 440.12)
(printf '("|%8.4f|%8.4f|%8.4f|\n" x1 x2 x3))
| -1.2500| 34.0000|440.1200|
"| -1.2500| 34.0000|440.1200|\n"

Przykład rozmieszczenia w wierszu 3 liczb rzeczywistych. Dla wi

ększej widoczności rozmiaru

pól s

ą one oddzielone od siebie znakiem "|".

background image

677

BvupMJTQ!—!qsbluzd{oz!lvst

Tabela 15.4. Przykłady wywołania funkcji printf (c.d.)

(setq x1 1 x2 34400 x3 24 x4 55)
(printf '("|%5i|%8i|

|%i| |%i|\n" x1 x2 x3 x4))

|

1|

34400|

|24| |55|

"|

1|

34400|

|24| |55|\n"

To samo dla liczb całkowitych. Dodatkowo pomi

ędzy zmienne x2 i x3 wstawiono 3 spacje,

a pomi

ędzy zmienne x3 i x4 wstawiono 1 spację.

(printf '("%8.4f" 10))
Error: real value expected.

ąd typu wartości podlegającej formatowaniu — oczekiwano na liczbę rzeczywistą.

(printf '("%i" 10.0))
Error: integer value expected.

ąd typu wartości podlegającej formatowaniu — oczekiwano na liczbę całkowitą.

Poni

żej pokazano sposób wykorzystania funkcji fprintf do zapisu zbioru danych MES

dla programu PAFEC FE.

;*************************************************PROG_117
;Przyklad zapisu do pliku wierszami z wykorzystaniem
;funkcji FPRINTF, zawartej w pliku PRINTF.LLB.
;Zapis do pliku $FILE_05.DAT.
;
;=================================================
;Funkcja zatrzymujaca realizacje programu,
;dopoki uzytkownik nie nacisnie ENTER...
;
(defun CZEKAJ ()

(progn

;----------
(getstring "\nNacisnij ENTER...")
(princ)
;----------

);progn

);CZEKAJ
;
;=================================================
;Funkcja tworzaca globalne listy wezlow i elementow.
;
(defun UTWORZ_LISTY_DANYCH ()

(progn

;----------
(setq

glob_lista_wezlow

'(

(1 "1" "2" (1.0 1.0 0.0) (0 1 5) (0) (0))
(2 "3" "4" (3.0 8.0 0.0) (0 1 2 7) (0) (0))
(3 "5" "6" (6.0 1.0 0.0) (0 2 3 5 6) (0) (0))
(4 "7" "8" (9.0 8.0 0.0) (0 3 4 7) (0) (0))
(5 "9" "A" (11.0 1.0 0.0) (0 4 6) (0) (0))
;ponizszy wezel nie jest uwzgledniony w

konstrukcji

;sluzy on jedynie do testowania zapisu do pliku
(100000 "id1" "id2"

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

678

(1000000.0 1000000.0 1000000.0) (0) (0) (0)

)

)

glob_lista_elementow

'(

(1 "B" "C" (2.0 4.5 0.0) 1 34000 1 1 2)
(2 "D" "E" (4.5 4.5 0.0) 1 34000 1 2 3)
(3 "F" "10" (7.5 4.5 0.0) 1 34000 1 3 4)
(4 "11" "12" (10.0 4.5 0.0) 1 34000 1 4 5)
(5 "13" "14" (3.5 1.0 0.0) 2 34000 2 1 3)
(6 "15" "16" (8.5 1.0 0.0) 2 34000 2 3 5)
(7 "17" "18" (6.0 8.0 0.0) 3 34000 3 2 4)

)

);setq
;----------
(princ)
;----------

);progn

);UTWORZ_LISTY_DANYCH
;
;=================================================
;Funkcja zapisujaca w pliku modul sterujacy
;programem obliczajacym.
;
(defun ZAPISZ_MODUL_CONTROL ()

(progn

;----------
(princ "\nZapis modulu CONTROL.")
(fprintf

'("%s%s%s%s"

"CONTROL\n"
"PHASE=9\n"
"STRESS\n"
"CONTROL.END\n"

)

file_id

);fprintf
(princ "

Zapisano.")

;----------
(princ)
;----------

);progn

);ZAPISZ_MODUL_CONTROL
;
;=================================================
;Funkcja zapisujaca w pliku dane o wezlach.
;
(defun ZAPISZ_WEZLY

(/ dlugosc licznik opis_wezla numer wspolrzedne

wsp_x wsp_y wsp_z

)

(progn

;----------
(if (> (length glob_lista_wezlow) 0)

(progn

;----------

background image

679

BvupMJTQ!—!qsbluzd{oz!lvst

(princ "\nZapis wezlow.

")

(fprintf '("NODES\n") file_id)
(fprintf

'("NODE.NUMBER

X

Y

Z\n")

file_id

);fprintf
;
(setq

dlugosc (length glob_lista_wezlow)
licznik 0

);setq
(repeat dlugosc

(progn

;----------
(setq

opis_wezla (nth licznik glob_lista_wezlow)
numer (nth 0 opis_wezla)
wspolrzedne (nth 3 opis_wezla)

);setq
;
(setq

wsp_x (nth 0 wspolrzedne)
wsp_y (nth 1 wspolrzedne)
wsp_z (nth 2 wspolrzedne)

);setq
;
(fprintf

'("%5d

%11.4f

%11.4f

%11.4f\n"

numer wsp_x wsp_y wsp_z

)

file_id

);fprintf
;----------
(setq licznik (1+ licznik))
;----------

);progn

);repeat dlugosc
;
(fprintf '("C END.OF.NODES\n") file_id)
(princ "

Zapisano.")

;----------

);progn

);if
;----------
(princ)
;----------

);progn

);ZAPISZ_WEZLY
;
;=================================================
;Funkcja zapisujaca w pliku dane o elementach.
;
(defun ZAPISZ_ELEMENTY

(/ dlugosc licznik opis_elementu numer grupa typ

wlasciwosci wezel_1 wezel_2

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

67:

)

(progn

;----------
(if (> (length glob_lista_elementow) 0)

(progn

;----------
(princ "\nZapis elementow.

")

(fprintf '("ELEMENTS\n") file_id)
(fprintf

'("%s%s\n"

"NUMBER

GROUP.NUMBER

ELEMENT.TYPE

"

"PROPERTIES

TOPOLOGY"

)

file_id

);fprintf
;
(setq

dlugosc (length glob_lista_elementow)
licznik 0

);setq
(repeat dlugosc

(progn

;----------
(setq

opis_elementu

(nth licznik glob_lista_elementow)

numer (nth 0 opis_elementu)
grupa (nth 4 opis_elementu)
typ (nth 5 opis_elementu)
wlasciwosci (nth 6 opis_elementu)
wezel_1 (nth 7 opis_elementu)
wezel_2 (nth 8 opis_elementu)

);setq
;
(fprintf

'("%6d

%3d

%4d

%3d

%d

%d\n"

numer grupa typ wlasciwosci wezel_1 wezel_2

)

file_id

);fprintf
;----------
(setq licznik (1+ licznik))
;----------

);progn

);repeat dlugosc
;
(fprintf '("C END.OF.ELEMENTS\n") file_id)
(princ "

Zapisano.")

);progn

);if
;----------
(princ)
;----------

);progn

);ZAPISZ_ELEMENTY
;

background image

681

BvupMJTQ!—!qsbluzd{oz!lvst

;=================================================
;Funkcja glowna do zapisu danych w pliku.
;
(defun ZAPISZ_ZBIOR_DANYCH (/ file_id)

(progn

;----------
(setq file_id (open glob_filename_dat "w"))
(fprintf

'("C Zbior danych programu PAFEC FE\n") file_id)

(fprintf

'("C przygotowany przez program AutoCAD.\n") file_id)

(fprintf '("C\nC\n") file_id)
(ZAPISZ_MODUL_CONTROL)
(fprintf '("C\nC\n") file_id)
(ZAPISZ_WEZLY)
(fprintf '("C\nC\n") file_id)
(ZAPISZ_ELEMENTY)
(fprintf '("C\nC\n") file_id)
(fprintf '("END.OF.DATA\n") file_id)
(close file_id)
;----------
(princ)
;----------

);progn

);ZAPISZ_ZBIOR_DANYCH
;
;=================================================
;Ten fragment programu wykonywany jest
;automatycznie po jego zaladowaniu.
;
(setq

glob_filename_dat "$file_05.dat"
glob_filename_lib_1 "printf.llb"
glob_fullpath (findfile glob_filename_lib_1)

);setq
(if (= glob_fullpath nil)

(progn

(alert

(strcat

"Nie znaleziono pliku "
glob_filename_lib_1
".\n"
"Przerwanie wykonywania programu."

);strcat

);alert
(exit)

);progn
;
(progn

;else

(load glob_fullpath)
(UTWORZ_LISTY_DANYCH)
(textpage)
(princ "\nListy danych do zapisu.")
(princ "\n\nLista wezlow.\n")
(prin1 glob_lista_wezlow)
(princ "\n\nLista elementow.\n")

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

682

(prin1 glob_lista_elementow)
(princ "\n")
(CZEKAJ)
(ZAPISZ_ZBIOR_DANYCH)
(princ "\n")
(CZEKAJ)
(graphscr)

);progn

);if
(princ)
;
;=================================================
;*************************************************KONIEC

Wykonanie programu b

ędzie następujące:

Command: (load "prog_117")

↵↵

Listy danych do zapisu.

Lista wezlow.
((1 "1" "2" (1.0 1.0 0.0) (0 1 5) (0) (0))(2 "3" "4" (3.0
8.0 0.0) (0 1 2 7) (0) (0))(3 "5" "6" (6.0 1.0 0.0) (0 2 3 5
6) (0) (0))(4 "7" "8" (9.0 8.0 0.0) (0 3 4 7) (0) (0))(5 "9"
"A" (11.0 1.0 0.0) (0 4 6) (0) (0))(100000 "id1"
"id2"(1000000.0 1000000.0 1000000.0) (0) (0) (0)))

Lista elementow.

((1 "B" "C" (2.0 4.5 0.0) 1 34000 1 1 2)(2 "D" "E" (4.5 4.5
0.0) 1 34000 1 2 3)(3 "F" "10" (7.5 4.5 0.0) 1 34000 1 3
4)(4 "11" "12" (10.0 4.5 0.0) 1 34000 1 4 5)(5 "13" "14"
(3.5 1.0 0.0) 2 34000 2 1 3)(6 "15" "16" (8.5 1.0 0.0) 2
34000 2 3 5)(7 "17" "18" (6.0 8.0 0.0) 3 34000 3 2 4))

Nacisnij ENTER...

↵↵

Zapis modulu CONTROL.

Zapisano.

Zapis wezlow.

Zapisano.

Zapis elementow.

Zapisano.

Nacisnij ENTER...

↵↵

Command:

Zawarto

ść pliku $FILE_05.DAT będzie następująca:

C Zbior danych programu PAFEC FE

C przygotowany przez program AutoCAD.
C
C
CONTROL
PHASE=9
STRESS
CONTROL.END

background image

683

BvupMJTQ!—!qsbluzd{oz!lvst

C
C
NODES
NODE.NUMBER

X

Y

Z

1

1.0000

1.0000

0.0000

2

3.0000

8.0000

0.0000

3

6.0000

1.0000

0.0000

4

9.0000

8.0000

0.0000

5

11.0000

1.0000

0.0000

100000

1000000.0000

1000000.0000

1000000.0000

C END.OF.NODES
C
C
ELEMENTS
NUMBER

GROUP.NUMBER

ELEMENT.TYPE

PROPERTIES

TOPOLOGY

1

1

34000

1

1

2

2

1

34000

1

2

3

3

1

34000

1

3

4

4

1

34000

1

4

5

5

2

34000

2

1

3

6

2

34000

2

3

5

7

3

34000

3

2

4

C END.OF.ELEMENTS
C
C
END.OF.DATA

Jak zapewne zauwa

żyłeś, wykonanie programu jest analogiczne jak programu PROG-

_115, utworzony zbiór danych jest za

ś taki sam jak plik $FILE_03.DAT.

Algorytm do zapisu w

ęzłów i elementów jest też bardzo podobny. Po wybraniu od-

powiednich danych dla w

ęzła lub elementu wykorzystujemy funkcję fprintf do

utworzenia ła

ńcucha danych i jego zapisu w pliku. Łańcuch sterujący funkcji printf

zawiera odpowiednie specyfikatory formatu oddzielone tak

ą liczbą spacji, aby plik

danych miał przejrzyst

ą i czytelną strukturę.

26/5/6/!Qps.

26/5/6/!Qps.

26/5/6/!Qps.

26/5/6/!Qps.xobojf!{bqjtv!

xobojf!{bqjtv!

xobojf!{bqjtv!

xobojf!{bqjtv!ep!qmjlv

ep!qmjlv

ep!qmjlv

ep!qmjlv

qs{

qs{

qs{

qs{zl1bepxzd

zl1bepxzd

zl1bepxzd

zl1bepxzdi!mjojj!{!xzlp

i!mjojj!{!xzlp

i!mjojj!{!xzlp

i!mjojj!{!xzlps{ztubojfn

s{ztubojfn

s{ztubojfn

s{ztubojfn

gvoldkj!QSJ

gvoldkj!QSJ

gvoldkj!QSJ

gvoldkj!QSJOD-!QSJO2-!

OD-!QSJO2-!

OD-!QSJO2-!

OD-!QSJO2-!XSJUF.MJ

XSJUF.MJ

XSJUF.MJ

XSJUF.MJOF!psb{

OF!psb{

OF!psb{

OF!psb{

QSJO

QSJO

QSJO

QSJOUG

UG

UG

UG

Poni

ższy program zapisuje do pliku te same linie danych wykorzystując cztery różne

funkcje. Wydruk pliku wynikowego pozwoli nam oceni

ć sposób zapisu informacji

przez ka

żdą z funkcji jak również poznać wady i zalety wymienionych funkcji.

;*************************************************PROG_118
;Zapis do pliku przykladowych linii z wykorzystaniem
;funkcji PRINC, PRIN1, WRITE-LINE oraz FPRINTF.
;Zapis do pliku $FILE_06.DAT.
;Kazda linia danych umieszczona jest w nowej linii.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

684

;
;Program korzysta z funkcji FPRINTF zawartej w pliku
PRINTF.LLB.
;
;=================================================
;Funkcja zatrzymujaca realizacje programu,
;dopoki uzytkownik nie nacisnie ENTER...
;
(defun CZEKAJ ()

(progn

;----------
(getstring "\nNacisnij ENTER...")
(princ)
;----------

);progn

);CZEKAJ
;
;=================================================
;Przygotowanie linii danych do zapisu.
;
(defun PRZYGOTUJ_DANE ()

(progn

;----------
(setq

glob_linia_1 "CMG \"KOMAG\" Gliwice"
glob_linia_2 "1 2.50 \"abcd\" (\"A1\" . \"10\")"
glob_linia_3 '(1 2.50 "abcd" ("A1" . "10"))

);setq
;----------
(princ)
;----------

);progn

);PRZYGOTUJ_DANE
;
;=================================================
;Zapis danych z wykorzystaniem funkcji PRINC.
;
(defun ZAPISZ_DANE_PRINC ()

(progn

;----------
(princ "\n==============================" file_id)
(princ "\nZapis danych funkcja PRINC." file_id)
(princ "\n" file_id)
(princ glob_linia_1 file_id)
(princ "\n" file_id)
(princ glob_linia_2 file_id)
(princ "\n" file_id)
(princ glob_linia_3 file_id)
(princ "\n==============================" file_id)
;----------
(princ)
;----------

);progn

);ZAPISZ_DANE_PRINC
;

background image

685

BvupMJTQ!—!qsbluzd{oz!lvst

;=================================================
;Zapis danych z wykorzystaniem funkcji PRIN1.
;
(defun ZAPISZ_DANE_PRIN1 ()

(progn

;----------
(princ "\n==============================" file_id)
(princ "\nZapis danych funkcja PRIN1." file_id)
(princ "\n" file_id)
(prin1 glob_linia_1 file_id)
(princ "\n" file_id)
(prin1 glob_linia_2 file_id)
(princ "\n" file_id)
(prin1 glob_linia_3 file_id)
(princ "\n==============================" file_id)
;----------
(princ)
;----------

);progn

);ZAPISZ_DANE_PRIN1
;
;=================================================
;Zapis danych z wykorzystaniem funkcji WRITE-LINE.
;
(defun ZAPISZ_DANE_WRITE_LINE ()

(progn

;----------
(princ "\n==============================" file_id)
(princ "\nZapis danych funkcja WRITE-LINE." file_id)
(princ "\n" file_id)
(write-line glob_linia_1 file_id)
(write-line glob_linia_2 file_id)

;

(write-line glob_linia_3 file_id)

(princ "\n==============================" file_id)
;----------
(princ)
;----------

);progn

);ZAPISZ_DANE_WRITE_LINE
;
;=================================================
;Zapis danych z wykorzystaniem funkcji FPRINTF.
;
(defun ZAPISZ_DANE_FPRINTF ()

(progn

;----------
(fprintf '("\n==============================") file_id)
(fprintf '("\nZapis danych funkcja FPRINTF.") file_id)
(fprintf '("\n") file_id)
(fprintf '("%s" glob_linia_1) file_id)
(fprintf '("\n") file_id)
(fprintf '("%s" glob_linia_2) file_id)
(fprintf '("\n") file_id)

;

(fprintf '("%s" glob_linia_3) file_id)

(fprintf '("\n==============================") file_id)

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

686

;----------
(princ)
;----------

);progn

);ZAPISZ_DANE_FPRINTF
;
;=================================================
;Ten fragment programu wykonywany jest
;automatycznie po jego zaladowaniu.
;
(setq

glob_filename_dat "$file_06.dat"
glob_filename_lib_1 "printf.llb"
glob_fullpath (findfile glob_filename_lib_1)

);setq
(if (= glob_fullpath nil)

(progn

(alert

(strcat

"Nie znaleziono pliku "
glob_filename_lib_1
".\n"
"Przerwanie wykonywania programu."

);strcat

);alert
(exit)

);progn
;
(progn

;else

(load glob_fullpath)
(setq file_id (open glob_filename_dat "w"))
(PRZYGOTUJ_DANE)
(textpage)
(princ "\nLinie danych do zapisu.")
(princ "\n\nLinia 1.\n")
(prin1 glob_linia_1)
(princ "\n\nLinia 2.\n")
(prin1 glob_linia_2)
(princ "\n\nLinia 3.\n")
(prin1 glob_linia_3)
(princ "\n")
(princ "\nRozpoczecie zapisu danych.")
(CZEKAJ)
(princ "\nZapis danych funkcja PRINC.")
(CZEKAJ)
(ZAPISZ_DANE_PRINC)
(princ "\nZapis danych funkcja PRIN1.")
(CZEKAJ)
(ZAPISZ_DANE_PRIN1)
(princ "\nZapis danych funkcja WRITE-LINE.")
(CZEKAJ)
(ZAPISZ_DANE_WRITE_LINE)
(princ "\nZapis danych funkcja FPRINTF.")
(CZEKAJ)
(ZAPISZ_DANE_FPRINTF)

background image

687

BvupMJTQ!—!qsbluzd{oz!lvst

(princ "\nZakonczenie zapisu danych.")
(CZEKAJ)
(graphscr)
(close file_id)

);progn

);if
(princ)
;
;=================================================
;*************************************************KONIEC

Wykonanie programu b

ędzie następujące:

Command: (load "prog_118")

↵↵

Linie danych do zapisu.

Linia 1.
"CMG "KOMAG" Gliwice"

Linia 2.
"1 2.50 "abcd" ("A1" . "10")"

Linia 3.
(1 2.5 "abcd" ("A1" . "10"))

Rozpocz

ę

cie zapisu danych.

Nacisnij ENTER...

↵↵

Zapis danych funkcja PRINC.

Nacisnij ENTER...

↵↵

Zapis danych funkcja PRIN1.

Nacisnij ENTER...

↵↵

Zapis danych funkcja WRITE-LINE.

Nacisnij ENTER...

↵↵

Zapis danych funkcja FPRINTF.

Nacisnij ENTER...

↵↵

Zakonczenie zapisu danych.

Nacisnij ENTER...

↵↵

Command:

Zawarto

ść pliku $FILE_06.DAT będzie następująca:

==============================
Zapis danych funkcja PRINC.
CMG "KOMAG" Gliwice
1 2.50 "abcd" ("A1" . "10")
(1 2.5 abcd (A1 . 10))
==============================

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

688

==============================
Zapis danych funkcja PRIN1.
"CMG "KOMAG" Gliwice"
"1 2.50 "abcd" ("A1" . "10")"
(1 2.5 "abcd" ("A1" . "10"))
==============================
==============================
Zapis danych funkcja WRITE-LINE.
CMG "KOMAG" Gliwice
1 2.50 "abcd" ("A1" . "10")

==============================
==============================
Zapis danych funkcja FPRINTF.
CMG "KOMAG" Gliwice
1 2.50 "abcd" ("A1" . "10")

==============================

Podsumowuj

ąc, możliwości poszczególnych funkcji są następujące:

QSJ

QSJ

QSJ

QSJOD

OD

OD

OD

Princ wy

świetla dowolne wyrażenie (niekoniecznie łańcuch alfanumeryczny) w linii ko-

mend, zwraca podane wyra

żenie i opcjonalnie może wysyłać dane do pliku dyskowego.

Princ wykonuje kody steruj

ące, np.:

Command: (princ "test1\ntest2")

↵↵

test1
test2 "test1\ntest2"
Command:

Princ nie umieszcza automatycznie na ko

ńcu wyrażenia kodu przejścia do nowej linii.

Aby zapisa

ć zagnieżdżone dane typu łańcuchowego należy je poprzedzić znakiem "\".

QSJO2

QSJO2

QSJO2

QSJO2

Prin1 wy

świetla dowolne wyrażenie (niekoniecznie łańcuch alfanumeryczny) w linii ko-

mend, zwraca podane wyra

żenie i opcjonalnie może wysyłać dane do pliku dyskowego.

Prin1 nie wykonuje kodów steruj

ących, np:

Command: (prin1 "test1\ntest2")

↵↵

"test1\ntest2""test1\ntest2"
Command:

Prin1 nie umieszcza automatycznie na ko

ńcu wyrażenia kodu przejścia do nowej linii.

Ła

ńcuchy tekstowe w listach są wyświetlane w cudzysłowach.

background image

689

BvupMJTQ!—!qsbluzd{oz!lvst

XSJ

XSJ

XSJ

XSJUF.MJOF

UF.MJOF

UF.MJOF

UF.MJOF

Write-line słu

ży do wyświetlenia w linii komend lub zapisania w pliku tylko zmiennej łań-

cuchowej. W przypadku danej innego typu (np. listy) wypisywany jest komunikat o bł

ędzie.

Write-line wykonuje kody steruj

ące, np.:

Command: (write-line "test1\ntest2")

↵↵

test1
test2
"test1\ntest2"
Command:

Write-line umieszcza automatycznie na ko

ńcu wyrażenia kod przejścia do nowej linii.

Aby zapisa

ć zagnieżdżone dane typu łańcuchowego należy je poprzedzić znakiem "\".

GQSJOUG

GQSJOUG

GQSJOUG

GQSJOUG

Fprinf słu

ży do formatowanego wyświetlania w linii komend lub zapisania w pliku

danych typu ła

ńcuchowego, całkowitego lub rzeczywistego. W przypadku list mogą to

by

ć wyłącznie listy reprezentujące punkty.

Fprintf wykonuje kody steruj

ące, np.:

Command: (fprintf '("test1\ntest2") file_id)

↵↵

test1
test2 "test1\ntest2"
Command:

Fprintf nie umieszcza automatycznie na ko

ńcu wyrażenia kodu przejścia do nowej

linii. Aby zapisa

ć zagnieżdżone dane typu łańcuchowego należy je poprzedzić znakiem

"\".

26/5/7/![b

26/5/7/![b

26/5/7/![b

26/5/7/![bqjt!ebozd

qjt!ebozd

qjt!ebozd

qjt!ebozdi!x!qptubdj!

i!x!qptubdj!

i!x!qptubdj!

i!x!qptubdj!sflpse.x

sflpse.x

sflpse.x

sflpse.x

Przedstawione do tej pory przykłady zapisu danych do pliku bazowały na zało

żeniu, że

wewn

ątrz danej nie występują spacje. Podczas zapisu danych do pliku możemy je

dodatkowo ustawi

ć w kolumnach (dla zapewnienia lepszej czytelności pliku). Nie

zmienia to jednak faktu,

że podczas odczytu danych z pliku poszczególne linie rozbijamy

na podła

ńcuchy, gdzie końcem podłańcucha jest miejsce wystąpienia pierwszej spacji.

Przykładowo, linia danych

"

1

2

34000

1

11

25"

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

68:

zostanie rozbita na podła

ńcuchy

"1" "2" "34000" "1" "11" "25"

W wi

ększości typowych zastosowań taki sposób interpretowania danych w pliku jest

wystarczaj

ący. Przypuśćmy jednak, że chcemy zapisać w pliku dane z tabliczki rysunku

zło

żeniowego uchwytu frezarskiego.

Pod pozycj

ą Nazwa części mogą być umieszczone między innymi:

Podstawa

Tulejka

Klocek

Pokrywka

Wałek mimo

środowy

Śruba z łbem z gniazdem M6x25
Kołek sto

żkowy 5x35

Kołek oporowy 10x6

Wkr

ęt M6x8

R

ękojeść B80

Jak wida

ć, podczas odczytu tak zapisanych danych nie możemy stosować zasady

podziału na podła

ńcuchy zakończone spacją, gdyż np. linia

"Kołek oporowy 10x6"

zostanie rozbita na podła

ńcuchy

"Kołek" "oporowy" "10x6"

co nie jest tym, czego oczekiwali

śmy. Oczywiście, gdy każda nazwa części zajmuje

osobn

ą linię i nie ma już w tej linii innych danych (np. numeru rysunku, numeru normy,

materiału cz

ęści itp.), nie musimy rozbijać linii na podłańcuchy (cała linia stanowi

wówczas jedn

ą daną). Najczęściej jednak w jednej linii umieszczamy wszystkie dane

opisuj

ące jedną część na rysunku. W takim wypadku przy zapisie i odczycie danych

musimy si

ę posłużyć zapisem rekordowym (jest to zapis stosowany w bazach danych).

Rekord jest to linia danych, podzielona na poszczególne pola, z których ka

żde zajmuje

w rekordzie

ściśle określoną pozycję. Poszczególne pola oddzielone są od siebie jedną

spacj

ą. Liczba znaków w polu musi być na tyle duża, aby pomieścić najdłuższy

ła

ńcuch. Typ pola (numeryczne lub znakowe) wskazuje na sposób wyrównania danych

w polu. Dane ła

ńcuchowe wyrównywane są do lewej, dane numeryczne wyrównywane

s

ą zaś do prawej.

Aby pokaza

ć, jak wygląda zapis w postaci rekordów, posłużymy się wybranymi

rekordami z bazy danych zawartej w pliku INVENTRY.DBF. Plik ten jest cz

ęścią

pakietu AutoCAD i znajduje si

ę na dołączonej dyskietce.

W poni

ższej tabeli podano charakterystykę pól tworzących jeden rekord.

background image

691

BvupMJTQ!—!qsbluzd{oz!lvst

Tabela 15.5. Charakterystyka pól tworz

ących jeden rekord w pliku INVENTRY.DBF

Name

Type

Length

Decimals

Justification

Fields

INV_ID

Numeric

12

0

right

1 — 12

TYPE

Character

20

left

14 — 33

DESCRIPT

Character

40

left

35 — 74

MFR

Character

40

left

76 — 115

MODEL

Character

15

left

117 — 131

COMP_CFG

Numeric

12

0

right

133 — 144

PRICE

Numeric

10

2

right

146 — 155

ROOM

Character

5

left

157 — 161

EMP_ID

Numeric

12

0

right

163 — 174

Poszczególne kolumny tabeli oznaczaj

ą: nazwę pola (name), typ pola — numeryczne

lub znakowe (type), długo

ść pola w znakach — dla pól numerycznych wlicza się

dodatkowo kropk

ę oraz miejsca dziesiętne (length), liczbę miejsc dziesiętnych

(decimals), sposób wyrównania pola — lewostronne lub prawostronne (justification)
oraz poło

żenie pola w rekordzie — pozycja początkowa i końcowa (fields). Poszcze-

gólne pola w rekordzie oddzielone s

ą od siebie jedną spacją.

W poni

ższej tabeli zestawiono dane wybranych rekordów bazy danych zawartej w pliku

INVENTRY.DBF. Nagłówek tabeli zawiera nazwy pól w rekordzie, poszczególne
wiersze zawieraj

ą zawartości rekordów.

Tabela 15.6. Wybrane rekordy z pliku INVENTRY.DBF

INV
_ID

TYPE

DESCRIPT

MFR

MODEL

COMP
_CFG

PRICE

ROOM EMP

_ID

1

FURNITURE

6x3 couch

couches
are us

lounge cat

0

800.00

101

1000

2

FURNITURE

adjustable
chair

chairs R
us

comp pro

0

200.00

101

1000

3

FURNITURE

two piece
desk

office
master

desk3

0

400.00

101

1000

4

FURNITURE

one piece
desk

office
master

desk4

0

200.00

109

1006

5

FURNITURE

42x18 file
cabinet

office
master

fc42x18d

0

40.00

101

1000

6

FURNITURE

36x48 file flat

office
master

ff36x48d

0

60.00

122

1010

7

FURNITURE

36x12 file
cabinet

office
master

fc36x12d

0

30.00

101

1000

8

HARDWARE personal

inventry

hardwire
hardware

cpu1

2

1300.00

101

1000

9

HARDWARE telephone

Baby bell

voice box 1

0

150.00

109

1006

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

692

Tabela 15.6. Wybrane rekordy z pliku INVENTRY.DBF (c.d.)

INV
_ID

TYPE

DESCRIPT

MFR

MODEL

COMP
_CFG

PRICE

ROOM

EMP
_ID

10

FURNITURE

6 foot table

office
master

2x6tb

0

33.00

121

1000

11

FURNITURE

3 foot filing
case

office
master

fc3

0

60.00

111

1000

12

FURNITURE

8 foot table

office
master

2x8tb

0

40.00

128

1000

Poni

ższy program pokazuje sposób zapisu pliku danych w postaci rekordów — każda

linia pliku stanowi osobny rekord.

;*************************************************PROG_119
;Zapis danych w postaci rekordow.
;Zapis do pliku $FILE_07.dat.
;
;Program korzysta z funkcji USTAW_DLUGOSC_LANCUCHA
;zawartej w pliku PROG_062.LSP
;
;=================================================
;Funkcja zatrzymujaca realizacje programu,
;dopoki uzytkownik nie nacisnie ENTER...
;
(defun CZEKAJ ()

(progn

;----------
(getstring "\nNacisnij ENTER...")
(princ)
;----------

);progn

);CZEKAJ
;
;=================================================
;Przygotowanie listy danych do zapisu.
;
(defun PRZYGOTUJ_DANE ()

(progn

;----------
(setq

glob_lista_1

'(

(1 "FURNITURE" "6x3 couch" "couches are us" "lounge cat" 0
800.00 "101" 1000)
(2 "FURNITURE" "adjustable chair" "chairs R us" "comp pro" 0
200.00 "101" 1000)
(3 "FURNITURE" "two piece desk" "office master" "desk3" 0
400.00 "101" 1000)
(4 "FURNITURE" "one piece desk" "office master" "desk4" 0
200.00 "109" 1006)
(5 "FURNITURE" "42x18 file cabinet" "office master"
"fc42x18d" 0 40.00 "101" 1000)

background image

693

BvupMJTQ!—!qsbluzd{oz!lvst

(6 "FURNITURE" "36x48 flat file" "office master" "ff36x48d"
0 60.00 "122" 1010)
(7 "FURNITURE" "36x12 file cabinet" "office master"
"fc36x12d" 0 30.00 "101" 1000)
(8 "HARDWARE" "personal inventry" "hardwire hardware" "cpu1"
2 1300.00 "101" 1000)
(9 "HARDWARE" "telephone" "Baby bell" "voice box 1" 0 150.00
"109" 1006)
(10 "FURNITURE" "6 foot table" "office master" "2x6tb" 0
33.00 "121" 1000)
(11 "FURNITURE" "3 foot filing case" "office master" "fc3" 0
60.00 "111" 1000)
(12 "FURNITURE" "8 foot table" "office master" "2x8tb" 0
40.00 "128" 1000)

)

);setq
;----------
(princ)
;----------

);progn

);PRZYGOTUJ_DANE
;
;=================================================
;Zapis danych.
;
(defun ZAPISZ_DANE

(/ dlugosc licznik dane inv_id typ descript mfr model

comp_cfg price room emp_id rekord

)

(progn

;----------
(setq

dlugosc (length glob_lista_1)
licznik 0

);setq

(repeat dlugosc

(progn

;----------
;pobranie danych dla jednego rekordu
;ustawienie dlugosci lancuchow

(setq

dane (nth licznik glob_lista_1)
inv_id

(nth 0 dane)

typ

(nth 1 dane)

descript (nth 2 dane)
mfr

(nth 3 dane)

model

(nth 4 dane)

comp_cfg (nth 5 dane)
price

(nth 6 dane)

room

(nth 7 dane)

emp_id

(nth 8 dane)

);setq

;

(setq

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

694

inv_id

(rtos inv_id 2 0)

inv_id

(USTAW_DLUGOSC_LANCUCHA inv_id

12 2)

typ

(USTAW_DLUGOSC_LANCUCHA typ

20 1)

descript (USTAW_DLUGOSC_LANCUCHA descript 40 1)
mfr

(USTAW_DLUGOSC_LANCUCHA mfr

40 1)

model

(USTAW_DLUGOSC_LANCUCHA model

15 1)

comp_cfg (rtos comp_cfg 2 0)
comp_cfg (USTAW_DLUGOSC_LANCUCHA comp_cfg 12 2)
price

(rtos price 2 2)

price

(USTAW_DLUGOSC_LANCUCHA price

10 2)

room

(USTAW_DLUGOSC_LANCUCHA room

5 1)

emp_id

(rtos emp_id 2 0)

emp_id

(USTAW_DLUGOSC_LANCUCHA emp_id

12 2)

);setq

;----------
;przygotowanie rekordu

(setq

rekord ""
rekord (strcat

rekord
inv_id
" "
typ
" "
descript
" "
mfr
" "
model
" "
comp_cfg
" "
price
" "
room
" "
emp_id

);strcat

);setq

;----------
;zapis rekordu do pliku

(write-line rekord file_id)

;----------
(setq licznik (1+ licznik))
;----------

);progn

);repeat dlugosc
;----------
(princ)
;----------

);progn

);ZAPISZ_DANE
;
;=================================================

background image

695

BvupMJTQ!—!qsbluzd{oz!lvst

;Ten fragment programu wykonywany jest
;automatycznie po jego zaladowaniu.
;
(setq

glob_filename_dat "$file_07.dat"
glob_filename_lib_1 "prog_062.lsp"
glob_fullpath (findfile glob_filename_lib_1)

);setq
(if (= glob_fullpath nil)

(progn

(alert

(strcat

"Nie znaleziono pliku "
glob_filename_lib_1
".\n"
"Przerwanie wykonywania programu."

);strcat

);alert
(exit)

);progn
;
(progn

;else

(load glob_fullpath)
(setq file_id (open glob_filename_dat "w"))
(PRZYGOTUJ_DANE)
(princ "\nZapis rekordow do pliku $FILE_07.DAT..")
(CZEKAJ)
(ZAPISZ_DANE)
(princ "\nZapisano.")
(close file_id)

);progn

);if
(princ)
;
;=================================================
;*************************************************KONIEC

Wykonanie programu spowoduje utworzenie pliku $FILE_07.DAT zawieraj

ącego 12

rekordów, z których ka

żdy umieszczony jest w osobnym wierszu.

Omówmy teraz wyró

żnione linie i bloki programu.

Wchodzimy w pętlę repeat i rozpoczynamy przetwarzanie listy glob_lista_1,

zawieraj

ącej dane tworzące poszczególne rekordy. Lista zawiera dane typu

ła

ńcuchowego i numerycznego zgodne z typem pól w rekordzie.

W bloku tym pobieramy dane tworzące jeden rekord i podstawiamy je pod

zmienne, których nazwy pokrywaj

ą się z nazwami pól w rekordzie.

Pole TYPE zostało zamienione na typ (setq typ (nth 1 dane)) — inaczej
spowoduje to przedefiniowanie standardowej funkcji AutoLISPu type.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

696

W bloku tym zamieniamy pola numeryczne na łańcuchowe, formatujemy

długo

ści łańcuchów oraz wyrównujemy zawartości pól do lewej lub do prawej.

W bloku tym, używając funkcji strcat, łączymy poszczególne pola w rekord

pami

ętając o tym, że pola oddzielone są od siebie jedną spacją.

Zapisujemy utworzony rekord do pliku.

Je

śli chcemy odczytać dane z pliku, mamy do dyspozycji następujące funkcje: read-

char, read-line lub SSCANF. Poni

żej przedstawiono przykłady zastosowań poszcze-

gólnych funkcji. Wszystkie programy korzystaj

ą ze zbiorów danych przygotowanych

wcze

śniej przez funkcje do zapisu danych w pliku (pliki $FILE_01.DAT

$FILE_08.DAT).

2

22

26/6/2/!Ped{zu!e

6/6/2/!Ped{zu!e

6/6/2/!Ped{zu!e

6/6/2/!Ped{zu!ebozdi!qpk

bozdi!qpk

bozdi!qpk

bozdi!qpkfezod{p!{ob

fezod{p!{ob

fezod{p!{ob

fezod{p!{obl!qp

l!qp

l!qp

l!qp

{oblv

{oblv

{oblv

{oblv

W celu odczytania danych z pliku pojedynczo znak po znaku posługujemy si

ę funkcją

read-char o składni:

(read-char

[file-desc])

Funkcja odczytuje jeden znak z wej

ściowego bufora klawiatury lub z otwartego pliku

wskazywanego przez deskryptor file-desc. Funkcja zwraca kod ASCII odczytanego
znaku. W przypadku odczytu z pliku po napotkaniu znacznika ko

ńca pliku funkcja

zwraca nil.

Poni

ższy program pokazuje wykorzystanie funkcji read-char oraz write-char do

wy

świetlenia na ekranie tekstowym zawartości podanego pliku tekstowego.

;*************************************************PROG_120
;Wykorzystanie funkcji READ-CHAR i WRITE-CHAR.
;Wyswietlenie zawartosci pliku znak po znaku.
;
;=================================================
;Funkcja wyswietlajaca plik o podanej nazwie.
;
(defun WYSWIETL_PLIK_1 (nazwa_pliku / file_id znak)

(progn

;----------

(setq file_id (open nazwa_pliku "r"))

(if (/= file_id nil)

(progn

;----------

(while (/= (setq znak (read-char file_id)) nil)

background image

697

BvupMJTQ!—!qsbluzd{oz!lvst

(progn

;----------

(write-char znak)

;----------

);progn

);while

;----------
(close file_id)
;----------

);progn

);if

;----------
(princ)
;----------

);progn

);WYSWIETL_PLIK_1
;
;=================================================
;Funkcja testujaca
;
(defun C:TEST (/ plik)

(progn

;----------
;wyswietlenie okna dialogowego GETFILED
;pobranie nazwy pliku do wyswietlenia
(setq plik (getfiled "Wybierz Plik" "" "" 2))
;----------
(if plik

(progn

(WYSWIETL_PLIK_1 plik)

);progn
;
(progn

;else

(princ "\nNie wybrano pliku.")

);progn

);if
;----------
(princ)
;----------

);progn

);C:TEST
;
;=================================================
(princ

(strcat

"\nProgram zaladowany. "
"Komenda TEST uruchamia testowanie."

);strcat

);princ
(princ)
;=================================================
;*************************************************KONIEC

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

698

Program składa si

ę z funkcji głównej WYSWIETL_PLIK_1, wyświetlającej zawartość

podanego pliku oraz funkcji testuj

ącej C:TEST, zadaniem której jest pobranie nazwy

pliku do wy

świetlenia oraz przekazanie jej funkcji głównej.

Omówmy teraz wyró

żnione linie i bloki funkcji WYSWIETL_PLIK_1.

Otwieramy do odczytu plik podany w argumencie wywołania funkcji.
Ten blok instrukcji wykonywany jest wówczas, gdy plik został otwarty do

odczytu.

W bloku tym wchodzimy w pętlę while i rozpoczynamy przetwarzanie pliku

znak po znaku. P

ętlę while wykonujemy tak długo, aż funkcja read-char nie

zwróci znacznika ko

ńca pliku (nil). Wartość zwrotną funkcji read-char podsta-

wiamy pod zmienn

ą znak.

Wypisujemy odczytany znak na ekranie tekstowym.

26/6/

26/6/

26/6/

26/6/3/!Ped{zu!e

3/!Ped{zu!e

3/!Ped{zu!e

3/!Ped{zu!ebozdi!1b2dvdib

bozdi!1b2dvdib

bozdi!1b2dvdib

bozdi!1b2dvdibnj

nj

nj

nj

W celu odczytania danych z pliku wierszami posługujemy si

ę funkcją read-line o

składni:

(read-line

[file-desc])

Funkcja odczytuje ła

ńcuch alfanumeryczny z wejściowego bufora klawiatury lub z otwar-

tego pliku wskazywanego przez deskryptor file-desc. Funkcja zwraca odczytany ła

ńcuch.

W przypadku odczytu z pliku po napotkaniu znacznika ko

ńca pliku funkcja zwraca nil.

Poni

ższy program pokazuje wykorzystanie funkcji read-line oraz write-line do wyświet-

lenia na ekranie tekstowym zawarto

ści podanego pliku tekstowego.

;*************************************************PROG_121
;Wykorzystanie funkcji READ-LINE i WRITE-LINE.
;Wyswietlenie zawartosci pliku wiersz po wierszu.
;
;=================================================
;Funkcja wyswietlajaca plik o podanej nazwie.
;
(defun WYSWIETL_PLIK_2 (nazwa_pliku / file_id linia)

(progn

;----------
(setq file_id (open nazwa_pliku "r"))
(if (/= file_id nil)

(progn

;----------
(while (/= (setq linia (read-line file_id)) nil)

(progn

;----------
(write-line linia)
;----------

);progn

);while

background image

699

BvupMJTQ!—!qsbluzd{oz!lvst

;----------
(close file_id)
;----------

);progn

);if
;----------
(princ)
;----------

);progn

);WYSWIETL_PLIK_2
;
;=================================================
;Funkcja testujaca
;
(defun C:TEST (/ plik)

(progn

;----------
;wyswietlenie okna dialogowego GETFILED
;pobranie nazwy pliku do wyswietlenia
(setq plik (getfiled "Wybierz Plik" "" "" 2))
;----------
(if plik

(progn

(WYSWIETL_PLIK_2 plik)

);progn
;
(progn

;else

(princ "\nNie wybrano pliku.")

);progn

);if
;----------
(princ)
;----------

);progn

);C:TEST
;
;=================================================
(princ

(strcat

"\nProgram zaladowany. "
"Komenda TEST uruchamia testowanie."

);strcat

);princ
(princ)
;=================================================
;*************************************************KONIEC

Działanie funkcji WYSWIETL_PLIK_2 jest analogiczne do funkcji WYSWIETL
_PLIK_1
— funkcj

ę read-char zastąpiono przez read-line, zaś funkcję write-char

zast

ąpiła funkcja write-line.

Mo

żesz wypróbować działanie funkcji na którymś ze zbiorów danych $FILE_01.DAT

$FILE_08.DAT, wy

świetlić plik z programem w AutoLISPIE czy też dowolny inny

plik tekstowy.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

69:

Program, który przedstawi

ę poniżej, pokazuje wykorzystanie funkcji read-line, funkcji

operuj

ących na łańcuchach, listach oraz listach DXF elementów. Program pokazuje

sposób wczytania zbioru danych dla MES celem jego dalszej obróbki (tworzenie
nowych w

ęzłów siatki, nowych elementów, kasowanie części siatki MES itp.). Efektem

wczytania zbioru danych jest narysowanie siatki MES konstrukcji oraz utworzenie
globalnych list w

ęzłów i elementów. Przedstawiony poniżej program jest najdłuższym

programem w tej ksi

ążce, można niejako powiedzieć, że stanowi jej podsumowanie.

Przedstawiam go jednak

świadomie, gdyż wiem z własnego doświadczenia, jak trudno

jest przej

ść od prostych przykładów do realizacji zadań, z którymi spotkasz się

w Swojej codziennej pracy zawodowej. Nie przejmuj si

ę, jeżeli nie zrozumiesz pro-

gramu od razu lub nie b

ędziesz widział celowości zastosowania w nim niektórych

funkcji. Przedstawiony program jest tylko fragmentem (

5%) aplikacji słu

żącej do two-

rzenia modeli obliczeniowych dla MES w

środowisku systemu AutoCAD.

;*************************************************PROG_122
;Wykorzystanie funkcji READ-LINE.
;Odbior zbioru danych dla MES zapisanego w pliku
$FILE_08.DAT.
;W module NODES wykasowano wezel o numerze 100000.
;
;Program korzysta z nastepujacych funkcji:
;

PODZIEL_NA_PODLANCUCHY zawartej w pliku PROG_063.LSP

;

MIN_MAX_Z_LISTY zawartej w pliku PROG_040.LSP

;
;=================================================
;
(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)
(set zmster (+ ki (eval zmster)))

);while
(setq fun nil)
(princ)

);progn

);FOR
;
;=================================================
;
(defun RYSUNEK_PROTOTYPOWY ()

(progn

;----------
(command

"_cmdecho" "0"

;wylacz echo komend

"_blipmode" "_off"

;wylacz znaczniki punktow

"_handles" "_on"

;wlacz identyfikatory

"_layer"

;utworz warstwy

"_new" "wezly"

background image

6:1

BvupMJTQ!—!qsbluzd{oz!lvst

"_new" "numery_wezlow"
"_new" "elementy"
"_new" "numery_elementow"
"_color" "5" "wezly"
"_color" "5" "numery_wezlow"
"_color" "1" "elementy"
"_color" "1" "numery_elementow"
""

);command
(setvar "pdmode" 33)

;wyglad punktu

;----------
(princ)
;----------

);progn

);RYSUNEK_PROTOTYPOWY
;
;=================================================
;
(defun ZMIENNE_GLOBALNE ()

(progn

;----------
(setq

glob_lista_wezlow (list)
glob_lista_elementow (list)
;
glob_punkt_ld '(0 0 0)
glob_punkt_pg '(12 9 0)
;
glob_appname "ACPAFEC_V_1_50"
;
glob_h_tekstu 0.20
glob_h_tekstu_0 0.20
glob_delta_tekstu 0.20
glob_wielkosc_punktu 0.20
glob_wielkosc_punktu_0 0.20
;
glob_typ_elementu 34000
glob_grupa_elementu 1
glob_material_elementu 1

);setq
(regapp glob_appname)

;rejestracja aplikacji

;----------
(princ)
;----------

);progn

);ZMIENNE_GLOBALNE
;
;=================================================
;
(defun ODBIERZ_ZBIOR_DANYCH (nazwa_zbioru / plik)

(progn

;----------
(setq plik (open nazwa_zbioru "r"))
(command "_ucs" "_World")
(CZYTAJ_ZBIOR_DANYCH)
(OBSZAR_MODELU)

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

6:2

(GRANICE glob_punkt_ld glob_punkt_pg)
(ODBIERZ_WEZLY)
(ODBIERZ_ELEMENTY)
(if plik

(progn

(close plik)

);progn

);if
;----------
(princ)
;----------

);progn

);ODBIERZ_ZBIOR_DANYCH
;
;=================================================
;Wczytanie zbioru danych DAT.
;Utworzenie odpowiednich list.
;
(defun CZYTAJ_ZBIOR_DANYCH ( / jeszcze1 linia)

(progn

;----------
(princ "\nRozpoczecie czytania zbioru danych.")
(setq jeszcze1 T)
(while jeszcze1

(progn

(setq linia (read-line plik))
(setq linia1 (substr linia 1 5))
(cond

((= linia "NODES")(CZYTAJ_MODUL_NODES))
((= linia "ELEMENTS")(CZYTAJ_MODUL_ELEMENTS))
((or (= linia "END.OF.DATA")(= linia nil))

(setq jeszcze1 nil)(close plik)(setq plik nil)

)

);cond

);progn

);while jeszcze1
(princ "\nZakonczenie czytania zbioru danych.")
;----------
(princ)

);progn

);CZYTAJ_ZBIOR_DANYCH
;
;=================================================
;Czytanie modulu NODES
;
(defun CZYTAJ_MODUL_NODES

( / jeszcze2 linia lista1 numer

wsp_x wsp_y wsp_z wsp_wz opis_wezla

)

(progn

;----------
(princ "\nCzytanie wezlow.....")
(setq glob_lista_wezlow (list))
(setq jeszcze2 T)
(while jeszcze2

(progn

background image

6:3

BvupMJTQ!—!qsbluzd{oz!lvst

(setq linia (read-line plik))
(cond

((= linia "C END.OF.NODES")(setq jeszcze2 nil))
((/= linia "C END.OF.NODES")

(if (= (substr linia 1 1) "C")

(progn

(princ)

;nie rob nic

);progn
(progn

;else

(setq

lista1 (PODZIEL_NA_PODLANCUCHY

linia
" "
0

)

);setq
(if (and

(/= (nth 0 lista1) "NODE.NUMBER")
(/= (nth 0 lista1) "NODE")

);and

(progn

(setq

numer (read (nth 0 lista1))
wsp_x (read (nth 1 lista1))
wsp_y (read (nth 2 lista1))

);setq
(if (/= (nth 3 lista1) nil)

(setq wsp_z (read (nth 3 lista1)))
(setq wsp_z 0.0)

;else

);if
(setq

wsp_wz (list wsp_x wsp_y wsp_z)
opis_wezla (list numer wsp_wz)
glob_lista_wezlow

(append glob_lista_wezlow (list

opis_wezla))

);setq

);progn

);if

);progn

);if

)

);cond

);progn

);while jeszcze2
(princ "\rCzytanie wezlow.

")

;----------
(princ)

);progn

);CZYTAJ_MODUL_NODES
;
;=================================================
;Czytanie modulu ELEMENTS
;
(defun CZYTAJ_MODUL_ELEMENTS

( / jeszcze2 linia lista1 numer grupa typ material

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

6:4

topologia dlugosc wezel opis_elementu

)

(progn

;----------
(princ "\nCzytanie elementow.....")
(setq glob_lista_elementow (list))
(setq jeszcze2 T)
(while jeszcze2

(progn

(setq linia (read-line plik))
(cond

((= linia "C END.OF.ELEMENTS")(setq jeszcze2 nil))
((/= linia "C END.OF.ELEMENTS")

(if (= (substr linia 1 1) "C")

(progn

(princ)

;nie rob nic

);progn
(progn

;else

(setq

lista1 (PODZIEL_NA_PODLANCUCHY

linia
" "
0

)

);setq
(if (/= (nth 0 lista1) "NUMBER")

(progn

;----------
(setq

numer (read (nth 0 lista1))
grupa (read (nth 1 lista1))
typ (read (nth 2 lista1))
material (read (nth 3 lista1))

);setq
;
(setq topologia (list))
(setq dlugosc (length lista1))
(for 'j 4 (- dlugosc 1) 1

'(progn

(setq

wezel (read (nth j lista1))
topologia

(append topologia (list wezel))

);setq

);progn

);for j
;----------
(setq

opis_elementu (append

(list numer)
(list grupa)
(list typ)
(list material)
topologia

);append

glob_lista_elementow

background image

6:5

BvupMJTQ!—!qsbluzd{oz!lvst

(append glob_lista_elementow (list

opis_elementu))

);setq

);progn

);if

);progn

);if

)

);cond

);progn

);while jeszcze2
(princ "\rCzytanie elementow.

")

;----------
(princ)

);progn

);CZYTAJ_MODUL_ELEMENTS
;
;=================================================
;Ustalenie takich granic rysunku, aby byl widoczny caly
model
;
(defun OBSZAR_MODELU ()

(progn

;----------
(MIN_MAX_NODES)
;----------
(command

"_limits" glob_punkt_ld glob_punkt_pg
"_zoom" "_all"

);command
;----------
(princ)

);progn

);OBSZAR_MODELU
;
;=================================================
;Znalezienie wezlow, w obrebie ktorych miesci sie
;cala konstrukcja
;
(defun MIN_MAX_NODES

( / x_min x_max y_min y_max wezel x y x_odl y_odl

x_r y_r p1 p2 w_min w_max w_min_real delta delta2

)

(progn

;----------
(if (= (length glob_lista_wezlow) 1)

(progn

;----------
(setq

wezel (nth 0 glob_lista_wezlow)
x (car (nth 1 wezel))
y (cadr (nth 1 wezel))
x_min (- x 6.0)
y_min (- y 4.5)
x_max (+ x 6.0)
y_max (+ y 4.5)

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

6:6

glob_punkt_ld (list x_min y_min)
glob_punkt_pg (list x_max y_max)

);setq
;----------

);progn

);if
;----------
(if (> (length glob_lista_wezlow) 1)

(progn

;----------
(setq

x_min nil x_max nil y_min nil y_max nil
p1 nil p2 nil

);setq
(for 'i 0 (- (length glob_lista_wezlow) 1) 1

'(progn

(setq

wezel (nth i glob_lista_wezlow)
x (car (nth 1 wezel))
y (cadr (nth 1 wezel))

);setq
;
(if (= i 0)

(progn

(setq

x_min x
x_max x
y_min y
y_max y

);setq

);progn

);if
;
(if (/= i 0)

(progn

(setq

x_min (min x_min x)
x_max (max x_max x)
y_min (min y_min y)
y_max (max y_max y)

);setq

);progn

);if
;

);progn

);for i
;----------
(setq

x_odl (- x_max x_min)
y_odl (- y_max y_min)
x_r (* 0.1 x_odl)
y_r (* 0.1 y_odl)

);setq
;----------
;skalowanie granic, gdy wymiar w osi y jest mniejszy
;od wymiaru w osi x

background image

6:7

BvupMJTQ!—!qsbluzd{oz!lvst

;
(if (< y_odl x_odl)

(progn

;----------
(setq

w_min (min x_odl y_odl)
w_max (max x_odl y_odl)
w_min_real (* 0.75 w_max)

);setq
;----------
(setq

delta (- w_min_real w_min)
delta2 (/ delta 2)

);setq
;----------
(setq

y_min (- y_min delta2)
y_max (+ y_max delta2)

);setq
;----------

);progn

);if
;----------
;skalowanie granic, gdy wymiar w osi y jest wiekszy
;lub rowny od wymiaru w osi x
;
(if (>= y_odl x_odl)

(progn

;----------
(setq

w_min (min x_odl y_odl)
w_max (max x_odl y_odl)
w_min_real (* 1.3333 w_max)

);setq
;----------
(setq

delta (- w_min_real w_min)
delta2 (/ delta 2)

);setq
;----------
(setq

x_min (- x_min delta2)
x_max (+ x_max delta2)

);setq
;----------

);progn

);if
;----------
;skrajne brzegi rysunku po przeskalowaniu
;
(setq

p1 (list (- x_min x_r)(- y_min y_r))
p2 (list (+ x_max x_r)(+ y_max y_r))

);setq
;----------
(setq

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

6:8

glob_punkt_ld p1
glob_punkt_pg p2

);setq
;----------
(princ)
;----------

);progn

);if

);progn

);MIN_MAX_NODES
;
;=================================================
;Funkcja pomocnicza przy powiekszeniach/pomniejszeniach
;
(defun GRANICE

(p1 p2 / x0 y0 x1 y1 x2 y2 deltax deltay kx ky k)

(progn

;----------
(setq

x0 12.0
y0

9.0

x1 (car p1)
y1 (cadr p1)
x2 (car p2)
y2 (cadr p2)
deltax (abs (- x2 x1))
deltay (abs (- y2 y1))
kx (/ deltax x0)
ky (/ deltay y0)
k (max kx ky)
;
glob_h_tekstu (* k glob_h_tekstu_0)
glob_wielkosc_punktu (* k glob_wielkosc_punktu_0)
glob_delta_tekstu

(+ glob_wielkosc_punktu (* 0.20

glob_wielkosc_punktu))

);setq
(setvar "pdsize" glob_wielkosc_punktu)
;----------
(princ)
;----------

);progn

);GRANICE
;
;=================================================
;Odbior wezlow
;
(defun ODBIERZ_WEZLY

( / wezel wsp_wz lista_dxf id_wz dane_dodatkowe

nowa_lista_dxf punkt id_op_wz opis_wezla
w_min w_max

)

(progn

;----------
(princ "\nOdbior wezlow.....")
(for 'i 0 (- (length glob_lista_wezlow) 1) 1

background image

6:9

BvupMJTQ!—!qsbluzd{oz!lvst

'(progn

;------------------------------
;pobranie danych o wezle
;
(setq

wezel (nth i glob_lista_wezlow)
glob_numer_wezla (car wezel)
wsp_wz (cadr wezel)

);setq
;------------------------------
;wykreslenie wezla
;
(command

"_layer" "_set" "wezly" ""
"_point" wsp_wz

);command
;------------------------------
;pobranie identyfikatora wezla
;
(setq

lista_dxf (entget (entlast))
id_wz (assoc 5 lista_dxf)
id_wz (cdr id_wz)

);setq
;------------------------------
;dopisanie danych dodatkowych dla wezla - numer

wezla

;
(setq

dane_dodatkowe

(list

(list

-3
(list

glob_appname
(cons 1070 glob_numer_wezla)

);list

);list

);list

);setq
;------------------------------
;dolaczenie danych dodatkowych do listy lista_dxf
;
(setq

nowa_lista_dxf (append lista_dxf dane_dodatkowe)

);setq
;------------------------------
;modyfikacja entycji
;
(entmod nowa_lista_dxf)
;------------------------------
;opisanie wezla na rysunku
;
(setq

punkt (list

(- (car wsp_wz) glob_delta_tekstu)

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

6::

(+ (cadr wsp_wz) glob_delta_tekstu)
(caddr wsp_wz)

);list

);setq
(command

"_layer" "_set" "numery_wezlow" ""
"_text" punkt glob_h_tekstu "" glob_numer_wezla

);command
;------------------------------
;pobranie identyfikatora opisu wezla
;
(setq

lista_dxf (entget (entlast))
id_op_wz (assoc 5 lista_dxf)
id_op_wz (cdr id_op_wz)

);setq
;------------------------------
;utworzenie listy opisujacej wezel
;
(setq

opis_wezla

(list

glob_numer_wezla
id_wz
id_op_wz
wsp_wz
'(0)
'(0)
'(0)

);list

);setq
;------------------------------
;wymiana opisu wezla na liscie glob_lista_wezlow
;
(setq

glob_lista_wezlow

(subst opis_wezla wezel glob_lista_wezlow)

);setq
;------------------------------

);progn

);for i
;----------
(command "_layer" "_set" "0" "")
;----------
;ustawienie zmiennej glob_numer_wezla
;
(

MIN_MAX_Z_LISTY

glob_lista_wezlow
"(car x1)"
1
-1
"w_min"
"w_max"

)
(setq glob_numer_wezla (+ w_max 1))

background image

711

BvupMJTQ!—!qsbluzd{oz!lvst

;----------
(princ "\rOdbior wezlow.

")

;----------
(princ)

);progn

);ODBIERZ_WEZLY
;
;=================================================
;Odbior elementow
;
(defun ODBIERZ_ELEMENTY

( / element liczba_wezlow el_min el_max)

(progn

;----------
(if (> (length glob_lista_elementow) 0)

(progn

;----------

(princ "\nOdbior elementow.....")
(for 'j 0 (- (length glob_lista_elementow) 1) 1

'(progn

;----------
;pobranie danych o elemencie
;
(setq

element (nth j glob_lista_elementow)
glob_numer_elementu (nth 0 element)
glob_grupa_elementu (nth 1 element)
glob_typ_elementu (nth 2 element)
glob_material_elementu (nth 3 element)

);setq
;----------
;odbior elementu w zaleznosci od jego typu
;
(cond

(

(or

(= glob_typ_elementu 34000)
(= glob_typ_elementu 34100)
(= glob_typ_elementu 34400)

);or

(setq liczba_wezlow 2)
(ODBIERZ_ELEMENT_2W)

)
(

(or

(= glob_typ_elementu 31100)
(= glob_typ_elementu 31110)
(= glob_typ_elementu 36640)
(= glob_typ_elementu 36620)
(= glob_typ_elementu 36100)
(= glob_typ_elementu 36110)
(= glob_typ_elementu 44110)
(= glob_typ_elementu 45110)
(= glob_typ_elementu 46110)
(= glob_typ_elementu 46115)

);or

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

712

(setq liczba_wezlow 3)
(ODBIERZ_ELEMENT_3W)

)
(

(or

(= glob_typ_elementu 31210)
(= glob_typ_elementu 31200)
(= glob_typ_elementu 36610)
(= glob_typ_elementu 36615)
(= glob_typ_elementu 36630)
(= glob_typ_elementu 36210)
(= glob_typ_elementu 36215)
(= glob_typ_elementu 36200)
(= glob_typ_elementu 44210)
(= glob_typ_elementu 44215)
(= glob_typ_elementu 44200)
(= glob_typ_elementu 45210)
(= glob_typ_elementu 46210)
(= glob_typ_elementu 46215)

);or

(setq liczba_wezlow 4)
(ODBIERZ_ELEMENT_4W)

)

);cond
;----------

);progn

);for j
;----------
(command "_layer" "_set" "0" "")
;----------
;ustalenie numeru ostatniego elementu w zbiorze

danych

;
(

MIN_MAX_Z_LISTY

glob_lista_elementow
"(car x1)"
1
-1
"el_min"
"el_max"

)
;----------
;pobranie danych ostatniego elementu
;
(setq

element (assoc el_max glob_lista_elementow)
glob_numer_elementu (nth 0 element)
glob_grupa_elementu (nth 4 element)
glob_typ_elementu (nth 5 element)
glob_material_elementu (nth 6 element)

);setq
;----------
;ustawienie zmiennej MODEMACRO
;
(USTAW_MODEMACRO)

background image

713

BvupMJTQ!—!qsbluzd{oz!lvst

;----------
;zwiekszenie numeru elementu o 1
;
(setq glob_numer_elementu (+ glob_numer_elementu

1))

;----------
(princ "\rOdbior elementow.

")

;----------

);progn

);if
;----------

(princ)

);progn

);ODBIERZ_ELEMENTY
;
;=================================================
;Ustawienie zmiennej MODEMACRO
;
;Funkcja wywolywana jest w nastepujacych przypadkach:
;- ustalenia grupy elementu
;- ustalenia typu elementu
;- ustalenia materialu elementu
;- odbioru zbioru danych DAT
;
(defun USTAW_MODEMACRO ( / x)

(progn

;----------
(setq

x (strcat

"Typ Elementu = "
(rtos glob_typ_elementu 2 0)
"

"

"Grupa = "
(rtos glob_grupa_elementu 2 0)
"

"

"Material = "
(rtos glob_material_elementu 2 0)

);strcat

);setq
(setvar "modemacro" x)
;----------
(princ)
;----------

);progn

);USTAW_MODEMACRO
;
;=================================================
;Odebranie elementu 2-wezlowego
;
(defun ODBIERZ_ELEMENT_2W

( / w1 w2 wezel1 wezel2 wsp_w1 wsp_w2 lista_dxf id_el

dane_dodatkowe nowa_lista_dxf lista1 wsp_sc_el
wsp_sc_el_glob punkt id_op_el opis_elementu

)

(progn

;----------

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

714

;pobranie topologii elementu
;
(setq

w1 (nth 4 element)
w2 (nth 5 element)

);setq
;----------
;wrysowanie elementu opisanego na wezlach w1 i w2
;
(setq

wezel1 (assoc w1 glob_lista_wezlow)
wezel2 (assoc w2 glob_lista_wezlow)
wsp_w1 (nth 3 wezel1)
wsp_w1 (trans wsp_w1 0 1)
wsp_w2 (nth 3 wezel2)
wsp_w2 (trans wsp_w2 0 1)

);setq
(command

"_layer" "_set" "elementy" ""
"_line" wsp_w1 wsp_w2 ""

);command
;----------
;pobranie identyfikatora elementu
;
(setq

lista_dxf (entget (entlast))
id_el (assoc 5 lista_dxf)
id_el (cdr id_el)

);setq
;----------
;dopisanie danych dodatkowych dla elementu - numer

elementu

;
(setq

dane_dodatkowe

(list

(list

-3
(list

glob_appname
(cons 1070 glob_numer_elementu)

);list

);list

);list

);setq
;----------
;dolaczenie danych dodatkowych do listy lista_dxf
;
(setq

nowa_lista_dxf (append lista_dxf dane_dodatkowe)

);setq
;----------
;modyfikacja entycji
;
(entmod nowa_lista_dxf)
;----------

background image

715

BvupMJTQ!—!qsbluzd{oz!lvst

;obliczenie wspolrzednych srodka ciezkosci elementu
;
(setq

wsp_sc_el (list

(/ (+ (car wsp_w1)(car wsp_w2)) 2.0)
(/ (+ (cadr wsp_w1)(cadr wsp_w2)) 2.0)
(/ (+ (caddr wsp_w1)(caddr wsp_w2)) 2.0)

);list

);setq
(setq wsp_sc_el_glob (trans wsp_sc_el 1 0))
;----------
;opisanie elementu na rysunku
;
(setq

punkt (list

(+ (car wsp_sc_el) glob_delta_tekstu)
(- (cadr wsp_sc_el) glob_delta_tekstu)
(caddr wsp_sc_el)

);list

);setq
(command

"_layer" "_set" "numery_elementow" ""
"_text" punkt glob_h_tekstu "" glob_numer_elementu

);command
;----------
;pobranie identyfikatora opisu elementu
;
(setq

lista_dxf (entget (entlast))
id_op_el (assoc 5 lista_dxf)
id_op_el (cdr id_op_el)

);setq
;----------
;utworzenie listy opisujacej element
;
(setq

opis_elementu

(list

glob_numer_elementu
id_el
id_op_el
wsp_sc_el_glob
glob_grupa_elementu
glob_typ_elementu
glob_material_elementu
w1
w2

);list

);setq
;----------
;wymiana na liscie glob_lista_elementow
;
(setq

glob_lista_elementow

(subst opis_elementu element glob_lista_elementow)

);setq

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

716

;----------
;wpisanie na liste glob_lista_wezlow numerow elementow
;opisanych na danym wezle
;
(DOPISZ_NUMER_ELEMENTU liczba_wezlow)
;----------
(princ)

);progn

);ODBIERZ_ELEMENT_2W
;
;=================================================
;
(defun ODBIERZ_ELEMENT_3W ()

(progn

;----------
;----------
(princ)
;----------

);progn

);ODBIERZ_ELEMENT_3W
;
;=================================================
;
(defun ODBIERZ_ELEMENT_4W ()

(progn

;----------
;----------
(princ)
;----------

);progn

);ODBIERZ_ELEMENT_4W
;
;=================================================
;Funkcja dopisujaca numer utworzonego elementu do
;listy glob_lista_wezlow dla wezlow w1 w2 w3 w4 - w
;zaleznosci od typu elementu
;
(defun DOPISZ_NUMER_ELEMENTU (_liczba_wezlow

/

)

(progn

;----------
(for 'l 1 _liczba_wezlow 1

'(progn

(cond

((= l 1)(setq num_wz w1))
((= l 2)(setq num_wz w2))
((= l 3)(setq num_wz w3))
((= l 4)(setq num_wz w4))

);cond
(setq

x1 (assoc num_wz glob_lista_wezlow)

;opis wezla

x2 (nth 4 x1)
x3 (append x2 (list glob_numer_elementu))
x4 (list

(nth 0 x1)

background image

717

BvupMJTQ!—!qsbluzd{oz!lvst

(nth 1 x1)
(nth 2 x1)
(nth 3 x1)
x3
(nth 5 x1)
(nth 6 x1)

);list

glob_lista_wezlow (subst x4 x1 glob_lista_wezlow)

);setq

);progn

);for l
(princ)

);progn

);DOPISZ_NUMER_ELEMENTU
;
;=================================================
;Funkcja testujaca.
;
(defun C:TEST ()

(progn

;----------
(RYSUNEK_PROTOTYPOWY)
(ZMIENNE_GLOBALNE)
(ODBIERZ_ZBIOR_DANYCH "$file_08.dat")
;----------
(princ)
;----------

);progn

);C:TEST
;
;=================================================
(load "prog_040")
(load "prog_063")
(princ "\nProgram zaladowany. ")
(princ "Komenda TEST uruchamia testowanie.")
(princ)
;=================================================
;*************************************************KONIEC

Wykonanie programu b

ędzie następujące:

Command: (load "prog_122")

↵↵

Program zaladowany. Komenda TEST uruchamia testowanie.

Command: TEST

↵↵

_cmdecho
New value for CMDECHO <1>: 0
Rozpoczecie czytania zbioru danych.
Czytanie wezlow.
Czytanie elementow.
Zakonczenie czytania zbioru danych.
Odbior wezlow.
Odbior elementow.

Command:

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

718

Po wczytaniu zbioru danych i odbiorze siatki MES linia statusu zawiera informacje
odno

śnie elementu o największym numerze

Typ Elementu = 34000

Grupa = 3

Material = 3

natomiast ekran graficzny zawiera nast

ępujący rysunek siatki:

Program zawiera nast

ępujące funkcje:

G

G

G

GPS

PS

PS

PS

Definicja p

ętli FOR w AutoLISPie.

SZTVO

SZTVO

SZTVO

SZTVOFL`QSPUPU

FL`QSPUPU

FL`QSPUPU

FL`QSPUPUZQPXZ

ZQPXZ

ZQPXZ

ZQPXZ

Ustawienia pocz

ątkowe środowiska pracy programu.

[

[

[

[NJFOOF`HM

NJFOOF`HM

NJFOOF`HM

NJFOOF`HMPCBMOF

PCBMOF

PCBMOF

PCBMOF

Ustawienie zmiennych globalnych, rejestracja aplikacji.

P

P

P

PECJFS[`[CJPS`E

ECJFS[`[CJPS`E

ECJFS[`[CJPS`E

ECJFS[`[CJPS`EBOZDI

BOZDI

BOZDI

BOZDI

Funkcja główna odbioru zbioru danych.

D[Z

D[Z

D[Z

D[ZUBK`[CJ

UBK`[CJ

UBK`[CJ

UBK`[CJPS`EBO

PS`EBO

PS`EBO

PS`EBOZDI

ZDI

ZDI

ZDI

Czytanie zbioru danych. Wywołanie funkcji czytaj

ących węzły i elementy.

background image

719

BvupMJTQ!—!qsbluzd{oz!lvst

D[ZUB

D[ZUB

D[ZUB

D[ZUBK`NPEVM`

K`NPEVM`

K`NPEVM`

K`NPEVM`OPEFT

OPEFT

OPEFT

OPEFT

Czytanie modułu w

ęzłów. Utworzenie listy węzłów.

D

D

D

D[ZUBK`N

[ZUBK`N

[ZUBK`N

[ZUBK`NPEVM`FMFNF

PEVM`FMFNF

PEVM`FMFNF

PEVM`FMFNFOUT

OUT

OUT

OUT

Czytanie modułu elementów. Utworzenie listy elementów.

PCT[

PCT[

PCT[

PCT[BS`NPE

BS`NPE

BS`NPE

BS`NPEFMV

FMV

FMV

FMV

Ustalenie takich granic rysunku, aby była widoczna cała konstrukcja.

NJO`N

NJO`N

NJO`N

NJO`NBY`OPE

BY`OPE

BY`OPE

BY`OPEFT

FT

FT

FT

Znalezienie dwóch skrajnych w

ęzłów, w obrębie których mieści się cała konstrukcja.

HSBOJ

HSBOJ

HSBOJ

HSBOJDF

DF

DF

DF

Funkcja pomocnicza przy powi

ększeniach/pomniejszeniach.

PECJFS

PECJFS

PECJFS

PECJFS[`XF[MZ

[`XF[MZ

[`XF[MZ

[`XF[MZ

Odbiór w

ęzłów — narysowanie i opisanie węzłów, dodanie danych dodatkowych do

w

ęzła, uzupełnienie listy węzłów.

PECJFS[`F

PECJFS[`F

PECJFS[`F

PECJFS[`FMFNFOUZ

MFNFOUZ

MFNFOUZ

MFNFOUZ

Odbiór elementów — narysowanie i opisanie elementów, dodanie danych dodatkowych
dla elementu, uzupełnienie listy elementów.

VTUBX`

VTUBX`

VTUBX`

VTUBX`NPEFNB

NPEFNB

NPEFNB

NPEFNBDSP

DSP

DSP

DSP

Ustawienie zmiennej MODEMACRO.

PECJFS

PECJFS

PECJFS

PECJFS[`FMFNFOU`

[`FMFNFOU`

[`FMFNFOU`

[`FMFNFOU`3X

3X

3X

3X

Odebranie elementu 2-w

ęzłowego.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

71:

PECJ

PECJ

PECJ

PECJFS[`FMFNFO

FS[`FMFNFO

FS[`FMFNFO

FS[`FMFNFOU`4X

U`4X

U`4X

U`4X

Odebranie elementu 3-w

ęzłowego.

PE

PE

PE

PECJFS[`FMFNF

CJFS[`FMFNF

CJFS[`FMFNF

CJFS[`FMFNFOU`5X

OU`5X

OU`5X

OU`5X

Odebranie elementu 4-w

ęzłowego.

E

E

E

EPQJT[`OV

PQJT[`OV

PQJT[`OV

PQJT[`OVNFS`FMFNFOU

NFS`FMFNFOU

NFS`FMFNFOU

NFS`FMFNFOUV

V

V

V

Funkcja dopisuje numer utworzonego elementu do listy w

ęzłów dla podanego węzła.

D;UFTU

D;UFTU

D;UFTU

D;UFTU

Funkcja testuj

ąca — odbiór zbioru danych $FILE_08.DAT.

Poni

żej omówiono poszczególne funkcje programu:

S

S

S

SZTVOFL`

ZTVOFL`

ZTVOFL`

ZTVOFL`QSPUPUZQP

QSPUPUZQP

QSPUPUZQP

QSPUPUZQPXZ

XZ

XZ

XZ

Funkcja ustawia

środowisko pracy programu: wyłącza echo komend i znaczniki

punktów, wł

ącza identyfikatory elementów, tworzy warstwy i przyporządkowuje im

kolory oraz ustala wygl

ąd punktu na rysunku.

[NJF

[NJF

[NJF

[NJFOOF`HMPC

OOF`HMPC

OOF`HMPC

OOF`HMPCBMOF

BMOF

BMOF

BMOF

Funkcja ustawia warto

ści następujących zmiennych globalnych:

glob_lista_wezlow

lista danych o w

ęzłach,

glob_lista_elementow

lista danych o elementach,

glob_punkt_ld, glob_punkt_pg

współrz

ędne lewego dolnego i prawego górnego

rogu okna podstawowego, wzgl

ędem którego

ustawiana jest pocz

ątkowa wielkość tekstu oraz

wielko

ść punktu,

glob_appname

nazwa, pod któr

ą zarejestrujemy aplikację — jest

to potrzebne, gdy chcemy doda

ć dane dodatkowe

dla

wybranych

elementów

rysunkowej

bazy

danych AutoCADa,

glob_h_tekstu

wielko

ść tekstu opisującego numer węzła i ele-

mentu dla okna obejmuj

ącego całą konstrukcję —

w chwili startu programu jest ona równa wielko

ści

tekstu dla okna podstawowego 12x9,

background image

721

BvupMJTQ!—!qsbluzd{oz!lvst

glob_h_tekstu_0

wielko

ść tekstu opisującego numer węzła i ele-

mentu dla okna podstawowego — nie ulega zmia-
nie przez cały czas działania programu,

glob_delta_tekstu

odległo

ść tekstu opisującego numer węzła i ele-

mentu w osi X i Y od

środka węzła i elementu,

glob_wielkosc_punktu

wielko

ść punktu reprezentującego węzeł konstru-

kcji dla okna obejmuj

ącego całą konstrukcję —

w chwili startu programu jest ona równa wielko

ści

punktu dla okna podstawowego 12x9,

glob_wielkosc_punktu_0

wielko

ść punktu reprezentującego węzeł konstru-

kcji dla okna podstawowego — nie ulega zmianie
przez cały czas działania programu,

glob_typ_elementu

typ elementu (belka) w momencie startu programu,

glob_grupa_elementu

grupa elementu w momencie startu programu,

glob_material_elementu

materiał elementu w momencie startu programu.

Na samym ko

ńcu rejestrujemy aplikację wykorzystując funkcję regapp o składni:

(regapp

application)

Funkcja rejestruje nazw

ę aplikacji (programu użytkowego) w aktualnym rysunku Auto-

CADa. Nazwa programu u

żytkowego, przekazywana w argumencie application, jest

podstawowym parametrem wykorzystywanym do grupowania, przechowywania, uzyskiwa-
nia i modyfikowania zdefiniowanych przez taki program dodatkowych danych elementów.

PE

PE

PE

PECJFS[`[CJPS`E

CJFS[`[CJPS`E

CJFS[`[CJPS`E

CJFS[`[CJPS`EBOZDI

BOZDI

BOZDI

BOZDI

Funkcja odbiera zbiór danych przekazany w argumencie wywołania funkcji
nazwa_zbioru. Po otwarciu pliku danych do odczytu, ustawiamy globalny układ
współrz

ędnych (współrzędne węzłów zapisane w pliku podane są w układzie global-

nym), po czym wykonujemy funkcje czytaj

ące zbiór danych, tworzące listy węzłów

i elementów oraz rysuj

ące na ich podstawie siatkę MES konstrukcji.

D[Z

D[Z

D[Z

D[ZUBK`[CJ

UBK`[CJ

UBK`[CJ

UBK`[CJPS`EBO

PS`EBO

PS`EBO

PS`EBOZDI

ZDI

ZDI

ZDI

Funkcja czyta zbiór danych i wywołuje funkcje odbioru w

ęzłów i elementów. Funkcja

działa w p

ętli jeszcze1, która wykonywana jest do chwili odczytania linii

"END.OF.DATA" lub do osi

ągnięcia końca zbioru. Poszczególne linie pliku

odbieramy za pomoc

ą funkcji read-line i podstawiamy pod zmienną linia. Gdy linia

pliku zawiera ła

ńcuch "NODES", wywoływana jest funkcja CZYTAJ_MODUL

_NODES, odbieraj

ąca moduł węzłów, po czym następuje powrót do pętli while

jeszcze1. Gdy linia pliku zawiera ła

ńcuch "ELEMENTS", wywoływana jest funkcja

CZYTAJ_MODUL_ELEMENTS, odbieraj

ąca moduł elementów, po czym następuje

powrót do p

ętli while jeszcze1.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

722

D[ZUB

D[ZUB

D[ZUB

D[ZUBK`NPEVM`

K`NPEVM`

K`NPEVM`

K`NPEVM`OPEFT

OPEFT

OPEFT

OPEFT

Funkcja czyta moduł w

ęzłów i tworzy na tej podstawie listę węzłów. Funkcja działa

w p

ętli jeszcze2, która wykonywana jest do chwili odczytania linii "C END.OF

.NODES". Je

żeli odczytana linia nie jest końcem modułu węzłów, sprawdzamy

dodatkowo, czy nie jest to linia komentarza (du

ża litera C w pierwszej kolumnie, po

której wyst

ępuje co najmniej jedna spacja). Jeśli odczytana linia nie jest komentarzem,

rozbijamy

j

ą na listę łańcuchów za pomocą funkcji PODZIEL_NA_

PODLANCUCHY. Warto

ść zwrotną funkcji podstawiamy pod zmienną lista1.

Nast

ępnie sprawdzamy, czy zerowy element listy nie jest nagłówkiem modułu węzłów

("NODE.NUMBER" lub "NODE"). Je

śli nie, oznacza to, że lista zawiera dane

o w

ęźle. Pobieramy z niej wówczas dane odnośnie numeru węzła (numer) oraz jego

współrz

ędnych X i Y (wsp_x, wsp_y). Jeśli współrzędna Z węzła została podana,

podstawiamy j

ą pod zmienną wsp_z, w przeciwnym wypadku ustawiamy wartość

współrz

ędnej Z na 0. Następnie łączymy współrzędne węzła w listę wsp_wz, tworzymy

list

ę opis_węzla, zawierającą numer węzła oraz jego współrzędne, oraz dołączamy opis

w

ęzła do listy glob_lista_wezlow.

Przykładowo, dla linii danych

"

1

1.0000

1.0000

0.0000"

lista opis_wezla ma posta

ć

(1 (1.0 1.0 0.0))

D

D

D

D[ZUBK`N

[ZUBK`N

[ZUBK`N

[ZUBK`NPEVM`FMFNF

PEVM`FMFNF

PEVM`FMFNF

PEVM`FMFNFOUT

OUT

OUT

OUT

Funkcja czyta moduł elementów i tworzy na tej podstawie list

ę elementów. Funkcja

działa w p

ętli jeszcze2, która wykonywana jest do chwili odczytania linii "C END

.OF.ELEMENTS". Je

żeli odczytana linia nie jest końcem modułu elementów,

sprawdzamy dodatkowo, czy nie jest to linia komentarza (du

ża litera C w pierwszej

kolumnie, po której wyst

ępuje co najmniej jedna spacja). Jeżeli odczytana linia nie jest

komentarzem, rozbijamy j

ą na listę łańcuchów za pomocą funkcji PODZIEL_NA

_PODLANCUCHY. Warto

ść zwrotną funkcji podstawiamy pod zmienną lista1. Nastę-

pnie sprawdzamy, czy zerowy element listy nie jest nagłówkiem modułu elementów
("NUMBER"). Je

śli nie, oznacza to, że lista zawiera dane o elemencie. Pobieramy

z niej wówczas dane odno

śnie numeru elementu, jego grupy, typu, materiału oraz

topologii, tworzymy list

ę opisu elementu opis_elementu oraz dołączamy opis elementu

do listy glob_lista_elementow.

Przykładowo, dla linii danych

"

1

1

34000

1

1 2"

lista opis_elementu ma posta

ć

(1 1 34000 1 1 2)

background image

723

BvupMJTQ!—!qsbluzd{oz!lvst

PCT[

PCT[

PCT[

PCT[BS`NPE

BS`NPE

BS`NPE

BS`NPEFMV

FMV

FMV

FMV

Funkcja ustawia takie granice rysunku, aby był w nich widoczny cały model siatki
MES.

NJO`N

NJO`N

NJO`N

NJO`NBY`OPE

BY`OPE

BY`OPE

BY`OPEFT

FT

FT

FT

Funkcja pomocnicza, wywoływana w funkcji OBSZAR_MODELU, znajduj

ąca współ-

rz

ędne dwóch punktów (węzłów), w obrębie których mieści się cała konstrukcja.

Funkcja zmienia warto

ści zmiennych globalnych glob_punkt_ld oraz glob_punkt_pg.

W przypadku, gdy na li

ście węzłów znajduje się tylko jeden węzeł, umieszczamy go w

środku okna o wymiarach 12x9.

Je

śli konstrukcja zawiera dwa lub więcej węzłów, znajdujemy współrzędne jej dwóch

skrajnych punktów (x_min y_min), (x_max y_max), nast

ępnie znajdujemy długości

boków prostok

ąta, którego przeciwległe wierzchołki rozpięte są na tych punktach —

x_odl, y_odl. Maj

ąc obliczone długości boków prostokąta, obliczamy odległości x_r

i y_r, o jakie powi

ększymy długości obliczonych boków. W ten sposób wokół

konstrukcji powstanie dodatkowy wolny obszar (odpowiada to w przybli

żeniu komen-

dzie AutoCADa ZOOM 0.9X).

Kolejn

ą czynnością wykonywaną przez funkcję jest skalowanie granic rysunku.

Rozró

żniamy tutaj dwa przypadki:

wymiar prostok

ąta w osi Y jest mniejszy od wymiaru w osi X — skalujemy

przez współczynnik 0.75 (9 / 12) i dopasowujemy wymiary okna w osi Y,

wymiar prostok

ąta w osi Y jest większy lub równy od wymiaru w osi X —

skalujemy przez współczynnik 1.3333 (12 / 9) i dopasowujemy wymiary okna w
osi X.

Na koniec obliczamy współrz

ędne skrajnych brzegów rysunku po przeskalowaniu p1

i p2 oraz ustawiamy warto

ści zmiennych globalnych glob_punkt_ld i glob_punkt_pg.

HSBOJ

HSBOJ

HSBOJ

HSBOJDF

DF

DF

DF

Funkcja wywoływana jest z dwoma argumentami: p1 i p2, okre

ślającymi skrajne brzegi

rysunku, w obr

ębie których mieści się cała konstrukcja. Funkcja stosowana jest przy

powi

ększeniach/pomniejszeniach, a jej zadaniem jest zachowanie na ekranie stałej

wielko

ści punktu reprezentującego węzeł, stałej wysokości tekstu opisującego węzły

i elementy oraz stałej odległo

ści opisu węzła i elementu od środka węzła i środka ele-

mentu. Skalowanie wymiarów przeprowadzamy w stosunku do okna podstawowego
12x9. Funkcja zmienia warto

ści zmiennych globalnych glob_h_tekstu, glob_wielkosc

_punktu i glob_delta_tekstu oraz ustawia now

ą wartość zmiennej systemowej PDSIZE.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

724

PECJFS

PECJFS

PECJFS

PECJFS[`XF[MZ

[`XF[MZ

[`XF[MZ

[`XF[MZ

Funkcja odbiera w

ęzły — rysuje i opisuje węzeł, dodaje dane dodatkowe do węzła i uzu-

pełnia brakuj

ące dane na liście glob_lista_wezlow. Funkcja działa w pętli FOR, przeglą-

daj

ąc kolejne dane o węzłach. Procedura odbioru węzła przedstawia się następująco:

pobierz dane kolejnego w

ęzła z listy glob_lista_wezlow: dane o węźle (wezel),

numer w

ęzła (glob_numer_wezla) oraz jego współrzędne (wsp_wz),

narysuj w

ęzeł na warstwie "WEZLY",

pobierz identyfikator w

ęzła (id_wz),

utwórz dane dodatkowe dla w

ęzła (dane_dodatkowe), zawierające numer węzła.

Przy

tworzeniu

danych

dodatkowych

korzystamy

z

nazwy

aplikacji

umieszczonej w zmiennej globalnej glob_appname,

doł

ącz dane dodatkowe do listy DXF opisu węzła (nowa_lista_dxf),

dokonaj modyfikacji listy nowa_lista_dxf, opisuj

ącej węzeł (lista zawiera już

dane dodatkowe),

opisz nowo powstały w

ęzeł (wstaw numer węzła na warstwie "NUMERY

_WEZLOW"),

pobierz identyfikator opisu w

ęzła,

utwórz list

ę opisującą węzeł, zawierającą wszystkie niezbędne informacje,

wymie

ń opis węzła na liście glob_lista_wezlow,

b

ędąc już poza pętlą FOR, a więc po przetworzeniu całej listy węzłów, ustaw

warto

ść zmiennej w_max na największy numer węzła występującego na liście

glob_lista_wezlow,

ustaw warto

ść zmiennej glob_numer_wezla jako w_max + 1.

PECJFS[`F

PECJFS[`F

PECJFS[`F

PECJFS[`FMFNFOUZ

MFNFOUZ

MFNFOUZ

MFNFOUZ

Funkcja odbiera elementy — pobiera dane o elemencie i wywołuje funkcje odbioru elemen-
tu w zale

żności od jego typu (liczby węzłów). Funkcja działa w pętli FOR, przeglądając

kolejne dane o elementach. Procedura odbioru w

ęzła przedstawia się następująco:

pobierz dane kolejnego elementu z listy glob_lista_elementow: dane o elemencie
(element),

numer

elementu

(glob_numer_elementu),

grupa

elementu

(glob_grupa_elementu), typ_elementu (glob_typ_elementu) oraz materiał ele-
mentu (glob_material_elementu),

w zale

żności od typu elementu (liczby jego węzłów), wywołaj odpowiednią

funkcj

ę do odbioru elementu,

background image

725

BvupMJTQ!—!qsbluzd{oz!lvst

b

ędąc już poza pętlą FOR, a więc po przetworzeniu całej listy elementów, ustaw

warto

ść zmiennej el_max na największy numer elementu występującego na liście

glob_lista_elementow,

pobierz dane dla tego elementu i podstaw je pod odpowiednie zmienne globalne
(glob_numer_elementu,

glob_grupa_elementu,

glob_typ_elementu,

glob_material_elementu),

ustaw now

ą wartość zmiennej systemowej MODEMACRO,

zwi

ększ numer elementu o 1.

VTUBX`

VTUBX`

VTUBX`

VTUBX`NPEFNB

NPEFNB

NPEFNB

NPEFNBDSP

DSP

DSP

DSP

Funkcja ustawia now

ą wartość zmiennej systemowej MODEMACRO. Funkcja

wywoływana jest w nast

ępujących przypadkach:

ustalenia nowej bie

żącej grupy elementu,

ustalenia nowego bie

żącego typu elementu,

ustalenia nowego bie

żącego materiału elementu,

odbioru zbioru danych DAT.

PECJFS

PECJFS

PECJFS

PECJFS[`FMFNFOU`

[`FMFNFOU`

[`FMFNFOU`

[`FMFNFOU`3X

3X

3X

3X

Funkcja odbiera element 2-w

ęzłowy. Jest ona wywoływana z funkcji ODBIERZ

_ELEMENTY (korzysta ze zmiennej lokalnej tej funkcji o nazwie element) i wykonuje
nast

ępujące czynności:

pobiera topologie elementu — numery w

ęzłów w1 i w2,

pobiera dane o w

ęzłach z listy glob_lista_wezlow i dokonuje transformacji ich

współrz

ędnych do układu lokalnego,

rysuje element jako lini

ę na warstwie "ELEMENTY",

pobiera identyfikator elementu,

tworzy list

ę danych dodatkowych dla elementu — numer elementu,

doł

ącza dane dodatkowe do listy opisującej element,

modyfikuje list

ę opisującą element (lista zawiera już dane dodatkowe),

oblicza współrz

ędne środka ciężkości elementu,

opisuje element na rysunku (numer elementu na warstwie
"NUMERY_ELEMENTOW"),

pobiera identyfikator opisu elementu,

tworzy list

ę opisującą element,

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

726

wymienia opis elementu na li

ście glob_lista_elementow,

wywołuje funkcj

ę DOPISZ_NUMER_ELEMENTU.

PECJ

PECJ

PECJ

PECJFS[`FMFNFO

FS[`FMFNFO

FS[`FMFNFO

FS[`FMFNFOU`4X

U`4X

U`4X

U`4X

Funkcja odbiera element 3-w

ęzłowy. Z uwagi na długość pliku przykładowego oraz na

to,

że w zbiorze danych występują tylko elementy 2-węzłowe, kod funkcji został

pomini

ęty w przykładzie.

PE

PE

PE

PECJFS[`FMFNF

CJFS[`FMFNF

CJFS[`FMFNF

CJFS[`FMFNFOU`5X

OU`5X

OU`5X

OU`5X

Funkcja odbiera element 4-w

ęzłowy. Z uwagi na długość pliku przykładowego oraz na

to,

że w zbiorze danych występują tylko elementy 2-węzłowe, kod funkcji został

pomini

ęty w przykładzie.

E

E

E

EPQJT[`OV

PQJT[`OV

PQJT[`OV

PQJT[`OVNFS`FMFNFOU

NFS`FMFNFOU

NFS`FMFNFOU

NFS`FMFNFOUV

V

V

V

Funkcja dopisuje numer utworzonego elementu do listy glob_lista_wezlow dla zmien-
nych w1, w2, w3 i w4 (numery w

ęzłów), w zależności od typu elementu.

D;UFTU

D;UFTU

D;UFTU

D;UFTU

Funkcja testuj

ąca, wywołująca poszczególne funkcje programu.

26/6/4/!Ped

26/6/4/!Ped

26/6/4/!Ped

26/6/4/!Ped{zu!ebozdi!

{zu!ebozdi!

{zu!ebozdi!

{zu!ebozdi!x!qptubdj!mjtu

x!qptubdj!mjtu

x!qptubdj!mjtu

x!qptubdj!mjtuz

z

z

z

Program PROG_116 pokazał nam sposób zapisu wybranych modułów zbioru danych
programu PAFEC FE (moduł steruj

ący, dane o węzłach i dane o elementach) w postaci

jednej listy. Tak utworzony zbiór danych nie mo

że być bezpośrednio wczytany przez pro-

gram obliczeniowy PAFEC, był to jednak przykład na zapis zbioru danych w innej postaci.

Zadaniem programu przedstawionego poni

żej jest wczytanie tak utworzonego zbioru danych

do jednej listy oraz wyodr

ębnienie z niej listy węzłów i listy elementów. Tak przygotowane

listy s

ą już gotowe do dalszego przetwarzania (odbiór węzłów, odbiór elementów).

;*************************************************PROG_123
;Odczyt danych zapisanych do pliku $FILE_04.DAT
;w postaci jednej listy.
;
;=================================================
;Wczytanie zawartosci pliku do zmiennej LISTA.
;
(defun WCZYTAJ_PLIK (nazwa_pliku / plik lista)

(progn

background image

727

BvupMJTQ!—!qsbluzd{oz!lvst

;----------

(setq plik (findfile nazwa_pliku))

(if plik

(progn

(setq

lista (load plik)
glob_lista_wezlow (cdr (assoc 'NODES lista))
glob_lista_elementow (cdr (assoc 'ELEMENTS lista))

);setq

);progn

;

(progn

;else

(princ

(strcat

"\nNie znaleziono pliku "
nazwa_pliku
"."

);strcat

);princ

);progn

);if plik
;----------
(princ)
;----------

);progn

);WCZYTAJ_PLIK
;
;=================================================
;Funkcja testujaca.
;
(defun C:TEST ()

(progn

;----------
(WCZYTAJ_PLIK "$file_04.dat")

;

(WCZYTAJ_PLIK "brak.dat")

(textscr)
(princ "\nLista wezlow.\n")
(princ glob_lista_wezlow)
(princ "\n\nLista elementow.\n")
(princ glob_lista_elementow)
;----------
(princ)
;----------

);progn

);C:TEST
;
;=================================================
(princ "\nProgram zaladowany. ")
(princ "Komenda TEST uruchamia testowanie.")
(princ)
;=================================================
;*************************************************KONIEC

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

728

Wykonanie powy

ższego programu będzie następujące.

Command: (load "prog_123")

↵↵

Program zaladowany. Komenda TEST uruchamia testowanie.

Command: test

↵↵

Lista wezlow.
((1 (1.0 1.0 0.0))(2 (3.0 8.0 0.0))(3 (6.0 1.0 0.0))(4 (9.0
8.0 0.0))(5 (11.0 1.0 0.0))(100000 (1000000.0 1000000.0
1000000.0)))

Lista elementow.
((1 1 34000 1 1 2)(2 1 34000 1 2 3)(3 1 34000 1 3 4)(4 1
34000 1 4 5)(5 2 34000 2 1 3)(6 2 34000 2 3 5))

Command:

Omówmy teraz wyró

żnione linie i bloki programu.

Wykorzystując funkcję findfile, szukamy pliku podanego w argumencie wy-

wołania funkcji WCZYTAJ_PLIK.

Ten blok instrukcji wykonywany jest w przypadku znalezienia pliku.

Wykorzystuj

ąc funkcję load, wczytujemy plik, podstawiając pod zmienną lista

warto

ść zwrotną funkcji load. Jak zapewne wiesz, funkcja load zwraca wartość

ostatniego wyra

żenia w pliku. Ponieważ jedynym wyrażeniem w pliku $FILE

_04.DAT jest lista poprzedzona znakiem kwotowania, jest ona zwracana bez
ewaluacji przez funkcj

ę load. Następnie wykorzystując funkcję cdr w połącze-

niu z assoc, tworzymy listy danych o w

ęzłach i elementach.

Ten blok instrukcji jest wykonywany wówczas, gdy funkcja findfile nie znalazła

szukanego pliku.

26/6/5/!Gpsn

26/6/5/!Gpsn

26/6/5/!Gpsn

26/6/5/!Gpsnbupxboz!ped

bupxboz!ped

bupxboz!ped

bupxboz!ped{zu!ebozdi

{zu!ebozdi

{zu!ebozdi

{zu!ebozdi

Interpreter AutoLISPu zawarty w pakiecie AutoCAD posiada tylko dwie funkcje do odczytu
danych z pliku dyskowego: readchar odczytuj

ącą jeden znak i zwracającą kod ASCII

odczytanego znaku oraz read-line odczytuj

ącą i zwracającą łańcuch alfanumeryczny.

U

żytkownikom AutoLISPu przydałaby się uniwersalna funkcja do obsługi czytania

danych z plików dyskowych (taka jak funkcja read w j

ęzyku FORTRAN czy fscanf

w j

ęzyku C). Poniżej zostanie zaprezentowana trójargumentowa funkcja SSCANF,

zawarta w pliku SCANF1.LLB, realizuj

ąca powyższe zadanie.

Plik przetwarzany funkcj

ą SSCANF powinien spełniać następujące warunki:

plik mo

że mieć dowolną strukturę — może mieć zmienną długość linii, zawierać

dowolnie zło

żone listy, pary kropkowe itp.,

linia pliku mo

że zawierać dane numeryczne, łańcuchy i listy umieszczone w do-

wolnej kolejno

ści,

background image

729

BvupMJTQ!—!qsbluzd{oz!lvst

dane mog

ą być oddzielone od siebie dowolną liczbą spacji,

je

śli w linii danych ma znajdować się łańcuch zagnieżdżony np. "to jest

"ła

ńcuch" w łańcuchu" — daną taką należy umieścić w liście — ("to jest

"ła

ńcuch" w łańcuchu"),

ka

żda linia tekstu jest traktowana jako jeden łańcuch tekstowy — decyzję, ile

linii tekstu zostanie przekazanych do bufora (argumentu input_string) —
podejmuje u

żytkownik.

Funkcja SSCANF czyta dane ze strumienia wej

ściowego. Strumień ten należy utworzyć

wcze

śniej otwierając plik do odczytu funkcją open i czytając jedną lub więcej linii

funkcj

ą read-line. W przypadku, gdy strumień wejściowy ma zawierać kilka linii

z pliku, nale

ży je połączyć w jeden łańcuch funkcją strcat. Tego typu rozwiązanie

posiada nast

ępujące zalety w porównaniu z bezpośrednim odczytem z pliku:

mo

żna bardzo łatwo pominąć linie, których nie chcemy przetwarzać funkcją

SSCANF,

mo

żemy łatwo zmieniać liczbę linii, które są jednorazowo ładowane do

strumienia — jest to szczególnie wa

żne w przypadku zmiennej liczby linii

tworz

ących poszczególne moduły danych,

funkcja SSCANF mo

że być również użyta do czytania danych podanych z kla-

wiatury — w tym przypadku strumie

ń wejściowy pobieramy wykorzystując

funkcj

ę getstring.

;*************************************************SCANF1.LLB
;Funkcja (SSCANF input_string format output_list) sluzy do
;formatowanego lub swobodnego odczytu danych z pliku
;tekstowego lub z bufora wskazujacego lancuch znakow.
;
;Funkcja wywolywana jest z trzema argumentami:
;input_string - lancuch (bufor) z danymi do przetworzenia,
;format - lancuch podajacy format czytanych danych.
;

Argument ten moze przyjac dwie wartosci:

;

format = "" - czytanie swobodne - argument input_string

;

zostaje rozbity na liste lancuchow. Otrzymana

lista
;

jest podstawiana pod nazwe zmiennej przekazana

;

w argumencie output_list,

;

format /= "" - czytanie formatowane - argument

input_string
;

zostaje rozbity na liste lancuchow.

;

Poszczegolne elementy listy po przeformatowaniu na

;

odpowiedni typ zostaja podstawione pod odpowiednie

;

nazwy zmiennych.

;

Argument format w przypadku czytania formatowanego

sklada
;

sie z dwoch glownych sekcji:

;

- sekcja typu zmiennych

;

%d - typ calkowity

;

%f - typ rzeczywisty

;

%s - string

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

72:

;

%l - lista

;

- sekcja nazw zmiennych

;

Nazwe zmiennej stanowi ciag dowolnych znakow ASCII

(oprocz
;

spacji, apostrofu, srednika i nawiasow), przy czym

pierwszym
;

znakiem nazwy zmiennej musi byc litera

;

np. &x1 - wartosc zmiennej po przeformatowaniu na

odpowiedni
;

typ zostanie umieszczona pod zmienna x1.

;

Znak & jest tylko zaznaczeniem, ze chodzi tu o nazwe

;

zmiennej i nie wchodzi do nazwy zmiennej.

;

Gdy argument input_string zawiera wiecej zmiennych

niz
;

zadeklarowano w argumencie format - zmienne

nadmiarowe
;

zostana obciete.

;

Gdy argument input_string zawiera mniej zmiennych niz

;

zadeklarowano w argumencie format - zmiennym

;

niedomiarowym zostanie nadana wartosc nil.

;output_list - lancuch z nazwa zmiennej, pod ktora zostanie
;

podstawiona lista lancuchow otrzymana po rozbiciu

argumentu
;

input_string na poszczegolne wartosci - argument ten

;

wykorzystywany jest tylko w przypadku swobodnego

odczytu danych.
;
;Funkcje pomocnicze (deklarowane wewnatrz funkcji glownej):
;(PAUSE_1)
;(ERROR_SSCANF msg)
;(CHECK_ARGUMENT_TYPE argument_name argument_type
output_message)
;(READ_LISP_DATA input_string_1 output_list_1)
;(CHECK_ARGUMENT_FORMAT)
;
;Przyklady wywolania funkcji SSCANF
;
;(SSCANF "1 2 (1)" "%d &x1 %f &x2 %l &x3" "")
;

!x1 => 1

;

!x2 => 2.0

;

!x3 => (1)

;
;(SSCANF "1" "%d %d &x1 &x2" "")
;

!x1 => 1

;

!x2 => nil

;
;(setq x (getstring T "Podaj imie i nazwisko : "))
;

=> Marek Dudek => !x => "Marek Dudek"

;(SSCANF x "%s &x1 %s &x2" "")
;

!x1 => "Marek"

;

!x2 => "Dudek"

;
;(setq plik (open "test.dat" "r"))
;(setq x (read-line plik))
;

!x => "(1 . 2) (1 (2 "test")) demo"

background image

731

BvupMJTQ!—!qsbluzd{oz!lvst

;(SSCANF x "" "#x1")
;

!#x1 => ("(1 . 2)" "(1 (2 "test"))" "demo")

;
;=================================================
;
(defun SSCANF

(input_string format output_list /

#list_1 #list_2 list_type list_name msg_all msg_1 msg_2
msg_3 bufor_read i type_i name_i value_i

)

(progn

;========================================
;Definicje funkcji pomocniczych
;
;----------------------------------------
;
(defun PAUSE_1 ()

(progn

;----------
(getstring "\nNacisnij ENTER...")
(princ)
;----------

);progn

);PAUSE_1
;
;----------------------------------------
;Wewnetrzna obsluga bledow
;
(defun ERROR_SSCANF (msg)

(progn

;----------
(if (/= msg "quit / exit abort")

(progn

(terpri)
(princ msg)
(terpri)
(setq *error* old_mistake)

);progn
(progn

;else

(setq *error* old_mistake)

);progn

);if
;----------
(princ)
;----------

);progn

);ERROR_SSCANF
;
;----------------------------------------
;Funkcja pomocnicza do sprawdzania typu argumentu
;
;Argumenty argument_name, argument_type oraz

output_message

;sa danymi typu string.
;

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

732

(defun CHECK_ARGUMENT_TYPE

(argument_name argument_type output_message / msg)

(progn

;----------
(setq msg "")

;reset msg

(set (read output_message) "")
(if (/= (type (eval (read argument_name))) (read

argument_type))

(progn

(setq

msg (strcat

"Argument "
argument_name
" musi byc typu "
argument_type

);strcat

);setq
(set (read output_message) msg)

);progn

);if
;----------
(princ)
;----------

);progn

);CHECK_ARGUMENT_TYPE
;----------------------------------------
;Funkcja rozbija lancuch input_string na liste lancuchow

i podstawia

;otrzymana liste pod nazwe zmiennej przekazana w

argumencie output_list_1

;
(defun READ_LISP_DATA

(input_string_1 output_list_1 /

index i value_in value_out string list_str char

case lb rb

)

(progn

;----------
(setq

index (strlen input_string_1)
i 1

;licznik petli

value_in 0
value_out 0
string ""
list_str (list)

);setq
;----------
(repeat index

(progn

;----------
(setq char (substr input_string_1 i 1))
;----------
(if (and (= value_in 0)(= value_out 0))

(progn

(cond

background image

733

BvupMJTQ!—!qsbluzd{oz!lvst

((= char " ")

(setq value_in 0))

((= char "\"")

(setq value_in 1 case 0))

((= char (chr 40))(setq value_in 2 lb 0 rb 0))
((= char (chr 41))

(setq

msg (strcat

msg
"\n*Error SSCANF*"
"\nBrak nawiasu otwierajacego."
"\nPrzerwanie wykonywania

funkcji."

);strcat

);setq
(princ msg)
(PAUSE_1)
(exit)

)
(T

(setq value_in 3))

);cond

);progn

);if
;----------
(cond

((= value_in 1)

;lancuch

(if (/= char "\"")

(progn

(setq string (strcat string char))

);progn
(progn

;else

(setq case (+ case 1))
(if (= case 2)

;end of string

(progn

(setq

list_str (append list_str (list

string))

string ""
value_in 0
value_out 0

);setq

);progn

);if

);progn

);if

)
;
((= value_in 2)

;lista

(cond

((= char (chr 40))(setq lb (+ lb 1)))
((= char (chr 41))(setq rb (+ rb 1)))

);cond
(if (= lb rb)

;end of list

(progn

;sprawdzenie, czy nawias koncowy jest

typu ")"

(if (= char (chr 41))

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

734

(progn

(setq

string (strcat string char)
list_str (append list_str (list

string))

string ""
value_in 0
value_out 0

);setq

);progn
(progn

(setq

msg (strcat

msg
"\n*Error SSCANF*"
"\nBledny nawias

zamykajacy."

"\nPrzerwanie wykonywania

funkcji."

);strcat

);setq
(princ msg)
(PAUSE_1)
(exit)

);progn

);if

);progn
(progn

;else

(setq string (strcat string char))

);progn

);if

)
;
((= value_in 3)

;znak alfanumeryczny

(if (/= char " ")

(progn

(setq string (strcat string char))

);progn
(progn

;else - end of value

(setq

list_str (append list_str (list

string))

string ""
value_in 0
value_out 0

);setq

);progn

);if

)

);cond
;----------
(setq i (+ i 1))
;----------

);progn

);repeat index

background image

735

BvupMJTQ!—!qsbluzd{oz!lvst

;----------
(if (/= string "")

(progn

(setq

list_str (append list_str (list string))

);setq

);progn

);if
;----------
;sprawdzenie, czy zostaly zamkniete ostatni lancuch
;lub ostatnia lista
;
(if (= case 1)

(progn

(setq

msg (strcat

msg
"\n*Error SSCANF*"
"\nNie zamknieto lancucha."
"\nPrzerwanie wykonywania funkcji."

);strcat

);setq
(princ msg)
(PAUSE_1)
(exit)

);progn

);if
;
(if (/= lb rb)

(progn

(setq

msg (strcat

msg
"\n*Error SSCANF*"
"\nNie zamknieto listy."
"\nPrzerwanie wykonywania funkcji."

);strcat

);setq
(princ msg)
(PAUSE_1)
(exit)

);progn

);if
;----------
(set (read output_list_1) list_str)
;----------
(princ)
;----------

);progn

);READ_LISP_DATA
;
;----------------------------------------
;rozbicie argumentu format na poszczegolne typy

zmiennych

;i nazwy zmiennych

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

736

;sprawdzenie poprawnosci danych w argumencie format
;
(defun CHECK_ARGUMENT_FORMAT

(/ i entity)

(progn

(READ_LISP_DATA format "#list_2")
(setq

i 0
list_type (list)
list_name (list)

);setq
(repeat (length #list_2)

(progn

(setq entity (nth i #list_2))
(cond

((= (substr entity 1 1) "%")

(if (or

(= entity "%d")(= entity "%f")
(= entity "%s")(= entity "%l")

);or

(progn

(setq list_type (append list_type (list

entity)))

);progn
(progn

;else

(princ

(strcat

"\n*Error SSCANF*"
"\nBledny typ zmiennej w argumencie

format."

"\nPrzerwanie wykonywania funkcji."

);strcat

);princ
(PAUSE_1)
(exit)

);progn

);if

)
((= (substr entity 1 1) "&")

(if (/= (substr entity 2) "")

(progn

(setq

list_name (append list_name (list

(substr entity 2)))

);setq

);progn
(progn

;else

(princ

(strcat

"\n*Error SSCANF*"
"\nBledna nazwa zmiennej w

argumencie format."

"\nPrzerwanie wykonywania funkcji."

);strcat

);princ

background image

737

BvupMJTQ!—!qsbluzd{oz!lvst

(PAUSE_1)
(exit)

);progn

);if

)
(T

(princ

(strcat

"\n*Error SSCANF*"
"\nBledny parametr w argumencie format."
"\nPrzerwanie wykonywania funkcji."

);strcat

);princ
(PAUSE_1)
(exit)

)

);cond
(setq i (+ i 1))

);progn

);repeat

);progn

);CHECK_ARGUMENT_FORMAT
;----------------------------------------
;
;Koniec definicji funkcji pomocniczych
;========================================
;Definicja funkcji glownej
;
;----------
;uaktywnienie wlasnej obslugi bledow
;
(setq

old_mistake *error*
*error* ERROR_SSCANF

);setq
;----------
;sprawdzenie argumentow wywolania funkcji glownej
;
(setq msg_all "")
(CHECK_ARGUMENT_TYPE "input_string" "STR" "msg_1")
(CHECK_ARGUMENT_TYPE "format"

"STR" "msg_2")

(CHECK_ARGUMENT_TYPE "output_list"

"STR" "msg_3")

;
(if (/= msg_1 "")

(progn

(setq msg_all (strcat msg_all "\n" msg_1))

);progn

);if
(if (/= msg_2 "")

(progn

(setq msg_all (strcat msg_all "\n" msg_2))

);progn

);if
(if (/= msg_3 "")

(progn

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

738

(setq msg_all (strcat msg_all "\n" msg_3))

);progn

);if
;
(if (/= msg_all "")

(progn

(setq

msg_all (strcat

"\n*Error SSCANF*"

msg_all
"\nPrzerwanie wykonywania funkcji."

);strcat

);setq
(princ msg_all)
(PAUSE_1)
(exit)

);progn

);if
;----------
;sprawdzenie, czy argument format wskazuje na czytanie
;formatowane czy na czytanie swobodne
;
(if (/= (strlen format) 0)

(progn

(setq bufor_read 1)

;czytanie formatowane

);progn
(progn

;else

(setq bufor_read 0)

;czytanie swobodne

);progn

);if
;----------
;jesli czytanie ma byc formatowane
;
(if (= bufor_read 1)

(progn

;----------
;rozbicie argumentu input_string na poszczegolne

dane

;
(READ_LISP_DATA input_string "#list_1")
;----------
;rozbicie argumentu format na poszczegolne typy

zmiennych

;i nazwy zmiennych
;
(CHECK_ARGUMENT_FORMAT)
;----------
;sprawdzenie, czy lista typow zmiennych i lista nazw

zmiennych

;sa tej samej dlugosci
;
(if (/= (length list_type)(length list_name))

(progn

(princ

(strcat

background image

739

BvupMJTQ!—!qsbluzd{oz!lvst

"\n*Error SSCANF*"
"\nLista typow zmiennych i lista nazw

zmiennych"

"musza byc tej samej dlugosci."
"\nPrzerwanie wykonywania funkcji."

);strcat

);princ
(PAUSE_1)
(exit)

);progn

);if
;----------
;jesli powyzszy warunek jest spelniony, podstawienie

pod

;odpowiednie zmienne ich wartosci po ich uprzednim
;przeformatowaniu na podany typ
;
(if (= (length list_type)(length list_name))

(progn

(setq i 0)
(repeat (length list_type)

(progn

(setq

type_i (nth i list_type)
name_i (nth i list_name)
value_i (nth i #list_1)

);setq
(cond

((= type_i "%d")

;calkowita

(if (= value_i nil)

(progn

(set (read name_i) value_i)

);progn
(progn

;else

(set (read name_i)(atoi value_i))

);progn

);if

)
;
((= type_i "%f")

;rzeczywista

(if (= value_i nil)

(progn

(set (read name_i) value_i)

);progn
(progn

;else

(set (read name_i)(atof value_i))

);progn

);if

)
;
((= type_i "%s")

;lancuch

(set (read name_i) value_i)

)
;
((= type_i "%l")

;lista

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

73:

(if (= value_i nil)

(progn

(set (read name_i) value_i)

);progn
(progn

;else

(set (read name_i)(read value_i))

);progn

);if

)

);cond
(setq i (+ i 1))

);progn

)repeat

);progn

);if
;----------

);progn

);if
;----------
;jesli czytanie ma byc swobodne
;
(if (= bufor_read 0)

(progn

;----------
;rozbicie argumentu input_string na poszczegolne

dane

;
(READ_LISP_DATA input_string "#list_1")
;----------
;podstawienie listy rozbitych argumentow pod zmienna
;przekazana w argumencie output_list
;
(set (read output_list) #list_1)
;----------

);progn

);if
;----------
;powrot do standardowej obslugi bledow
;
(setq *error* old_mistake)
;----------
;
;Koniec definicji funkcji glownej
;========================================
(princ)

);progn

);SSCANF
;
;=================================================
;*************************************************KONIEC

Funkcja główna SSCANF definiuje nast

ępujące funkcje pomocnicze:

background image

741

BvupMJTQ!—!qsbluzd{oz!lvst

Q

Q

Q

QBVTF`2

BVTF`2

BVTF`2

BVTF`2

Funkcja zatrzymuje realizacj

ę programu do chwili naciśnięcia klawisza ENTER.

FSS

FSS

FSS

FSSPS`TTDB

PS`TTDB

PS`TTDB

PS`TTDBOG

OG

OG

OG

Funkcja ta zapewnia wewn

ętrzną obsługę błędów. Wywoływana jest z jednym argu-

mentem, b

ędącym łańcuchem z komunikatem o błędzie. Komunikat ten jest wyświe-

tlany w linii komend AutoCADa, po czym wywoływana jest funkcja exit, przerywaj

ąca

działanie funkcji SSCANF. Kontroli podlegaj

ą następujące dane i operacje:

sprawdzenie, czy wszystkie argumenty funkcji SSCANF s

ą łańcuchami,

sprawdzenie, czy lista nie zaczyna si

ę nawiasem prawym,

sprawdzenie, czy nawias zamykaj

ący listy jest nawiasem lewym,

sprawdzenie, czy zostały zamkni

ęte ostatni łańcuch lub ostatnia lista,

sprawdzenie typu zmiennej w argumencie format,

sprawdzenie nazwy zmiennej w argumencie format,

sprawdzenie, czy długo

ść listy typu zmiennych jest równa długości listy nazw

zmiennych.

DIFDL`

DIFDL`

DIFDL`

DIFDL`BSHVN

BSHVN

BSHVN

BSHVNFOU`UZQF

FOU`UZQF

FOU`UZQF

FOU`UZQF

Funkcja sprawdza, czy zmienna podana w argumencie argument_name jest odpo-
wiedniego typu (REAL, INT, STR, itp.), który podajemy w argumencie argument_type.
W przypadku, gdy zmienna nie spełnia wymaga

ń co do typu, pod zmienną podaną w ar-

gumencie output_message podstawiany jest odpowiedni komunikat o bł

ędzie.

SF

SF

SF

SFBE`MJTQ`EBUB

BE`MJTQ`EBUB

BE`MJTQ`EBUB

BE`MJTQ`EBUB

Funkcja rozbija ła

ńcuch podany w argumencie input_string_1 na listę łańcuchów

i podstawia otrzyman

ą listę pod nazwę zmiennej przekazanej w argumencie output

_list_1. Separatorem podziału ła

ńcucha na podłańcuchy jest spacja. Funkcja dodatkowo

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

742

sprawdza, czy w przypadku podła

ńcucha reprezentującego listę zgodny jest typ oraz

liczba nawiasów otwieraj

ących i zamykających oraz czy zostały zamknięte ostatni

ła

ńcuch lub ostatnia lista.

DIFDL`BS

DIFDL`BS

DIFDL`BS

DIFDL`BSHVNFOU`

HVNFOU`

HVNFOU`

HVNFOU`GPSNBU

GPSNBU

GPSNBU

GPSNBU

Funkcja rozbija ła

ńcuch podany w argumencie format na poszczególne typy zmiennych

i nazwy zmiennych. Typ zmiennej musi rozpoczyna

ć się znakiem %, po którym

wyst

ępuje litera d (liczba całkowita), f (liczba rzeczywista), s (łańcuch) lub l (lista).

Nazwa zmiennej musi rozpoczyna

ć się znakiem & (znak ten jest tylko zaznaczeniem, że

chodzi tu o nazw

ę zmiennej i nie wchodzi do jej nazwy).

Funkcja główna wykonuje nast

ępujące czynności:

uaktywnia własn

ą obsługę błędów ERROR_SSCANF,

sprawdza argumenty wywołania funkcji posługuj

ąc się funkcją CHECK

_ARGUMENT_TYPE. W przypadku bł

ędnych argumentów wypisywany jest

zbiorczy komunikat o bł

ędach (zmienna msg_all), po czym działanie funkcji

zostaje przerwane,

sprawdza, czy argument format wskazuje na czytanie formatowane czy na
czytanie swobodne,

w przypadku czytania formatowanego:

rozbija argument input_string na poszczególne dane, wykorzystuj

ąc

funkcj

ę READ_LISP_DATA,

rozbija argument format na poszczególne typy zmiennych i nazwy
zmiennych, wykorzystuj

ąc funkcję CHECK_ARGUMENT_FORMAT,

sprawdza, czy lista typów zmiennych i lista nazw zmiennych s

ą tej samej

długo

ści. Jeśli nie, wypisywany jest komunikat o błędzie po czym działa-

nie funkcji zostaje przerwane,

je

śli powyższy warunek jest spełniony, następuje podstawienie pod

odpowiednie zmienne ich warto

ści po ich uprzednim przeformatowaniu

na podany typ,

w przypadku czytania swobodnego:

rozbija argument input_string na poszczególne dane, wykorzystuj

ąc

funkcj

ę READ_LISP_DATA,

podstawia list

ę rozbitych argumentów pod zmienną przekazaną w argu-

mencie output_list,

powraca do standardowej obsługi bł

ędów.

Poni

ższy program pokazuje sposób wykorzystania funkcji SSCANF do odbioru zbioru

danych zapisanego w pliku $FILE_08.DAT.

background image

743

BvupMJTQ!—!qsbluzd{oz!lvst

;*************************************************PROG_124
;Wykorzystanie funkcji SSCANF z biblioteki SCANF1.LLB.
;Odbior zbioru danych dla MES zapisanego w pliku
$FILE_08.DAT
;
;=================================================
;
(defun ZMIENNE_GLOBALNE ()

(progn

;----------
(setq

glob_lista_wezlow (list)
glob_lista_elementow (list)
;
glob_punkt_ld '(0 0 0)
glob_punkt_pg '(12 9 0)
;
glob_appname "ACPAFEC_V_1_50"
;
glob_h_tekstu 0.20
glob_h_tekstu_0 0.20
glob_delta_tekstu 0.20
glob_wielkosc_punktu 0.20
glob_wielkosc_punktu_0 0.20
;
glob_typ_elementu 34000
glob_grupa_elementu 1
glob_material_elementu 1

);setq
(regapp glob_appname)

;rejestracja aplikacji

;----------
(princ)
;----------

);progn

);ZMIENNE_GLOBALNE
;
;=================================================
;
(defun ODBIERZ_ZBIOR_DANYCH (nazwa_zbioru / plik)

(progn

;----------
(setq plik (open nazwa_zbioru "r"))
(command "_ucs" "_World")
(CZYTAJ_ZBIOR_DANYCH)

;

(OBSZAR_MODELU)

;

(GRANICE glob_punkt_ld glob_punkt_pg)

;

(ODBIERZ_WEZLY)

;

(ODBIERZ_ELEMENTY)

(if plik

(progn

(close plik)

);progn

);if
;----------
(princ)

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

744

;----------

);progn

);ODBIERZ_ZBIOR_DANYCH
;
;=================================================
;Wczytanie zbioru danych DAT.
;Utworzenie odpowiednich list.
;
(defun CZYTAJ_ZBIOR_DANYCH ( / jeszcze1 linia)

(progn

;----------
(princ "\nRozpoczecie czytania zbioru danych.")
(setq jeszcze1 T)
(while jeszcze1

(progn

(setq linia (read-line plik))
(setq linia1 (substr linia 1 5))
(cond

((= linia "NODES")(CZYTAJ_MODUL_NODES))
((= linia "ELEMENTS")(CZYTAJ_MODUL_ELEMENTS))
((or (= linia "END.OF.DATA")(= linia nil))

(setq jeszcze1 nil)(close plik)(setq plik nil)

)

);cond

);progn

);while jeszcze1
(princ "\nZakonczenie czytania zbioru danych.")
;----------
(princ)

);progn

);CZYTAJ_ZBIOR_DANYCH
;
;=================================================
;Czytanie modulu NODES
;
(defun CZYTAJ_MODUL_NODES

( / jeszcze2 linia numer

wsp_x wsp_y wsp_z wsp_wz opis_wezla

)

(progn

;----------
(princ "\nCzytanie wezlow.....")
(setq glob_lista_wezlow (list))
(setq jeszcze2 T)
;----------
(while jeszcze2

(progn

(setq linia (read-line plik))
(cond

((= linia "C END.OF.NODES")(setq jeszcze2 nil))
;
((/= linia "C END.OF.NODES")

(if (or

(= (substr linia 1 1) "C")
(= (substr linia 1 4) "NODE")

background image

745

BvupMJTQ!—!qsbluzd{oz!lvst

);or

(progn

(princ)

;nie rob nic

);progn
(progn

;else

(SSCANF

linia
"%d %f %f %f &numer &wsp_x &wsp_y &wsp_z"
""

);SSCANF
(if (= wsp_z nil)

(progn

(setq wsp_z 0.0)

);progn

);if
(setq

wsp_wz (list wsp_x wsp_y wsp_z)
opis_wezla (list numer wsp_wz)
glob_lista_wezlow

(append glob_lista_wezlow (list

opis_wezla))

);setq

);progn

);if

)

);cond

);progn

);while jeszcze2
;----------
(princ "\rCzytanie wezlow.

")

;----------
(princ)
;----------

);progn

);CZYTAJ_MODUL_NODES
;
;=================================================
;Czytanie modulu ELEMENTS
;
(defun CZYTAJ_MODUL_ELEMENTS

( / jeszcze2 linia numer grupa typ material

w1 w2 w3 w4 topologia opis_elementu

)

(progn

;----------
(princ "\nCzytanie elementow.....")
(setq glob_lista_elementow (list))
(setq jeszcze2 T)
;----------
(while jeszcze2

(progn

(setq linia (read-line plik))
(cond

((= linia "C END.OF.ELEMENTS")(setq jeszcze2 nil))
((/= linia "C END.OF.ELEMENTS")

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

746

(if (or

(= (substr linia 1 1) "C")
(= (substr linia 1 6) "NUMBER")

);or

(progn

(princ)

;nie rob nic

);progn
(progn

;else

;----------
(SSCANF

linia
(strcat

"%d %d %d %d %d %d %d %d "
"&numer &grupa &typ &material &w1 &w2

&w3 &w4"

);strcat
""

);SSCANF
;----------
(setq topologia (list))
(setq topologia (append topologia (list

w1)))

(setq topologia (append topologia (list

w2)))

(if (/= w3 nil)

(progn

(setq topologia (append topologia (list

w3)))

);progn

);if
(if (/= w4 nil)

(progn

(setq topologia (append topologia (list

w4)))

);progn

);if
;----------
(setq

opis_elementu (append

(list numer)
(list grupa)
(list typ)
(list material)
topologia

);append

glob_lista_elementow

(append glob_lista_elementow (list

opis_elementu))

);setq
;----------

);progn

);if

)

);cond

);progn

background image

747

BvupMJTQ!—!qsbluzd{oz!lvst

);while jeszcze2
;----------
(princ "\rCzytanie elementow.

")

;----------
(princ)
;----------

);progn

);CZYTAJ_MODUL_ELEMENTS
;
;=================================================
;Funkcja testujaca.
;
(defun C:TEST ()

(progn

;----------

;

(RYSUNEK_PROTOTYPOWY)

(ZMIENNE_GLOBALNE)
(ODBIERZ_ZBIOR_DANYCH "$file_08.dat")
;----------
(princ)
;----------

);progn

);C:TEST
;
;=================================================
(load "scanf1.llb")
(princ "\nProgram zaladowany. ")
(princ "Komenda TEST uruchamia testowanie.")
(princ)
;=================================================
;*************************************************KONIEC

Wykonanie powy

ższego programu będzie następujące:

Command: (load "prog_124")

↵↵

Program zaladowany. Komenda TEST uruchamia testowanie.

Command: test

↵↵

Rozpoczecie czytania zbioru danych.
Czytanie wezlow.
Czytanie elementow.
Zakonczenie czytania zbioru danych.

Command:

Po wczytaniu zbioru danych mo

żesz przejrzeć globalne listy węzłów i elementów

podstawione pod zmienne glob_lista_wezlow i glob_lista_elementow.

Funkcja SSCANF została tutaj zastosowana do odbioru danych z modułu w

ęzły

(NODES) i elementy (ELEMENTS).

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

748

Dla odbioru danych o w

ęzłach wywołanie funkcji SSCANF przedstawia się następująco:

(SSCANF

linia
"%d %f %f %f &numer &wsp_x &wsp_y &wsp_z"
""

)

gdzie:

linia

linia danych do przetworzenia odczytana z pliku,

%d &numer

numer w

ęzła (liczba całkowita) zapisany pod zmienną numer,

%f &wsp_x

współrz

ędna X węzła (liczba rzeczywista) zapisana pod

zmienn

ą wsp_x,

%f &wsp_y

współrz

ędna Y węzła (liczba rzeczywista) zapisana pod

zmienn

ą wsp_y,

%f &wsp_z

współrz

ędna Z węzła (liczba rzeczywista) zapisana pod

zmienn

ą wsp_z. W przypadku braku w linii danych współ-

rz

ędnej Z funkcja SSCANF ustawia wartość zmiennej

wsp_z na nil. Jest to sprawdzane w dalszej cz

ęści funkcji

CZYTAJ_MODUL_NODES i w takim przypadku zmien-
nej wsp_z nadawana jest warto

ść 0.0.

Dla odbioru danych o elementach wywołanie funkcji SSCANF przedstawia si

ę

nast

ępująco:

(SSCANF

linia
(strcat

"%d %d %d %d %d %d %d %d "
"&numer &grupa &typ &material &w1 &w2 &w3 &w4"

);strcat
""

)

gdzie:

linia

linia danych do przetworzenia odczytana z pliku,

%d &numer

numer elementu (liczba całkowita) zapisany pod zmienn

ą numer,

%d &grupa

grupa elementu (liczba całkowita) zapisana pod zmienn

ą grupa,

%d &typ

typ elementu (liczba całkowita) zapisany pod zmienn

ą typ,

%d &material

materiał elementu (liczba całkowita) zapisany pod zmienn

ą

material,

%d &w1

numer pierwszego w

ęzła elementu (liczba całkowita) zapisany

pod zmienn

ą w1,

%d &w2

numer drugiego w

ęzła elementu (liczba całkowita) zapisany

pod zmienn

ą w2,

background image

749

BvupMJTQ!—!qsbluzd{oz!lvst

%d &w3

numer trzeciego w

ęzła elementu (liczba całkowita) zapisany

pod zmienn

ą w3. W przypadku, gdy element jest belką — brak

danych dla w

ęzła trzeciego — funkcja SSCANF ustawia

warto

ść zmiennej w3 na nil,

%d &w4

numer czwartego w

ęzła elementu (liczba całkowita) zapisany

pod zmienn

ą w4. W przypadku, gdy element jest belką lub

płyt

ą 3-węzłową — brak danych dla węzła czwartego —

funkcja SSCANF ustawia warto

ść zmiennej w4 na nil.

2

22

26/6/6/!Ped{zu!e

6/6/6/!Ped{zu!e

6/6/6/!Ped{zu!e

6/6/6/!Ped{zu!ebozdi!x!q

bozdi!x!q

bozdi!x!q

bozdi!x!qptubdj!sflpse

ptubdj!sflpse

ptubdj!sflpse

ptubdj!sflpse.x

.x

.x

.x

W programie PROG_119 przedstawiłem sposób zapisu danych w postaci rekordów —
zapis do pliku $FILE_07.DAT. Obecnie, wykorzystuj

ąc utworzony plik danych,

dokonamy jego wczytania na globaln

ą listę danych, gdzie każdy element listy jest

podlist

ą zawierającą dane jednego rekordu.

;*************************************************PROG_125
;Odczyt danych w postaci rekordow.
;Dane zapisane w pliku $FILE_07.DAT.
;
;Program korzysta z nastepujacych funkcji:
;

USUN_SPACJE_W_LANCUCHU zawartej w pliku PROG_061.LSP

;
;=================================================
;
(defun ZMIENNE_GLOBALNE ()

(progn

;----------
(setq glob_lista_rekordow (list))
;----------
(princ)
;----------

);progn

);ZMIENNE_GLOBALNE
;
;=================================================
;Funkcja do odbioru zbioru danych.
;
;Funkcja wywolywana jest z dwoma argumentami:
;nazwa_zbioru - nazwa zbioru danych do wczytania
;opis_rekordu - opis pol rekordu w postaci:
;

(

;

(pole_1_p pole_1_k typ_pola_1)

;

.....

;

(pole_n_p pole_n_k typ_pola_n)

;

)

;

gdzie:

;

pole_1_p - poczatek danych dla pola nr 1

;

pole_1_k - koniec danych dla pola nr 1

;

typ_pola_1 - typ pola danych

;

1 - numeryczny

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

74:

;

2 - znakowy

;
;

pole_n_p - poczatek danych dla pola nr n

;

pole_n_k - koniec danych dla pola nr n

;

typ_pola_n - typ pola danych

;

1 - numeryczny

;

2 - znakowy

;
(defun ODBIERZ_ZBIOR_DANYCH (nazwa_zbioru opis_rekordu /

plik jeszcze dlugosc linia
rekord licznik dane_pola
pole_p pole_k dl_pola
pole typ_pola

)

(progn

;----------
(setq plik (open nazwa_zbioru "r"))
(if plik

(progn

;----------
(setq

jeszcze T

dlugosc (length opis_rekordu)

);setq

(while jeszcze

(progn

;----------
(setq linia (read-line plik))
(if (= linia nil)

(progn

;----------
(setq jeszcze nil)
;----------

);progn
(progn

;else

;----------

(setq

rekord (list)
licznik 0
pole ""

);setq

(repeat dlugosc

(progn

;----------

(setq

dane_pola (nth licznik opis_rekordu)
pole_p (nth 0 dane_pola)
pole_k (nth 1 dane_pola)
dl_pola (+ 1 (- pole_k pole_p))
typ_pola (nth 2 dane_pola)
pole (substr linia pole_p dl_pola)

);setq

;

(if (= typ_pola 1)

background image

751

BvupMJTQ!—!qsbluzd{oz!lvst

(progn

;----------
(setq pole (read pole))
;----------

);progn

);if

(if (= typ_pola 2)

(progn

;----------
(setq

pole (USUN_SPACJE_W_LANCUCHU pole 3)

);setq
;----------

);progn

);if

;----------

(setq

rekord (append rekord (list pole))
licznik (1+ licznik)

);setq

;----------

);progn

);repeat dlugosc
;

(setq

glob_lista_rekordow

(append glob_lista_rekordow (list rekord))

);setq
;----------

);progn

);if
;----------

);progn

);while jeszcze
(close plik)
;----------

);progn
(progn

;else

;----------
(princ

(strcat

"\nNie znaleziono pliku "
nazwa_pliku
"."

);strcat

);princ
;----------

);progn

);if plik
;----------
(princ)
;----------

);progn

);ODBIERZ_ZBIOR_DANYCH

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

752

;
;=================================================
;Funkcja testujaca.
;
(defun C:TEST (/ opis_rekordu dlugosc licznik rekord)

(progn

;----------
(setq

opis_rekordu

'(

(

1

12 1)

( 14

33 2)

( 35

74 2)

( 76 115 2)
(117 131 2)
(133 144 1)
(146 155 1)
(157 161 2)
(163 174 1)

)

);setq
;----------
(ZMIENNE_GLOBALNE)
(ODBIERZ_ZBIOR_DANYCH "$file_07.dat" opis_rekordu)
;----------
(if (/= glob_lista_rekordow nil)

(progn

;----------
(textpage)
(princ "Zawartosc listy rekordow.")
;----------
(setq

dlugosc (length glob_lista_rekordow)
licznik 0

);setq
;
(repeat dlugosc

(progn

;----------
(setq rekord (nth licznik glob_lista_rekordow))
(princ "\n")
(prin1 rekord)
(setq licznik (1+ licznik))
;----------

);progn

);repeat dlugosc
;----------

);progn

);if
;----------
(princ)
;----------

);progn

);C:TEST
;

background image

753

BvupMJTQ!—!qsbluzd{oz!lvst

;=================================================
(load "prog_061")
(princ "\nProgram zaladowany. ")
(princ "Komenda TEST uruchamia testowanie.")
(princ)
;=================================================
;*************************************************KONIEC

Wykonanie powy

ższego programu będzie następujące.

Command: (load "prog_125")

↵↵

Program zaladowany. Komenda TEST uruchamia testowanie.

Command: test

↵↵

Zawartosc listy rekordow.
(1 .....)
.....
(12 .....)
Command:

Omówmy teraz wyró

żnione linie i bloki programu.

Obliczamy długość listy opisującej rekord — liczbę pól w rekordzie. Tym

samym funkcja jest uniwersalna — mo

żemy ją zastosować do dowolnego

rekordu danych.

Wchodzimy w pętlę while i rozpoczynamy przetwarzanie poszczególnych linii

z pliku. P

ętlę while wykonujemy do chwili osiągnięcia znacznika końca pliku.

W bloku tym ustawiamy zmienne początkowe do przetworzenia kolejnego rekordu.
Wchodzimy w pętlę repeat i rozpoczynamy przetwarzanie kolejnego pola

w rekordzie.

Pobieramy dane opisujące kolejne pole rekordu.
W przypadku pola numerycznego, dokonujemy konwersji łańcucha na liczbę

całkowit

ą lub rzeczywistą.

W przypadku pola znakowego, obcinamy puste spacje na początku i na końcu

ła

ńcucha.

Dodajemy pole do listy opisującej rekord oraz zwiększamy wartość zmiennej

licznik o 1, umo

żliwiając tym samym przetworzenie kolejnego pola w rekordzie.

Będąc poza pętlą repeat, dodajemy listę opisującą cały rekord do listy globalnej

glob_lista_rekordow.

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

754

Je

śli istniejący plik został otwarty w trybie "w" (do odczytu), to wszystkie zawarte

w nim informacje zostan

ą zatarte. Aby dodać do pliku nowe informacje, musimy

otworzy

ć plik w trybie "a" (do dopisywania). Otwarcie w trybie "a" nie istniejącego

pliku spowoduje jego utworzenie; je

śli zaś plik już istnieje, to nowe informacje będą do

niego dopisywane.

Kiedy dodajemy dane na ko

ńcu, na nas spada odpowiedzialność za to, aby już istniejące

dane i

świeżo wprowadzone były w tym samym formacie.

Poni

ższy program otwiera plik $FILE_09.DAT do zapisu, wpisuje do niego linie podane

z klawiatury, zamyka plik, otwiera go w trybie do dopisywania i dopisuje do niego linie
podane z klawiatury. Zako

ńczenie wpisywania danych do pliku następuje w momencie

podania z klawiatury linii "end" (niezale

żnie od wielkości liter).

;*************************************************PROG_126
;Utworzenie pliku $FILE_09.DAT.
;Dodawanie danych do pliku.
;
;=================================================
;Funkcja zatrzymujaca realizacje programu,
;dopoki uzytkownik nie nacisnie ENTER...
;
(defun CZEKAJ ()

(progn

;----------
(getstring "\nNacisnij ENTER...")
(princ)
;----------

);progn

);CZEKAJ
;
;=================================================
;Funkcja zapisu do pliku
;
(defun WRITE_TO_FILE (file_desc / jeszcze linia)

(progn

;----------
(setq jeszcze T)

(while jeszcze

(progn

;----------

(setq linia

(getstring T "Linia do zapisu [END - koniec] >:")

);setq

(if (= (strcase linia) "END")

(progn

background image

755

BvupMJTQ!—!qsbluzd{oz!lvst

;----------
(setq jeszcze nil)
(close plik)
;----------

);progn
(progn

;else

(write-line linia plik)

);progn

);if

;----------

);progn

);while jeszcze
;----------

);progn

);WRITE_TO_FILE
;
;=================================================
;Funkcja testujaca.
;
(defun C:TEST (/ plik)

(progn

;----------
(textpage)
;----------
(princ "\nUtworzenie pliku $FILE_09.DAT.")
(setq plik (open "$file_09.dat" "w"))
(CZEKAJ)
;----------
(princ "\nZapis do pliku $FILE_09.DAT.\n")
(WRITE_TO_FILE plik)
;----------
(princ "\nOtwarcie pliku $FILE_09.DAT do dopisywania.")
(setq plik (open "$file_09.dat" "a"))
(CZEKAJ)
;----------
(princ "\nZapis do pliku $FILE_09.DAT.\n")
(WRITE_TO_FILE plik)
;----------
(princ "\nKoniec testu.")
(princ)
;----------

);progn

);C:TEST
;
;=================================================
(princ "\nProgram zaladowany. ")
(princ "Komenda TEST uruchamia testowanie.")
(princ)
;=================================================
;*************************************************KONIEC

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

756

Wykonanie powy

ższego programu może być następujące.

Command: (load "prog_126")

↵↵

Program zaladowany. Komenda TEST uruchamia testowanie.

Command: test

↵↵

Utworzenie pliku $FILE_09.DAT.

Nacisnij ENTER...

↵↵

Zapis do pliku $FILE_09.DAT.

Linia do zapisu [END - koniec] >: test 1

↵↵

Linia do zapisu [END - koniec] >: test 2

↵↵

Linia do zapisu [END - koniec] >: test 3

↵↵

Linia do zapisu [END - koniec] >: end

↵↵

Otwarcie pliku $FILE_09.DAT do dopisywania.

Nacisnij ENTER...

↵↵

Zapis do pliku $FILE_09.DAT.

Linia do zapisu [END - koniec] >:

↵↵

Linia do zapisu [END - koniec] >: test 4

↵↵

Linia do zapisu [END - koniec] >: test 5

↵↵

Linia do zapisu [END - koniec] >: test 6

↵↵

Linia do zapisu [END - koniec] >: end

↵↵

Command:

Po powy

ższym wykonaniu programu zawartość pliku $FILE_09.DAT będzie nastę-

puj

ąca.

test 1
test 2
test 3

test 4
test 5
test 6

Omówmy teraz wyró

żnione linie i bloki programu.

Wchodzimy w pętlę while i rozpoczynamy pobieranie linii do zapisu do pliku.
Wykorzystując funkcję getstring, pobieramy linię danych do zapisu.
Sprawdzamy, czy wprowadzono słowo kończące pobieranie danych. Jeśli tak,

opuszczamy p

ętlę while oraz zamykamy plik, w przeciwnym wypadku zapisu-

jemy wprowadzon

ą linię do pliku.

background image

757

BvupMJTQ!—!qsbluzd{oz!lvst

Potrzeba u

żywania drukarki nie wymaga komentarza. W instrukcjach wyjścia dla

systemu DOS traktowana jest ona jako plik o wyró

żnionej nazwie: LPT1 lub PRN.

Poni

ższy program wykorzystuje okno dialogowe getfiled do wyboru pliku, który

nast

ępnie może być wyświetlony na ekranie lub wydrukowany na drukarce podłączonej

do portu LPT1. Na zał

ączonej dyskietce znajduje się plik $FILE_10.DAT, który możesz

wykorzysta

ć do testowania działania programu.

Poniewa

ż

z poziomu AutoLISPu nie mo

ż

na sprawdzi

ć

stanu drukarki,

zakładam,

ż

e w chwili testowania wysyłania pliku na drukark

ę

jest ona gotowa

do drukowania.

;*************************************************PROG_127
;Wydruk pliku na drukarke lub ekran.
;
;=================================================
;Funkcja wyswietlajaca podany plik na ekranie.
;
(defun WYSWIETL_PLIK (nazwa_pliku /

file_desc jeszcze licznik linia

)

(progn

;----------
;otwarcie pliku do odczytu
(setq file_desc (open nazwa_pliku "r"))
;----------
(textpage)
(princ "Wyswietlam plik: ")
(prin1 nazwa_pliku)
(princ "\n\n")
;----------
(setq

jeszcze T
licznik 5

);setq
(while jeszcze

(progn

;----------
(setq linia (read-line file_desc))
(if (= linia nil)

(progn

;----------
(setq jeszcze nil)
;----------

);progn
(progn

;else

;----------

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

758

(princ linia)
(princ "\n")
;----------

);progn

);if
;----------
(setq licznik (1+ licznik))
(if (= licznik 24)

(progn

;----------
(getstring "\nNacisnij ENTER...")
(setq licznik 1)
(textpage)
;----------

);progn

);if
;----------

);progn

);while jeszcze
;----------
;zamkniecie pliku
(close file_desc)
;----------
(princ)
;----------

);progn

);WYSWIETL_PLIK
;
;=================================================
;Funkcja drukujaca podany plik.
;
(defun DRUKUJ_PLIK (nazwa_pliku /

file_in file_out jeszcze linia

)

(progn

;----------
(princ "\nDrukuje plik: ")
(prin1 nazwa_pliku)
;----------
;otwarcie plikow
(setq

file_in (open nazwa_pliku "r")
file_out (open "PRN" "w")

);setq
;----------
(setq jeszcze T)
(while jeszcze

(progn

;----------
(setq linia (read-line file_in))
(if (= linia nil)

(progn

;----------
(setq jeszcze nil)
;----------

background image

759

BvupMJTQ!—!qsbluzd{oz!lvst

);progn
(progn

;else

;----------
(princ linia file_out)
(princ "\n" file_out)
;----------

);progn

);if
;----------

);progn

);while jeszcze
;----------
;zamkniecie plikow
(close file_in)
(close file_out)
;----------
(princ)
;----------

);progn

);DRUKUJ_PLIK
;
;=================================================
;Funkcja testujaca.
;
(defun C:TEST (/ plik odp)

(progn

;----------
;pobranie nazwy pliku
(setq plik (getfiled "Wybierz Plik" "" "" 0))
(if plik

(progn

;----------
(princ "\nWybrales plik: ")
(prin1 plik)
(initget 1 "E D")
(setq

odp (getkword

"\nWydruk na Ekran [E] czy na drukarke [D]

?: "

);getkword

odp (strcase odp)

);setq
(cond

((= odp "E")

(WYSWIETL_PLIK plik)

)
;
((= odp "D")

(DRUKUJ_PLIK plik)

)

);cond
;----------

);progn
(progn

;else

;----------

background image

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf

75:

(princ "\nNie wybrano pliku.")
;----------

);progn

);if plik
;----------
(princ)
;----------

);progn

);C:TEST
;
;=================================================
(princ "\nProgram zaladowany. ")
(princ "Komenda TEST uruchamia testowanie.")
(princ)
;=================================================
;*************************************************KONIEC

Program składa si

ę z dwóch głównych funkcji:

XZTXJFUM

XZTXJFUM

XZTXJFUM

XZTXJFUM`QMJL

`QMJL

`QMJL

`QMJL

Funkcja wy

świetla na ekranie plik podany w argumencie wywołania funkcji nazwa

_pliku. Podany plik zostaje otwarty w trybie do odczytu, na ekranie tekstowym
wy

świetlona zostaje nazwa wybranego pliku, po czym zostaje wyświetlona zawartość

pliku. W przypadku długich plików s

ą one dzielone na fragmenty po 24 linie — realizacja

programu jest zatrzymywana do chwili naci

śnięcia przez użytkownika klawisza ENTER.

ESVLV

ESVLV

ESVLV

ESVLVK`QMJL

K`QMJL

K`QMJL

K`QMJL

Funkcja drukuje plik podany w argumencie wywołania funkcji nazwa_pliku. Podany
plik zostaje otwarty w trybie do odczytu (file_in), plik reprezentuj

ący drukarkę zostaje

natomiast otwarty w trybie do zapisu (file_out). Przesyłanie danych na drukark

ę odby-

wa si

ę w pętli while do czasu osiągnięcia znacznika końca pliku w pliku wejściowym.

Rozdział ten zapoznał Ci

ę z obsługą plików tekstowych w języku AutoLISP.

Przedstawione programy pokazały, jak t

ę samą informację zapisać i odczytać na wiele

żnych sposobów. Umiejętność posługiwania się informacją zapisaną w plikach spra-

wia,

że nie musisz się już posługiwać tylko plikami rysunkowymi AutoCADa. Możesz

wyłuskiwa

ć z plików DWG potrzebne informacje i zapisywać je do pliku tekstowego,

eksportowa

ć do innych programów (np. arkuszy kalkulacyjnych), możesz tworzyć

interfejsy pomi

ędzy AutoCADem a programami obliczeniowymi czy graficznymi,

mo

żesz również pisać rozbudowane aplikacje w języku AutoLISP lub ADS.

background image

761

BvupMJTQ!—!qsbluzd{oz!lvst

Rozdział ten ko

ńczy omawianie podstaw języka AutoLISP. Mam nadzieję, że po

wnikliwej lekturze tej ksi

ążki, analizie programów znajdujących się na dyskietce oraz

własnej inwencji twórczej, doszedłe

ś do wniosku, że sama znajomość komend

AutoCADa ju

ż Ci nie wystarcza. Wkrocz zatem w fascynujący świat języka AutoLISP,

aby przekona

ć Siebie samego i Twoich kolegów w pracy, że nauka programowania

AutoCADa jest bardzo opłacalna. Niechaj Twoje programy wynagrodz

ą Ci czas

sp

ędzony na lekturze tej książki.


Document Outline


Wyszukiwarka

Podobne podstrony:
wyklad 14 15 2010
wyklad badania mediow 15 i 16
15 ROE
15 Sieć Następnej Generacjiid 16074 ppt
wyklad 15 chemiczne zanieczyszczenia wod 2
Wykład 1 15
15 Uklady PLL i t s
Ćwiczenia i seminarium 1 IV rok 2014 15 druk
15 Fizjologiczne funkcje nerek
wykład 15 bezrobocie 2013
ustawa o dzialalnosci leczniczej z 15 kwietnia 2011
15 Wyposażenie Auta 1 33
Giddens środa 17 15
15 10 2010 Polityka przemysłowa i polityka wspierania konkurencjiid 16086 ppt

więcej podobnych podstron