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.
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.
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.
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.
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.
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:
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ż
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
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
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.
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
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)
;----------
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.
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
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")
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:
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
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
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
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.
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))
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:
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.
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)
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
↵
↵↵
↵
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.
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
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. ")
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.
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
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
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
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
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
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)
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
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"
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
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.
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
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
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
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")
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
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.
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
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).
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.
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.
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.
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 "|".
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.
Bł
ąd typu wartości podlegającej formatowaniu — oczekiwano na liczbę rzeczywistą.
(printf '("%i" 10.0))
Error: integer value expected.
Bł
ą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"
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
;----------
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
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
;
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")
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
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.
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
;
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)
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)
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))
==============================
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.
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"
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.
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
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)
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
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
;
;=================================================
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.
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)
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
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
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.
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"
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)
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
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
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
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)
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
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
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
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)
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))
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
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)
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
;----------
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)
;----------
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
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)
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:
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.
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.
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,
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.
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)
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.
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,
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,
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
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
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,
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
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"
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.
;
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
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))
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
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
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
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
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
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
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:
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
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.
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)
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")
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")
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
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).
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,
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
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)
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
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
;
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.
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
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
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.
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
;----------
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)
;----------
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
;----------
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
ró
ż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.
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.