You are on page 1of 136

26/!Pctvhb!qmjlx!ufltupxzdi!x!

BvupMJTQjf

626

Wywietlanie informacji na ekranie jest uyteczne, ale niesie te ze sob pewne ograniczenia. Nawet jeli wstrzymamy dziaanie programu, aby zyska na czasie przy odczytywaniu z ekranu, to po przewiniciu informacji poza pole widzenia, aby j odczyta
musimy ponownie uruchomi program czy te wybran funkcj.
A oprcz tego program utrzymuje warto zmiennych tylko wtedy, gdy jest uruchomiony; wprowadzona informacja zniknie po jego zatrzymaniu.
Aby informacja zostaa zapisana na stae lub by mc rozpowszechnia wyniki wasnej
pracy wrd innych uytkownikw, naley j wydrukowa. Z kolei przechowanie informacji na dysku bdzie niezbdne wwczas, gdy zechcemy tylko raz wprowadzi dane
i mc z nich korzysta wielokrotnie w pniejszym terminie.
Programy omwione w tym rozdziale.
PROG_109.LSP
Funkcja testujca okno dialogowe getfiled.
PROG_110.LSP
Zastosowanie funkcji getfiled do edycji pliku tekstowego.
PROG_111.LSP
Funkcja testujca okno dialogowe getfiled oraz funkcj findfile.

627

BvupMJTQ!!qsbluzd{oz!lvst
PROG_112.LSP
Funkcja dzielca acuch z wartoci zmiennej rodowiskowej na list podacuchw.
PROG_113.LSP
Przykad zastosowania funkcji read-char i write-char.
Test zapisu do pliku znak po znaku.
PROG_114.LSP
Przykad zastosowania funkcji read-line i write-line.
Test zapisu do pliku wierszami.
PROG_115.LSP
Przykad zapisu do pliku wierszami z zastosowaniem funkcji write-line.
PROG_116.LSP
Przykad zapisu do pliku informacji, ktre przed zapisem umieszczane s na jednej licie.
PROG_117.LSP
Przykad zapisu do pliku wierszami z zastosowaniem funkcji FPRINTF, zawartej
w pliku PRINTF.LLB.
PROG_118.LSP
Zapis do pliku przykadowych linii z zastosowaniem funkcji princ, prin1, write-line
oraz FPRINTF.
PROG_119.LSP
Zapis danych w postaci rekordw.
PROG_120.LSP
Przykad zastosowania funkcji read-char i write-char.
Wywietlenie zawartoci pliku znak po znaku.
PROG_121.LSP
Przykad zastosowania funkcji read-line i write-line.
Wywietlenie zawartoci pliku wiersz po wierszu.
PROG_122.LSP
Przykad zastosowania funkcji read-line.
Odbir zbioru danych dla MES.
PROG_123.LSP
Odczyt danych zapisanych do pliku w postaci jednej listy.
PROG_124.LSP
Przykad zastosowania funkcji SSCANF z biblioteki SCANF1.LLB.
Odbir zbioru danych dla MES.
PROG_125.LSP
Odczyt danych w postaci rekordw.

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

628

PROG_126.LSP
Przykad dodawania danych do pliku.
PROG_127.LSP
Wydruk pliku na drukark lub ekran.

Dane wejciowe nie przechodz bezporednio na dysk lub drukark, kiedy zastosujemy
polecenie wyprowadzenia. Zamiast tego, s przesyane do specjalnego obszaru pamici,
nazwanego buforem. Po zapenieniu buforu dane s przenoszone na dysk lub drukark.
Dane wprowadzone z dysku take s przenoszone do buforu; s tam przetrzymywane,
mog wic by przypisane zmiennej lub wywietlone.
Aby przeniesienie informacji do i z buforu byo moliwe musi istnie cze komunikacyjne midzy programem a systemem operacyjnym komputera. Tym czem jest plik.
Plikiem (ang. file) w najprostszym rozumieniu mona nazwa cig danych tego samego
typu skadowanych w pamici zewntrznej (tj. pamici masowej) komputera.
Fizycznym przykadem pamici zewntrznej moe by pami dyskowa lub tamowa.
Przykadem cigu danych moe by zestaw liczb, linii tekstu, struktur (rekordw), itd.
W pewnych sytuacjach, ze wzgldu na szybko dostpu do danych, plik moe by
rwnie tymczasowo skadowany w pamici operacyjnej komputera (tzw. RAM-dysk).
Kady plik musi mie zdolno przyjmowania i oddawania cigw bajtw (znakw).
Z powyszych zaoe wynika, e klawiatura i ekran s take plikami. Program
komunikuje si z otoczeniem poprzez plik, ktry jest abstrakcj urzdzenia
wejciowego lub wyjciowego. Wynika std, e programista nie musi, w zasadzie,
zastanawia
si
z jakim urzdzeniem jego program bdzie si w przyszoci porozumiewa: pisanie
i czytanie z pliku wyglda zawsze tak samo, bez wzgldu na rodzaj urzdzenia, ktre
jest z plikiem zwizane. Oczywicie istniej tu pewne wyjtki: np. drukarka lub monitor
s zdecydowanie urzdzeniami wyjcia i nie mona z nich czyta; podobnie klawiatura
jest urzdzeniem wejcia i pisanie do niej nie miaoby wikszego sensu.
Bajty tworzce plik mog by interpretowane w rny sposb. Z punktu widzenia
operacji wejcia lub wyjcia rozrnia si dwa rodzaje plikw: pliki tekstowe
(znakowe) i pliki binarne. Z uwagi na to, e AutoLISP obsuguje jedynie pliki tekstowe,
w dalszej czci tego rozdziau bdziemy si zajmowa wycznie nimi.
Kady plik identyfikowany jest przez nazw. AutoLISP udostpnia szereg funkcji
uatwiajcych posugiwanie si plikami. W poniszej tabeli dokonano ich krtkiej
charakterystyki.

629

BvupMJTQ!!qsbluzd{oz!lvst

Tabela 15.1. Funkcje do obsugi plikw tekstowych


(close file-desc)
Funkcja zamyka plik.
(load filename [onfailure])
Funkcja wczytuje plik z wyraeniami AutoLISPu.
(open filename mode)
Funkcja otwiera plik, udostpniajc 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 acuch 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 acuch alfanumeryczny na ekranie lub w otwartym pliku.

Nazwy plikw w systemie MS-DOS zbudowane s z co najwyej omiu znakw, liter


lub cyfr (minimum jeden znak). Nazwa pliku jest uzupeniona co najwyej trzyznakowym rozszerzeniem (opcja). Midzy nazw a rozszerzeniem (zawsze) wystpuje
kropka. Pena nazwa pliku moe si skada z minimum 1 znaku i kropki. Nastpujce
znaki nie mog wystpowa w nazwach plikw:
<>=,:;.*?[]()/\+
Nazwa pliku powinna informowa o jego zawartoci lub penionej funkcji, a rozszerzenie o typie pliku. Niektrym rodzajom plikw przypisano obligatoryjnie
rozszerzenia:
.EXE i .COM
pliki zawierajce programy wykonywalne.

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

62:

.BAT
pliki zawierajce zbir polece systemu operacyjnego, tzw. pliki wsadowe.
Niektre rozszerzenia nie s obligatoryjne, ale przyjy si zwyczajowo lub identyfikuj
okrelone programy, np.:
.BAK
kopia pliku, zbir zapasowy.
.BAS
program rdowy w jzyku Basic.
.C .CPP
program rdowy w jzyku C, C++.
.DBF
zbir danych w formacie dBase.
.DWG
pliki rysunkowe AutoCADa.
.LSP
program rdowy w jzyku AutoLISP.
.PAS
program rdowy w jzyku Pascal.
.SYS
plik systemowy lub sterownik programowy.
Na rwni z nazwami plikw wystpuj w niektrych poleceniach nazwy urzdze
wejcia/wyjcia. Nazwy te jednoznacznie identyfikuj urzdzenia:
CON
(ang. console) klawiatura i monitor.
AUX lub COMn
port komunikacji szeregowej (n = 1, 2, 3 lub 4) w zalenoci od konfiguracji
komputera.
PRN lub LPT1
pierwszy port komunikacji rwnolegej.
LPT2 lub LPT3
drugi lub trzeci port komunikacji rwnolegej.
NUL
urzdzenie nie istniejce symulowane (czasem istnieje potrzeba skierowania gdzie
informacji bez wywoywania skutkw).
Nazw pliku (wraz z ew. ciek dostpu do pliku) pobieramy w jzyku AutoLISP
wykorzystujc funkcj biblioteczn getstring lub getfiled. Do odszukania pliku stosujemy take funkcj biblioteczn findfile.

631

BvupMJTQ!!qsbluzd{oz!lvst

26/3/2/ Qpcjfs
Qpcjfsbojf!ob{xz!qmj
bojf!ob{xz!qmjlv!{b!qpnpd
bojf!ob{xz!qmjlv!{b!qpnpd
lv!{b!qpnpd
gvoldkj!HFUTUSJOH
gvoldkj!HFUTUSJOH
Funkcja posiada format:
(getstring [cr][prompt])

Funkcja ta powoduje przerw, ktra umoliwia uytkownikowi wprowadzenie nazwy


pliku. Gdy jest to konieczne, nazw pliku poprzedzamy jego ciek dostpu. Podczas
wykorzystania funkcji getstring do pobrania nazwy pliku, nie mona uywa argumentu cr (lub naley poda ten argument jako nil) uniemoliwiamy wtedy podanie
w nazwie pliku spacji.
Poniej podano przykadowe wywoania funkcji getstring, odpowiedzi uytkownika
oraz przykady otwarcia i zamknicia plikw.
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:

Wystpujcy w nazwie pliku pojedynczy lewy ukonik (\) podlega konwersji na dwa
lewe ukoniki (\\). Konwersja taka umoliwia podanie prawidowej cieki dostpu do
pliku. Funkcja otwarcia pliku open zwraca wskanik do niego (deskryptor pliku), plik
zostanie wic zamknity funkcj close wystpujc 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:

Wystpujcy w nazwie pliku pojedynczy prawy ukonik (/) umoliwia drug metod
podania prawidowej cieki dostpu do pliku. Plik ten zostanie rwnie otwarty,
a nastpnie zamknity.
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 powyszym przykadzie, w nazwie pliku uyto dwch lewych ukonikw (\\).


Podlegaj one konwersji na cztery lewe ukoniki (\\\\). Tak podana cieka dostpu do
pliku jest bdna funkcja open zwraca nil, nie zostanie wic wykonana funkcja
zamknicia 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 powyszym przykadzie, w nazwie pliku uyto dwch prawych ukonikw (//)


i w takiej postaci zwraca je te funkcja getstring. Tak podana cieka dostpu do pliku
jest bdna funkcja otwarcia pliku open zwrci nil, nie zostanie tym samym wykonana funkcja zamknicia pliku close.

26/3/3/ Qpcjfsb
Qpcjfsbojf!ob{xz!qmj
ojf!ob{xz!qmjlv!{b!qpnpd
ojf!ob{xz!qmjlv!{b!qpnpd
lv!{b!qpnpd
gvoldkj!HFUGJMFE
gvoldkj!HFUGJMFE
Funkcja posiada format:
(getfiled title default ext flags)

Funkcja wywietla okno dialogowe zawierajce nazwy plikw we wskazanym katalogu.


Zmieniajc katalog powodujemy uaktualnienie listy plikw w nim zawartych. Plik
mona wskaza na licie (w tym przypadku musi to by plik ju istniejcy nawet
jeli jest to plik pusty), lub mona wpisa jego nazw (z opcjonaln ciek dostpu)
w polu dialogowym File: (Plik:) w tym przypadku wpisujemy nazw pliku ju
istniejcego lub nazw nowego pliku do utworzenia.
Funkcja getfiled wywoywana jest z czterema argumentami:
title
acuch okrelajcy nagwek okna (jest on wypisywany w belce tytuowej okna). Moesz poda dowolny acuch do wywietlenia w belce tytuowej okna. Gdy dugo
acucha przekracza 46 znakw, koniec acucha jest obcinany. Podanie pustego acucha "" jako argumentu funkcji nie wywietla adnego napisu w belce tytuowej.
default
acuch okrelajcy domyln nazw pliku wraz z rozszerzeniem i ew. ciek dostpu.
Jeli w nazwie pliku podana jest cieka dostpu, to zawarto wskazywanego przez ni
katalogu zostanie wywietlona w oknie. Bez podania cieki funkcja getfiled wywietli
zawarto biecego katalogu. Jeeli podana zostanie podstawowa nazwa pliku to
zostanie umieszczona w polu edycyjnym File: (Plik:). Jeeli plik o wskazanej nazwie ju

633

BvupMJTQ!!qsbluzd{oz!lvst
istnieje, to zostanie on podwietlony na licie plikw. Dostpny jest rwnie przycisk
Default (Standard), ktry pozwala na natychmiastowy wybr pliku domylnego.
ext
acuch okrelajcy rozszerzenie pliku. Jeeli zostanie podany acuch pusty ""
to wywietlone zostan wszystkie pliki znajdujce si w katalogu. Jeeli wystpi
okrelone rozszerzenie, to na licie znajd si wycznie pliki, ktre maj takie samo
rozszerzenie.
flags
Liczba cakowita (znacznik bitowy) sterujca dziaaniem okna dialogowego. Aby
jednoczenie ustali wiksz liczb warunkw, naley po prostu zsumowa wartoci
(w dowolnej kolejnoci), tworzc warto argumentu flags z zakresu od 0 do 15.
Wartoci i znaczenie argumentu flags s nastpujce:
1. oznacza danie utworzenia nowego pliku,
2. blokuje przycisk Type it (Wpisz),
3. pozwala uytkownikowi wprowadzi dowolne rozszerzenie nazwy pliku,
4. wykonuje szukanie pliku o podanej nazwie w ciece poszukiwania bibliotek
AutoCADa,
Po otrzymaniu od uytkownika poprawnej nazwy pliku (wyjcie z okna dialogowego
przyciskiem OK), funkcja getfiled zwraca acuch z nazw pliku. W przypadku wyjcia
z okna dialogowego przyciskiem Cancel, funkcja getfiled zwraca nil.
Oto kilka przykadowych wywoa funkcji getfiled z linii komend.
Command: (getfiled "" "" "" 2)

Naley wskaza plik ju istniejcy. Belka tytuowa okna dialogowego jest pusta, nie
wystpuje domylna nazwa pliku, rozszerzenie pliku moe by dowolne. Przyciski
Type it (Napisz) oraz Default (Standard) s zablokowane.
Command: (getfiled "Wybierz Plik" "" "" 3)

Moemy wskaza plik ju istniejcy lub wpisa nazw nowego pliku. W przypadku,
gdy plik istnieje ju na dysku, jestemy o tym informowani przy pomocy dodatkowego
okna dialogowego. Opuszczajc okno dodatkowe przyciskiem OK, wybieramy opcj
przepisania pliku, wybierajc za przycisk Cancel wracamy do gwnego okna dialogowego funkcji getfiled.
Wybr pliku istniejcego do zapisu moe oznacza dwie moliwoci:

nowe dane cakowicie zastpi stare plik otwarty w trybie "w" (write
do zapisu),

nowe dane zostan dopisane do koca pliku plik otwarty w trybie "a" (append do dopisywania).

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

Moemy wskaza plik ju istniejcy lub wpisa nazw nowego pliku. Wybranie pliku
o rozszerzeniu innym ni LSP powoduje zablokowanie moliwoci opuszczenia okna

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

634

przyciskiem OK w dole okna wypisywany jest wwczas komunikat ostrzegawczy


o zym typie rozszerzenia wybranego pliku.
Command: (getfiled "Wybierz plik LSP" "" "lsp" 7)

Domylne rozszerzenie pliku to LSP, mamy jednak moliwo jego zmiany. Osigamy
to dodajc do argumentu flags cyfr 4.
Poniej podano przykad programu do testowania funkcji getfiled. Program dziaa w ptli,
wywoujc kadorazowo funkcj getfiled. Po opuszczeniu okna przyciskiem OK w linii
komend wypisywany jest wybrany plik wraz z rozszerzeniem i ciek dostpu.
;*************************************************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

Omwmy teraz wyrnione linie i bloki programu.


 Wywoujemy funkcj getfiled, podstawiajc jej warto zwrotn pod zmienn
plik. Moemy wybra plik ju istniejcy lub wpisa nazw nowego pliku.
 Wykorzystujc zmienn systemow AutoCADa DIASTAT badamy, czy okno
dialogowe funkcji getfiled zostao opuszczone przyciskiem OK (status = 1), czy
te przyciskiem Cancel (status = 0).
 Ten blok instrukcji jest wykonywany wwczas, gdy zmienna status ma warto
1 (wybrano przycisk OK). Wypisujemy wwczas w linii komend wybrany plik.
 Ten blok instrukcji jest wykonywany wwczas, gdy zmienna status ma warto
0 (wybrano przycisk Cancel).
 Ustawiamy bity i sowa kluczowe funkcji initget, obowizujce podczas
wywoania funkcji getkword.
 Uytkownik decyduje, czy chce zakoczy wykonywanie programu. Warto
zwrotn funkcji getkword podstawiamy pod zmienn odp.
 Zamieniamy wszystkie litery w zmiennej odp na due.
 Ten blok instrukcji wykonywany jest wwczas, gdy uytkownik zadecydowa
o zakoczeniu wykonywania programu. Ustawiamy wwczas warto zmiennej
jeszcze na nil, umoliwiajc tym samym opuszczenie ptli while.
Poniej zaprezentowany zostanie program wykorzystujcy funkcj getfiled, edytor
Nortona oraz komend NE utworzon w pliku ACAD.PGP. Zadaniem programu jest
pobranie nazwy pliku tekstowego za pomoc funkcji getfiled, a nastpnie umoliwienie
edycji wybranego pliku edytorem Nortona. Po zakoczeniu edycji pliku wracamy
z powrotem do rodowiska AutoCADa. W przypadku powtrnego wywoania funkcji
w tej samej sesji rysunkowej, program ma proponowa jako nazw domyln ostatnio
edytowany plik. Dodatkowo, naley zdefiniowa zmiann globaln glob_ext, bdc
filtrem rozszerzenia plikw wywietlanych przez funkcj getfiled. Zmienn t naley
ustawi na warto "LSP". W przypadku, gdy wartoci zmiennej glob_ext jest pusty
acuch, funkcja getfiled wywietla wszystkie pliki.

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf
;*************************************************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

636

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

Omwmy teraz wyrnione linie i bloki programu.


 Ustawiamy warto zmiennej globalnej glob_ext, bdcej filtrem rozszerzenia
plikw wywietlanych w oknie dialogowym getfiled.
 Definiujemy zewntrzn komend AutoCADa EDIT, pobierajc nazw pliku
do edycji i wywoujc edytor Nortona.
 W bloku tym sprawdzamy warto zmiennej globalnej glob_$_file_name.
Zmienna ta wskazuje ciek dostpu i nazw ostatnio edytowanego pliku. Jeli
wartoci zmiennej jest nil, oznacza to, e funkcja EDIT jest wywoywana po
raz pierwszy w biecej sesji. Ustawiamy wwczas warto zmiennej glob_$
_file_name na pusty string. Jeli wartoci zmiennej nie jest nil, sprawdzamy
dodatkowo, czy jest to zmienna typu acuchowego. Jeli nie, ustawiamy warto zmiennej glob_$_file_name na pusty string.
 W bloku tym wywoujemy funkcj getfiled, umoliwiajc uytkownikowi
wybr pliku do edycji. Sposb wywoania funkcji getfiled zaley od wartoci
zmiennej globalnej glob_$_file_name. W przypadku, gdy jest to pusty string,
oznacza to, e komend EDIT wywoujemy po raz pierwszy w biecej sesji.
Nie proponujemy wwczas wartoci domylnej nazwy pliku. W przypadku, gdy
warto zmiennej globalnej glob_$_file_name nie jest pustym stringiem, jest ona
podstawiana jako argument default funkcji getfiled. Wystarczy wwczas po
wywietleniu okna dialogowego wybra przycisk OK, aby uruchomi edytor
Nortona z ostatnio edytowanym plikiem.
 Ta instrukcja warunkowa if jest wykonywana wwczas, jeli okno dialogowe
getfiled opuszczono poprzez wybranie przycisku OK.
 Sprawdzamy, czy uytkownik wybra plik ju istniejcy na dysku czy te naley
utworzy nowy plik.
 Jeli wybrano plik ju istniejcy na dysku, ustawiamy warto zmiennej glob_$
_file_name na nazw pliku wraz ze ciek dostpu, po czym wywoujemy
edytor Nortona.
Jeli wybrano edycj nowego pliku, ustawiamy warto zmiennej glob_$_file
_name na nazw pliku wraz ze ciek dostpu, otwieramy plik w trybie do
zapisu, zamykamy plik (tworzymy tym samym pusty plik na dysku), po czym
wywoujemy edytor Nortona. Musimy tak zrobi dlatego, poniewa Norton
Edytor wywoywany z wntrza AutoCADa nie rozpoznaje prawidowo cieki
dostpu do pliku, ktry dopiero naley utworzy (zapisuje taki plik w katalogu,
z ktrego zosta uruchomiony AutoCAD). Utworzenie pustego pliku na dysku,
a nastpnie jego edycja rozwizuje ten problem.
 Definiujemy zewntrzn komend AutoCADa ED, wywoujc komend EDIT.
Tym samym mamy dwie komendy realizujce to samo zadanie: ED oraz EDIT.

639

BvupMJTQ!!qsbluzd{oz!lvst

26/3/4/
Tqsbxe{bojf!jtuojfojb!qmj
e{bojf!jtuojfojb!qmjlv!{b!qpnpd
26/3/4/ Tqsbx
e{bojf!jtuojfojb!qmjlv!{b!qpnpd
lv!{b!qpnpd
gvoldkj!GJOEGJMF
gvoldkj!GJOEGJMF
Funkcja findfile posiada format:
(findfile filename)

Funkcja poszukuje okrelonego pliku w bibliotecznej ciece poszukiwa AutoCADa


i w razie sukcesu zwraca pen nazw pliku wraz ze ciek dostpu.
Funkcja ta umoliwia napisanie aplikacji poszukujcej pliku o podanej nazwie.
Aplikacja moe okrela katalog do przeszukania, albo moe korzysta z biecej
bibliotecznej cieki poszukiwa AutoCADa.
W poniszym fragmencie kodu funkcja findfile poszukuje pliku w ciece 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

Jeli wywoanie findfile zakoczy si sukcesem, zmiennej plik zostanie przypisany


acuch tekstowy z nazw pliku z pen ciek dostpu, na przykad:
"c:/acad/testy/test1.dwg"
Przy podawaniu cieki dostpu w systemie DOS wewntrz procedury w AutoLISPie, ukonik lewy "\" musi by poprzedzony przez drugi ukonik lewy "\\".
Zamiast dwch ukonikw lewych "\", w charakterze separatora nazw
katalogw mona stosowa jeden ukonik prawy "/".

Funkcja findfile zwraca nil w nastpujcych przypadkach:


podano bdn ciek dostpu do pliku,
podano bdn nazw pliku,
podano nazw pliku, ktry naley dopiero utworzy.
Funkcj findfile mona wykorzysta w poczeniu z funkcj getfiled. Funkcja getfiled,
jeeli zostaa opuszczona poprzez wybranie przycisku OK, zwraca poprawn ciek
dostpu do pliku wraz z nazw pliku i jego rozszerzeniem. Warto zwrotna funkcji
getfiled moe by nastpnie podana jako argument funkcji findfile. Aplikacja moe

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

63:

wwczas wychwyci, czy uytkownik wybra plik istniejcy na dysku, czy te naley
utworzy podany plik.
Poniszy program pokazuje sposb wykorzystania funkcji findfile w poczeniu
z funkcj getfiled. Program dziaa w ptli, wywoujc kadorazowo funkcj getfiled. Po
opuszczeniu okna przyciskiem OK w linii komend wypisywany jest wybrany plik wraz
z rozszerzeniem i ciek dostpu. Dodatkowo wywoywana jest funkcja findfile, aby
okreli, czy plik zwrcony przez funkcj getfiled istnieje ju na dysku czy jest to plik
wymagajcy 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 testujcego funkcj getfiled,


omwione zostan tylko nowe elementy programu.
 Jeli funkcja getfiled zostaa opuszczona poprzez wybranie przycisku OK,
wykorzystujemy funkcj findfile aby zbada, czy wybrano plik istniejcy czy te
plik, ktry naley utworzy.
 Ten blok instrukcji jest wykonywany wwczas, gdy funkcja getfiled zwrcia
nazw pliku istniejcego.
 Ten blok instrukcji jest wykonywany wwczas, gdy funkcja getfiled zwrcia
nazw nowego pliku.

26/3/5/
Gvoldkb!SFUVSO`Q
b!SFUVSO`QBUI!
26/3/5/ Gvoldk
b!SFUVSO`QBUI!
BUI!!sp{t{fs{fojf
!sp{t{fs{fojf
tdjf-lj!qpt{vljxbojb!qmjl
tdjf-lj!qpt{vljxbojb!qmjl.x
{vljxbojb!qmjl.x
Funkcja findfile przeszukuje okrelony katalog lub katalogi AutoCADa okrelone
zmienn rodowiskow ACAD. Biblioteczna cieka poszukiwa jest przeszukiwana
w nastpujcej kolejnoci:

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

642

katalog biecy,
katalog zawierajcy plik biecego rysunku,
katalogi okrelone przez zmienn rodowiskow ACAD,
katalog zawierajcy plik ACAD.EXE.
W zalenoci od biecego rodowiska, dwa lub wicej tych katalogw , moe
by w rzeczywistoci tym samym katalogiem.

Piszc programy, chcemy czasami wykorzystywa katalogi, ktrych nie chcemy zacza do bibliotecznej cieki poszukiwa AutoCADa. Powyszy problem mona rozwiza na dwa sposoby:
umieci w pliku LSP zmienne okrelajce 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 katalogw, musimy dokona modyfikacji


zmiennych w pliku LSP.
posugujc 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 katalogw, dokonujemy jedynie modyfikacji


zmiennej rodowiskowej app1.
Poniej przedstawiono funkcj RETURN_PATH, ktra pobiera zawarto okrelonej
zmiennej rodowiskowej oraz rozbija j na list acuchw, z ktrych kady jest pen
ciek dostpu do plikw uytkownika, 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
Omwmy teraz wyrnione linie i bloki programu.
 Wykorzystujc funkcj AutoLISPu getenv, pobieramy warto zmiennej systemowej przekazanej w argumencie env_var i podstawiamy j pod zmienn path.
Format funkcji getenv jest nastpujcy:
(getenv variable-name)

Funkcja ta zwraca warto typu string w postaci acucha alfanumerycznego


przypisanego do systemowej zmiennej rodowiskowej. Argument variable-name
jest acuchem okrelajcym nazw zmiennej, ktrej warto ma by odczytana.
Jeli taka zmienna nie istnieje, to funkcja getenv zwraca nil.
 Jeli zmienna systemowa zostaa ustawiona (dotyczy to take przypadku set
variable= ), przystpujemy do jej przetwarzania.
 Obliczamy dugo acucha reprezentujcego zmienn systemow.
 Jeli dugo zmiennej systemowej jest wiksza od zera, rozpoczynamy przetwarzanie zmiennej na list podacuchw. Zmienn licznik (kolejne znaki w
zmiennej systemowej) ustawiamy na 1, zmienn substring (acuch oznaczajcy
kolejne cieki dostpu do plikw) ustawiamy na pocztek jako acuch pusty.
 Wchodzimy w ptl repeat i rozpoczynamy przetwarzanie zmiennej systemowej.
 Pobieramy kolejny znak z acucha reprezentujcego zmienn systemow.
 Ten blok instrukcji jest wykonywany wwczas, gdy znak jest separatorem koca
cieki dostpu ";". Sprawdzamy wwczas, czy cieka dostpu koczy si
ukonikiem (prawym lub lewym). Jeli nie, dodajemy ukonik na koniec acucha w zmiennej substring. Nastpnie doczamy acuch do listy podacuchw oraz ustawiamy zmienn substring na pusty acuch jestemy gotowi
do szukania kolejnej cieki dostpu.
 Ten blok instrukcji jest wykonywany wwczas, gdy znak nie jest separatorem koca
cieki dostpu doczamy go wwczas na koniec acucha w zmiennej substring.
Zwikszamy zmienn licznik o 1, umoliwiajc tym samym przetworzenie
kolejnego znaku zmiennej rodowiskowej.

Ten blok instrukcji wykonywany jest ju po wyjciu z ptli repeat, a wic po


przetworzeniu caej zmiennej rodowiskowej. Jeli ostatnim znakiem zmiennej
nie bdzie znak separatora koca cieki ";" ostatni podacuch bdzie si
znajdowa w zmiennej substring, nie zostanie on jednak automatycznie dodany
do listy podacuchw. Tak wic, gdy zmienna substring nie jest acuchem
pustym, sprawdzamy, czy cieka dostpu koczy si ukonikiem (prawym lub
lewym). Jeli nie, dodajemy ukonik na koniec acucha po czym doczamy
acuch na koniec zmiennej lista.
Dla lepszego zrozumienia dziaania funkcji, w poniszej tabeli podano 7 przykadw
jej wywoania. Poszczeglne 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. Przykady wywoania 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 midzy programem a komputerem, otwiera si za pomoc funkcji


open, korzystajc ze skadni pokazanej poniej:
(setq plik (open filename mode))

647

BvupMJTQ!!qsbluzd{oz!lvst
Pierwszy z argumentw funkcji open filename (nazwa_pliku) jest acuchem
zawiercym nazw pliku (wraz z rozszerzeniem i ew. ciek dostpu), ktra musi
spenia konwencje zwizane z nazywaniem plikw obowizujce w danym komputerze (systemie operacyjnym). W systemie DOS jej dugo nie moe przekroczy 8
znakw z opcjonalnym, co najwyej trzyznakowym rozszerzeniem. Aby dane wyjciowe wydrukowa zamiast wysa je do pliku na dysku, trzeba jako nazwy pliku uy
"LPT1" lub "PRN" (w cudzysowach). W ten sposb dane bd automatucznie
wysyane na drukark.
Drugi argument funkcji open mode (tryb) jest acuchem okrelajcym typ
operacji, ktr bdziemy wykonywa na pliku (koniecznie mae litery). Moe to by:
"r" Wskazuje, e mamy zamiar odczyta informacje z pliku do komputera. Jeli
plik nie istnieje jeszcze na dysku, to wystpi bd wykonania programu.
"w" Wskazuje, e mamy zamiar zapisa dane na dysku lub drukarce. Jeli plik
jeszcze nie istnieje, to system operacyjny go utworzy. Jeli jednak plik ju jest
na dysku, to wszystkie zawarte w nim informacje zostan zatarte.
"a" Wskazuje, e mamy zamiar doda dane do koca pliku. Jeli plik jeszcze nie
istnieje, to system operacyjny go utworzy. Jeli plik ju jest na dysku, to
wyprowadzane dane zostan dodane na koniec pliku, bez zacierania jego
zawartoci.
Przykadowo, poniszy zapis:
(setq plik (open "obudowa1.dat" "r"))

otwiera plik OBUDOWA1.DAT do odczytu, umoliwiajc dostp do jego zawartoci dla


funkcji Wejcia/Wyjcia AutoLISPu. Funkcja open zwraca deskryptor pliku, ktry jest
przeznaczony do wykorzystywania przez inne funkcje Wejcia/Wyjcia. Z tego
wzgldu musi by on przypisany do symbolu za pomoc funkcji setq (w naszym
przykadzie deskryptor pliku podstawiany jest pod zmiann plik).
Po zapisaniu lub odczytaniu danych z pliku trzeba zamkn poczenie midzy plikiem
a komputerem. W tym celu korzysta si z funkcji close o skadni:
(close file-desc)

Zamknicie pliku upewnia nas, e wszystkie informacje w buforze zostay zapisane


w pliku. Jeli zakoczymy program przed zamkniciem pliku, to kada nie zapisana
informacja bdca cigle w buforze moe nie zosta wyprowadzona i w konsekwencji
stracona. Znak koca pliku moe nie zosta poprawnie wstawiony, wskutek czego system operacyjny nie bdzie mg w pniejszym czasie uzyska dostpu do pliku.
Oprcz tego po zamkniciu pliku moemy zwolni wskanik do pliku, ktrego mona
wobec tego uy do innego pliku.
Kada funkcja wsppracujca z plikiem powinna zawiera nastpujce instrukcje, jak
ponisza przykadowa sekwencja:

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf
(setq plik (open nazwa_pliku tryb))
.....
(close plik)

648

;otwarcie pliku
;przetwarzanie pliku
;zamkniecie pliku

Otwarcie pliku moe by rozumiane jako nawizanie poczenia z wybranym plikiem


w celu umoliwienia przepywu strumienia danych, natomiast zamknicie pliku jako
przerwanie tego poczenia. Liczba jednoczenie otwartych plikw uzaleniona jest od
szczegw zwizanych z otoczeniem programu (np. ogranicze narzuconych przez
wykorzystywany system operacyjny lub takie czy inne jego skonfigurowanie).
Dane mona przenosi do i z plikw na rne 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 acuchami (wierszami), korzystamy
z funkcji write-line.
Aby odczyta dane z pliku acuchami (wierszami), korzystamy z funkcji read-line.
Aby zapisa sformatowane znaki, acuchy 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
doczonej do ksiki dyskietce.
Aby odczyta sformatowane znaki, acuchy i liczby, korzystamy z funkcji
SSCANF, zawartej w pliku SCANF1.LLB.

Jeli chcemy zapisa dane w pliku, mamy do dyspozycji nastpujce funkcje: writechar, write-line, princ, prin1, print lub funkcje grupy PRINTF. Plik otwieramy albo
w trybie do zapisu ("w"), albo w trybie dopisywania ("a"). Poniej przedstawiono
przykady zastosowa poszczeglnych funkcji.

26/5/2/![bqjt!ebozd
26/5/2/![bqjt!ebozdi!qpkfez
qjt!ebozdi!qpkfezod{p!{obl!qp!{oblv
i!qpkfezod{p!{obl!qp!{oblv
Przenoszenie danych po jednym znaku na raz to najbardziej podstawowa forma operacji
na pliku. Nie jest to pewnie najpraktyczniejszy sposb postpowania z informacj, ale
moe pokaza jak korzysta z plikw. Na przykad poniszy program zapisuje
wprowadzane znaki w pliku, dopki nie naciniemy 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
;---------);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 moe by nastpujce:


Command: (load "prog_113")

Program zaladowany. Komenda TEST uruchamia


Command: test

Wprowadz znak [ENTER lub spacja - koniec]:


Wprowadz znak [ENTER lub spacja - koniec]:
Wprowadz znak [ENTER lub spacja - koniec]:
Wprowadz znak [ENTER lub spacja - koniec]:
Wprowadz znak [ENTER lub spacja - koniec]:

testowanie.
T

zapisu

64:

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 bdzie nastpujca:


Testzdp

Omwmy teraz wyrnione linie i bloki programu.


 W bloku tym podstawiamy pod zmienn plik nazw pliku, w ktrym bdziemy
zapisywa wprowadzone dane. Nastpnie otwieramy plik do zapisu oraz podstawiamy warto zwrotn funkcji open pod zmienn file_desc.
 Ten blok instrukcji jest wykonywany wwczas, jeeli wystpi bd otwarcia
pliku. Wypisujemy wwczas odpowiedni komunikat w obszarze komend oraz
koczymy dziaanie funkcji.
 Ten blok instrukcji jest wykonywany wwczas, gdy funkcja open zwrcia
deskryptor pliku (plik zosta otwarty do zapisu).
 W bloku tym wchodzc w ptl while, rozpoczynamy pobieranie i przetwarzanie
znakw wpisanych przez uytkownika.
 Wykorzystujc funkcj read-char pobieramy cig znakw z klawiatury i wybieramy pierwszy znak z cigu, podstawiajc go pod zmienn znak.
 W bloku tym badamy, czy zosta wprowadzony znak spacji lub ENTER.
Zarwno spacja, jak i ENTER daje w funkcji read-char ten sam kod znaku
rwny 10.
Jeli kod wprowadzonego znaku jest rwny 10, ustawiamy zmienn jeszcze1 na
nil, umoliwiajc tym samym wyjcie z ptli while.
Jeli kod wprowadzonego znaku jest rny od 10, zapisujemy znak do pliku
wykorzystujc funkcj write-char, a nastpnie czycimy bufor klawiatury przy
pomocy funkcji OPROZNIJ_BUFOR.
Koczc omawianie programu, naley jeszcze powiedzie par zda na temat celowoci
stosowania funkcji OPROZNIJ_BUFOR. Funkcja read-char odczytuje jeden znak
z wejciowego bufora klawiatury lub z otwartego pliku o podanym deskryptorze i zwraca kod ASCII odczytanego znaku. Jeeli wejciowy bufor klawiatury jest pusty, to
read-char czeka na wprowadzenie czegokolwiek z klawiatury i nacinicie klawisza
ENTER. Przykadowo, jeeli bufor klawiatury jest pusty, to
Command: (read-char)

oczekuje na wprowadzenie dowolnego acucha znakw zakoczonego spacj lub


ENTER. Jeeli zostanie teraz wpisane sowo TEST, zakoczone spacj lub ENTER, to
read-char zwrci 84 (kod ASCII litery T). Nastpne cztery wywoania read-char
dadz odpowiednio 69, 83, 84 i 10 (kod znaku nowej linii). Po kolejnym wywoaniu
funkcji read-char nastpi ponowne oczekiwanie na wprowadzenie znakw.

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

652

Poniewa w programie uytkownik powinien wprowadzi kadorazowo jeden znak, aby


uchroni si od przypadku penego bufora klawiatury przy kolejnym wywoaniu funkcji
read-char, zbudowano funkcj OPROZNIJ_BUFOR, ktrej zadaniem jest oprnienie bufora klawiatury. Funkcja read-char jest w niej wywoywana tak dugo, dopki
nie zwrci znaku nowej linii. Dlatego podanie przez uytkownika wyrazw zapisu

do
pliku
spowodowao zapis w pliku liter zdp oraz automatyczne wyczyszczenie
bufora klawiatury po kadym cigu znakw.
Niedogodnoci stosowania funkcji read-char s nastpujce:
brak moliwoci zapisu poszczeglnych wyrazw (tj. umieszczania spacji
pomidzy wyrazami),
brak moliwoci przejcia do nowej linii.

26/5/3/![bqjt!ebozdi!1b2d
6/5/3/![bqjt!ebozdi!1b2dvdibnj
ebozdi!1b2dvdibnj
Zapis oraz odczyt danych acuchami stanowi podstawowy typ operacji na plikach.
Przy zapisie do pliku danych acuchami moemy wykorzysta nastpujce funkcje:
princ, prin1, write-line oraz FPRINTF. Poniej przedstawiono przykad zapisu do
pliku z wykorzystaniem funkcji write-line.
Funkcja ta ma format:
(write-line string [file-desc])

Funkcja zapisuje acuch alfanumeryczny string na ekranie lub do otwartego pliku wskazywanego 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 powyszego programu moe by nastpujce:


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 bdzie nastpujca:


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

Omwmy teraz wyrnione linie i bloki programu:


 Wchodzimy w ptl while rozpoczynamy pobieranie i przetwarzanie wprowadzonych linii tekstu.
 Wykorzystujc funkcj read-line pobieramy kolejny wiersz tekstu.
 Jeli uytkownik nacisn klawisz F2 a po nim Enter, przerywamy dziaanie
funkcji, w przeciwnym wypadku zapisujemy wprowadzony wiersz do pliku wykorzystujc funkcj write-line.
Przedstawione powyej przykady uycia funkcji write-char oraz write-line pokazuj
nam sposoby zapisu danych do pliku, gdzie dane podaje bezporednio uytkownik.
Najczciej jednak dane do zapisu s przygotowywane przez poszczeglne funkcje na
podstawie danych podanych przez uytkownika, odczytanych z pliku, obliczonych przez
funkcje programu itp. Przykadem takiego zbioru danych niech bdzie zapis konstrukcji
dla programu obliczeniowego metod elementw skoczonych. Zbir danych wejciowych dla programu obliczeniowego ma zazwyczaj budow moduow, gdzie poszczeglne moduy odzwierciedlaj zapis matematyczny modelu konstrukcji. Najwaniejszymi
moduami opisujcymi konstrukcj s moduy: wzy, elementy oraz charakterystyki
elementw, z ktrych to moduw zajmiemy si dokadnie dwoma pierwszymi.
Przystosowanie programu AutoCAD do budowy siatki MES polega na budowie modelu
konstrukcji oraz jego utwierdzeniu i obcieniu. Zbiorem wyjciowym z programu jest
zbir tekstowy ASCII w formacie wymaganym przez dany program obliczeniowy MES.
Program pracujcy w rodowisku AutoCADa musi mie rwnie moliwo wczytania
tak utworzonego zbioru i odtworzenia na jego podstawie modelu konstrukcji.

655

BvupMJTQ!!qsbluzd{oz!lvst
Poniej podano format zbioru danych dla programu metody elementw skoczonych
PAFEC FE. Nie jest to jeszcze zbir kompletny, jest on jednak wystarczajcy do pokazania sposobu zapisu wzw i elementw 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

Zbir danych ma budow moduow. Koniec zbioru zaznaczony jest przez lini
END.OF.DATA dane znajdujce si poniej tej linii nie bd brane pod uwag.
Komentarze zaczynaj si od litery C, po ktrej nastpuje co najmniej jedna spacja.
Koniec moduu zaznaczony jest lini C END.OF.module_name np. dla moduu NODES
jest to linia C END.OF.NODES. Modu NODES (wzy) skada si z numeru wza
oraz jego wsprzdnych podanych w ukadzie globalnym. Modu ELEMENTS (elementy) skada si z numeru elementu, jego grupy, typu (belka, pyta, powoka, element
3-d), waciwoci oraz topologii (numery wzw, na ktrych rozpity jest element).
Dla potrzeb budowy modelu siatki MES pod AutoCADem dane o wzach oraz elementach skadowane s na dwch globalnych listach glob_lista_wezlow oraz glob
_lista_elementow. Podczas zapisu zbioru danych odpowiednie wartoci z tych list (nie
wszystkie) s pobierane, formatowane do odpowiedniej postaci i zapisywane do pliku.
Struktura danych siatki MES w programie AutoCAD przedstawia si nastpujco:
przykadowe dane dla pojedynczego wza
(1 "1" "2" (1.0
gdzie:
1
"1"
"2"
(1.0 1.0 0.0)

1.0 0.0) (0 1 5) (0) (0)

numer wza
identyfikator wza
identyfikator opisu wza
wsprzdne wza w ukadzie globalnym

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf
(0 1 5)
(0)
(0)

656

numery elementw przynalenych do wza


(0) wze nie naley do adnego elementu
numery utwierdze w wle
(0) brak utwierdze w wle
numery obcie w wle
(0) brak obcie w wle

przykadowe dane dla pojedynczego elementu


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

4.5 0.0) 1 34000 1 1 2)

numer elementu
identyfikator elementu
identyfikator opisu elementu
wsprzdne globalne rodka cikoci elementu
grupa elementu
typ elementu
waciwoci elementu
topologia elementu

Poniej przedstawiono program do zapisu siatki MES. Dane w postaci list wzw
i elementw zostay przygotowane w oparciu o model ustroju prtowego (w zadaniu nie
wystpuj elementy pytowe).
;*************************************************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"
;(setq x1k (FORMAT_VALUE x1 2 1)) => x1k = " 3.2"
;(setq x2k (FORMAT_VALUE x2 1 2)) => x2k = "12.50"
;
(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

1
2
3

26/!Pctvhb!qmjlx!ufltupxzdi!x!BvupMJTQjf
;---------(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

658

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
);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)

65:

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 bdzie nastpujce:


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.
Zapis wezlow.
Zapis elementow.

Zapisano.
Zapisano.
Zapisano.

Nacisnij ENTER...
Command:

Zawarto pliku $FILE_03.DAT bdzie nastpujca:


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 skada si z nastpujcych funkcji:

D[FLBK
Funkcja zatrzymuje realizacj programu do czasu nacinicia klawisza ENTER.

GPSNBU`WBMVF
GPSNBU`WBMVF
Funkcja dokonuje konwersji liczby cakowitej lub rzeczywistej na acuch o odpowiedniej postaci. W porwnaniu z funkcj rtos ma t zalet, e moemy doda spacje
przed cz cakowit, uzyskujc dla rnych liczb t sam dugo acucha. Poniej
podano kilka wywoa funkcji format_value oraz rtos.
(FORMAT_VALUE 1.25 5 2)
(rtos 1.25 2 2)

=>
=>

"
1.25"
"1.25"

(FORMAT_VALUE 300.123 3 0)
(rtos 300.123 2 0)

=>
=>

"300"
"300"

(FORMAT_VALUE 1250.5 1 4)
(rtos 1250.5 1 4)

=>
=>

"1250.5000"
"1250.5000"

(FORMAT_VALUE -10.75 6 4)
(rtos -10.75 2 4)

=>
=>

"
-10.7500"
"-10.7500"

VUXPS[`MJ
VUXPS[`MJTUZ`EBOZ
XPS[`MJTUZ`EBOZDI
TUZ`EBOZDI
Funkcja tworzy globalne listy wzw i elementw.

[BQJT[`NPEVM`
[BQJT[`NPEVM`DPOUSPM
NPEVM`DPOUSPM
Funkcja zapisuje w pliku modu sterujcy programem obliczeniowym.

[BQJT[`XF[MZ
[BQJT[`XF[MZ
Funkcja zapisuje w pliku modu danych o wzach.

[BQJT[`FMFNFO
[BQJT[`FMFNFOUZ
T[`FMFNFOUZ
Funkcja zapisuje w pliku modu danych o elementach.

665

BvupMJTQ!!qsbluzd{oz!lvst

[BQJT[`[CJPS`EB
[BQJT[`[CJPS`EBOZDI
CJPS`EBOZDI
Funkcja gwna do zapisu danych w pliku, wywoujca funkcje do zapisu poszczeglnych moduw.
Funkcje do zapisu wzw i elementw dziaaj wedug nastpujcego algorytmu:
w ptli repeat przegldaj listy wzw (elementw),
pobierz opis kolejnego wza (elementu),
wybierz wartoci, ktre maj si pojawi w zbiorze danych,
wartoci numeryczne przekszta na acuchy o odpowiedniej dugoci,
utwrz linie danych, czc ze sob wybrane acuchy przedzielone odpowiedni
iloci spacji,
zapisz linie danych w pliku.

26/5/4/![bqjt!ebo
26/5/4/![bqjt!ebozdi!x!qptu
4/![bqjt!ebozdi!x!qptubdj!mjtuz
zdi!x!qptubdj!mjtuz
Poniej przedstawiono program zapisujcy wszystkie dane w postaci jednej listy. Tak
utworzony zbir danych nie moe by bezporednio wczytany przez program PAFEC
FE, jest to jednak przykad 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
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

666

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
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")

668








669

BvupMJTQ!!qsbluzd{oz!lvst
(CZEKAJ)
(princ "Zapis zbioru danych.")
(ZAPISZ_ZBIOR_DANYCH)
(princ "
Zapisano.")
(CZEKAJ)
(graphscr)
(princ)
;
;=================================================
;*************************************************KONIEC

Wykonanie programu bdzie nastpujce:


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.
Nacisnij ENTER...

Zapisano.

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.
Omwmy teraz wyrnione linie i bloki programu.
 Tworzymy list moduu CONTROL o postaci
(CONTROL "CONTROL" "PHASE=9" "STRESS" "CONTROL.END")

 Tworzymy list wzw o postaci


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

 Tworzymy list elementw o postaci


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

 Tworzymy wspln list danych o postaci

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

66:

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

 Zapisujemy do pliku znak zapobiegajcy ewaluacji listy podczas wczytywania


pliku funkcj load.
 Zapisujemy do pliku wspln list danych.

26/5/5/!Gpsnbupxbo
26/5/5/!Gpsnbupxboz!{bqjt!ebozd
Gpsnbupxboz!{bqjt!ebozdi
z!{bqjt!ebozdi
Na dyskietce doczonej do ksiki znajduje si plik PRINTF.LLB, zawierajcy nastpujce funkcje:
(printf _$args)
(fprintf _$args _$var)
(sprintf _$var _$args)
Funkcje te mog wywietla dane dowolnego typu i wsppracowa z wieloma
argumentami. Oprcz tego mog formatowa pojawiajce si dane. Wartoci zwrotn
kadej funkcji jest sformatowany acuch lub nil w przypadku bdu. Funkcje te umieszczaj sformatowane dane w rnych miejscach, co zbiorczo przedstawiono poniej.
Funkcja

Gdzie umieszcza wprowadzane dane

printf

na ekranie

fprintf

w pliku okrelonym argumentem _$var

sprintf

w zmiennej okrelonej argumentem _$var

Przy zapisie do zmiennej zmienna musi by zmienn kwotowan, np. 'x

Argument _$args wskazuje tzw. acuch formatujcy. acuch ten jest taki sam, jak
kady inny acuch. Rnica polega na sposobie traktowania niektrych sekwencji
znakw tego acucha przez omawiane tu funkcje. Pewne specjalne sekwencje (o ktrych mowa dalej) s bowiem zastpowane odpowiednio (tzn. zgodnie ze wskazaniami
zawartymi w tych sekwencjach) danymi znajdujcymi si w parametrach nieustalonych
(tj. tych wymienionych po acuchu formatujcym) np. w acuchu:
"%s ma %d lat."

sekwencja %s zostanie zastpiona acuchem znakw wskazanym parametrem


nieustalonym, za %d dziesitn postaci kolejnego parametru nieustalonego funkcji.
Poniej pokazano przykad uycia funkcji printf.

671

BvupMJTQ!!qsbluzd{oz!lvst
(setq
imie "Jacek"
wiek 25
);setq
(printf '("%s ma %d lat." imie wiek))

Powysze wywoanie funkcji printf spowoduje wypisanie na ekranie napisu: Jacek


ma 25 lat.

Jak wida, kadej sekwencji znakw formatujcych odpowiada jeden parametr nieustalony funkcji: %s imie, %d wiek. Zachowanie rwnoci liczby sekwencji
formatujcych i parametrw nieustalonych jest niezbdne dla prawidowego dziaania
omawianych funkcji.
Sekwencja formatujca okrela typ odpowiadajcego jej parametru, wskazujc tym samym omawianym funkcjom waciwy sposb jego traktowania, np. napotkanie sekwencji %s informuje, e odpowiedni parametr wskazuje acuch znakw. Zgodno
typu wskazanego sekwencj formatujc z typem odpowiadajcego jej parametru jest
kolejnym warunkiem niezbdnym dla prawidowego dziaania omawianych funkcji.
Oglny format sekwencji formatujcych przedstawia si nastpujco:
%[flagi][szeroko][.precyzja]znak-typu

Wszystkie sekwencje formatujce rozpoczynaj si znakiem %. Kolejne elementy okrelaj:


flagi
typ justowania
szeroko
liczb wysyanych znakw
precyzja
liczb cyfr znaczcych
znak-typu
typ argumentu
Omawianie kolejnych elementw sekwencji formatujcych rozpoczniemy od tyu.

[oblj!uzqv
[oblj!uzqv
Pole znak-typu okrela typ argumentu i posta, w jakiej zostanie on przedstawiony. W poniszej tabeli przedstawiono typy akceptowane przez funkcje printf, fprintf i sprintf.
Tabela 15.3. Typ i posta argumentu znak-typu funkcji grupy printf
Typ

Argument wejciowy

Wyprowadzana posta tego argumentu po


przeformatowaniu

znak (acuch lub


0<int<256)

pojedynczy znak

cakowity

liczba cakowita w ukadzie dziesitnym, ze znakiem

zmiennoprzecinkowy

warto ze znakiem przedstawiona w postaci


wykadniczej ze znakiem e dla wykadnika

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

672

Tabela 15.3. Typ i posta argumentu znak-typu funkcji grupy printf (c.d.)
Typ

Argument wejciowy

Wyprowadzana posta tego argumentu po


przeformatowaniu

zmiennoprzecinkowy

warto ze znakiem przedstawiona w postaci


wykadniczej ze znakiem E dla wykadnika

zmiennoprzecinkowy

warto dziesitna ze znakiem

zmiennoprzecinkowy

jak typ f lub jak typ e

zmiennoprzecinkowy

jak typ f lub jak typ E

cakowity

liczba cakowita w ukadzie dziesitnym, ze znakiem

cakowity

liczba cakowita w ukadzie semkowym, bez znaku

acuch

znaki z acucha

lista 3 liczb rzeczywistych

3 liczby rzeczywiste

cakowity

liczba cakowita w ukadzie dziesitnym, bez znaku

cakowity

liczba cakowita w ukadzie szesnastkowym, bez


znaku; do jej zapisania printf uywa liter: a, b, c, d,
e, f

cakowity

liczba cakowita w ukadzie szesnastkowym, ze


znakiem; do jej zapisania printf uywa liter: A, B, C,
D, E, F

znak "%"

Tqfdzgjlbups!
Tqfdzgjlbups!qsfdz{kj
fdzgjlbups!qsfdz{kj
Pole [.precyzja] okrela maksymaln ilo znakw wyprowadzanego acucha lub ilo
cyfr po kropce wyprowadzanej liczby zmiennoprzecinkowej.

Tqfdzgjlbups!t{fsplp
Tqfdzgjlbups!t{fsplp*dj
gjlbups!t{fsplp*dj
Pole [szeroko] okrela minimaln ilo znakw, ktre maj by wyprowadzone.
Jeeli wynikowa warto ma wicej znakw ni okrelono wyraeniem [szeroko], to
ilo znakw na wyjciu jest automatycznie, odpowiednio powikszana.

Gmbhj
Jeeli w polu [flagi] nie uyto znaku "", wynik konwersji bdzie wyrwnany do
prawej strony i uzupeniony spacjami z lewej, jeeli za uyto go wyrwnywany do
lewej strony i uzupeniony spacjami z prawej.
Argument _$args, wystpujcy we wszystkich trzech funkcjach, jest kwotowan list
dzielc si na acuch sterujcy oraz list danych, np. '("X1 = %d, X2 = %d" x1 x2).

673

BvupMJTQ!!qsbluzd{oz!lvst
Pierwsza cz nazywa si acuchem sterujcym lub formatujcym. acuch sterujcy,
ten w cudzysowie, wskazuje, gdzie maj si pojawi dane w wywietlanym wierszu.
Zawiera dowolny tekst, ktry chcemy wywietli, wraz ze znakami-wypeniaczami,
nazwanymi specyfikatorami formatowania, wskazujcymi typ i pooenie danych.
Druga cz argumentu to lista danych, zawierajca wartoci, stae lub zmienne, ktre
chcemy wywietli. Poszczeglne elementy listy danych oddzielamy od siebie spacj.
Kiedy interpreter AutoLISPu tworzy acuch wynikowy, wstawia dan z listy w miejscu zajmowanym przez specyfikator formatu.
Aby zapozna si z funkcj printf w dziaaniu, proponuj przeanalizowanie kilku
przykadw zamieszczonych w poniszej tabeli.

Tabela 15.4. Przykady wywoania funkcji printf


(printf '("Test dzialania funkcji PRINTF."))
Test dziaania funkcji PRINTF."Test dzialania funkcji
PRINTF."
Jeli w acuchu sterujcym nie wystpuj specyfikatory formatu, funkcja printf dziaa
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 przejcia do nowego wiersza po
wywietleniu danych. Po wywietleniu acucha kursor pozostaje w tym samym wierszu po
ostatnim znaku. Jeli chcemy, aby kursor znalaz si w nastpnym wierszu, w acuchu
sterujcym musi znale si kod \n.
(printf '("Wypisz to\nw trzech\nwierszach.\n"))
Wypisz to
w trzech
wierszach.
"Wypisz to\nw trzech\nwierszach.\n"
Kod przejcia do nowego wiersza \n umieszczamy w tym miejscu, w ktrym chcemy rozpocz
nowy wiersz (niekoniecznie na kocu).
(setq znak "A")
(printf '("%c\n" znak))
A
"A"
Chcc wywietli pojedynczy znak, posugujemy si kodem formatujcym %c.
(printf '("%c\n" 65))
A
"A"
Zmienna typu znakowego moe take zosta zadeklarowana jako liczba cakowita z przedziau
od 0 do 256.

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

674

Tabela 15.4. Przykady wywoania 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 moe zawiera wywoania funkcji bibliotecznych AutoLISPu lub funkcji
uytkownika (w przykadzie wywoujemy funkcj AutoLISPu ascii). Wane jest, aby warto
zwrotna wywoanej funkcji bya zgodna ze specyfikatorem formatu.
(setq x 123.45)
(printf '("%f\n" x))
123.4500
"123.4500"
Jeeli w specyfikatorze formatu nie podano liczby wywietlanych miejsc dziesitnych, zostan
przyjte biece ustawienia komendy UNITS.
(printf '("%.2f\n" x))
123.45
"123.45"
Korzystajc ze specyfikatora szerokoci i precyzji pola moemy dostosowa sposb
wywietlania liczb i tekstu.
Aby okreli liczb miejsc dziesitnych, korzystamy z formatu %.nf gdzie n jest liczb
potrzebnych miejsc.
(printf '("%8.2f\n" x))
123.45
" 123.45"
Moemy rwnie sterowa cakowit szerokoci pola liczb miejsc, jakie zajmie caa
wywietlana warto korzystajc z formatu %N.nf gdzie N oznacza cakowit szeroko
pola przeznaczonego na wywietlenie liczby (jest to suma pl czci cakowitej, jednego pola
na kropk oraz pl czci dziesitnej). Sama liczba 123.45 zajmuje 6 znakw kropka
dziesitna 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"
Moemy rwnie dodatkow przestrze przed liczb wypeni zerami zamiast spacjami.
Osigamy to dopisujc 0 przed liczb mwic o szerokoci pola %08.2f.
(printf '("%-8.2f\n" x))
123.45
"123.45 "
Aby wyrwna wartoci do lewej, tzn. umieci je po lewej stronie pola, trzeba wstawi znak
minus po % %-8.2f. Dodatkowe spacje pojawi si po wartoci.
(printf '("%-08.2f\n" x))
123.4500
"123.4500"
Jeli zadamy wypenienia dodatkowych wolnych pl zerami, i jednoczenie ustawimy
lewostronne wyrwnanie w polu, specyfikator precyzji pola zostanie zignorowany.

675

BvupMJTQ!!qsbluzd{oz!lvst

Tabela 15.4. Przykady wywoania funkcji printf (c.d.)


(printf '("%2.1f\n" x))
123.5
"123.5"
Jeli specyfikator szerokoci pola jest mniejszy ni liczba cyfr cakowitych 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 acuchy podane w zmiennych x1 i x2.
(printf '("%20s%s\n" x1 x2))
Test dzialania funkcji PRINTF.
"
Test dzialania funkcji PRINTF.\n"
czymy dwa acuchy podane w zmiennych x1 i x2, przy czym szeroko acucha w
zmiennej x1 ustawiamy na 20 pl. Wolne pola zostan uzupenione spacjami z lewej.
(printf '("%-20s%s\n" x1 x2))
Test dzialania
funkcji PRINTF.
"Test dzialania
funkcji PRINTF.\n"
czymy dwa acuchy podane w zmiennych x1 i x2, przy czym szeroko acucha w
zmiennej x1 ustawiamy na 20 pl. Wolne pola zostan uzupenione spacjami z prawej.
(printf '("%5s%5s\n" x1 x2))
Test dzialania funkcji PRINTF.
"Test dzialania funkcji PRINTF.\n"
Jeli specyfikatory szerokoci pl s mniejsze od ich rzeczywistej szerokoci, 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 szerokoci pl wiksze od ich rzeczywistej szerokoci,
specyfikatory precyzji s ignorowane.
(printf '("%10.5s%10.7s\n" x1 x2))
Test funkcji
"Test funkcji\n"
W przypadku, gdy podano specyfikatory szerokoci pl mniejsze od ich rzeczywistej
szerokoci, acuchy s obcinane na dugo zgodn z podanymi specyfikatorami precyzji.
(printf '("%.5s%.7s\n" x1 x2))
Test funkcji
"Test funkcji\n"
Efekt dziaania jak wyej.
(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"
Przykad wczenia specyfikatora formatu liczby rzeczywistej w acuch tekstu. Poniewa nie
podano pola precyzja, zostan przyjte biece ustawienia.

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

676

Tabela 15.4. Przykady wywoania 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"
Jeeli nie podano specyfikatora formatu, minimalna wielko pola szeroko jest rwna sumie
liczby pl czci cakowitej, pola kropki oraz liczby pl czci dziesitnej.
(printf '("Cena wynosi %10.2f nowych zlotych.\n" cena))
Cena wynosi
130.25 nowych zlotych.
"Cena wynosi
130.25 nowych zlotych.\n"
W przykadzie tym rezerwujemy 10 pl na zmienn rzeczywist. Poniewa zmienna po
przeformatowaniu zajmuje 6 pl, dodatkowe 4 spacje zostan wstawione przed zmienn
zgodnie z podanym sposobem wyrwnania.
(printf '("Cena wynosi %010.2f nowych zlotych.\n" cena))
Cena wynosi 0000130.25 nowych zlotych.
"Cena wynosi 0000130.25 nowych zlotych.\n"
Jak wyej, z daniem wypenienia pustych pl 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"
Przykad wyrwnania 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 wyej, z dodatkowym odsuniciem kolumn. Do odsunicia kolumn zalecam uycie 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 wsprzdnych punktu z wyrwnaniem 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"
Przykad rozmieszczenia w wierszu 3 liczb rzeczywistych. Dla wikszej widocznoci rozmiaru
pl s one oddzielone od siebie znakiem "|".

677

BvupMJTQ!!qsbluzd{oz!lvst

Tabela 15.4. Przykady wywoania 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 cakowitych. Dodatkowo pomidzy zmienne x2 i x3 wstawiono 3 spacje,
a pomidzy zmienne x3 i x4 wstawiono 1 spacj.
(printf '("%8.4f" 10))
Error: real value expected.
Bd typu wartoci podlegajcej formatowaniu oczekiwano na liczb rzeczywist.
(printf '("%i" 10.0))
Error: integer value expected.
Bd typu wartoci podlegajcej formatowaniu oczekiwano na liczb cakowit.

Poniej pokazano sposb 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
(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
;----------

678

679

BvupMJTQ!!qsbluzd{oz!lvst
(princ "\nZapis wezlow.
")
(fprintf '("NODES\n") file_id)
(fprintf
'("NODE.NUMBER
X

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 bdzie nastpujce:


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.
Zapis wezlow.
Zapis elementow.

Zapisano.
Zapisano.
Zapisano.

Nacisnij ENTER...
Command:

Zawarto pliku $FILE_05.DAT bdzie nastpujca:


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 zauwaye, wykonanie programu jest analogiczne jak programu PROG_115, utworzony zbir danych jest za taki sam jak plik $FILE_03.DAT.
Algorytm do zapisu wzw i elementw jest te bardzo podobny. Po wybraniu odpowiednich danych dla wza lub elementu wykorzystujemy funkcj fprintf do
utworzenia acucha danych i jego zapisu w pliku. acuch sterujcy funkcji printf
zawiera odpowiednie specyfikatory formatu oddzielone tak liczb spacji, aby plik
danych mia przejrzyst i czyteln struktur.

26/5/6/!Qps.xobojf!{bqjtv!
26/5/6/!Qps.xobojf!{bqjtv!ep!qmjlv
xobojf!{bqjtv!ep!qmjlv
qs{zl1bepxzd
qs{zl1bepxzdi!mjojj!{!xzlp
zl1bepxzdi!mjojj!{!xzlps{ztubojfn
i!mjojj!{!xzlps{ztubojfn
gvoldkj!QSJOD-!QSJO2-!
gvoldkj!QSJOD-!QSJO2-!XSJUF.MJ
OD-!QSJO2-!XSJUF.MJOF!psb{
XSJUF.MJOF!psb{
QSJOUG
QSJOUG
Poniszy program zapisuje do pliku te same linie danych wykorzystujc cztery rne
funkcje. Wydruk pliku wynikowego pozwoli nam oceni sposb zapisu informacji
przez kad z funkcji jak rwnie 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
;
;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
;

684

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
;---------(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)

686

687

BvupMJTQ!!qsbluzd{oz!lvst
(princ "\nZakonczenie zapisu danych.")
(CZEKAJ)
(graphscr)
(close file_id)
);progn
);if
(princ)
;
;=================================================
;*************************************************KONIEC

Wykonanie programu bdzie nastpujce:


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"))
Rozpoczcie 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 bdzie nastpujca:


==============================
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")
==============================

Podsumowujc, moliwoci poszczeglnych funkcji s nastpujce:

QSJOD
QSJOD
Princ wywietla dowolne wyraenie (niekoniecznie acuch alfanumeryczny) w linii komend, zwraca podane wyraenie i opcjonalnie moe wysya dane do pliku dyskowego.
Princ wykonuje kody sterujce, np.:
Command: (princ "test1\ntest2")

test1
test2 "test1\ntest2"
Command:

Princ nie umieszcza automatycznie na kocu wyraenia kodu przejcia do nowej linii.
Aby zapisa zagniedone dane typu acuchowego naley je poprzedzi znakiem "\".

QSJO2
Prin1 wywietla dowolne wyraenie (niekoniecznie acuch alfanumeryczny) w linii komend, zwraca podane wyraenie i opcjonalnie moe wysya dane do pliku dyskowego.
Prin1 nie wykonuje kodw sterujcych, np:
Command: (prin1 "test1\ntest2")

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

Prin1 nie umieszcza automatycznie na kocu wyraenia kodu przejcia do nowej linii.
acuchy tekstowe w listach s wywietlane w cudzysowach.

689

BvupMJTQ!!qsbluzd{oz!lvst

XSJUF.MJOF
XSJUF.MJOF
Write-line suy do wywietlenia w linii komend lub zapisania w pliku tylko zmiennej acuchowej. W przypadku danej innego typu (np. listy) wypisywany jest komunikat o bdzie.
Write-line wykonuje kody sterujce, np.:
Command: (write-line "test1\ntest2")

test1
test2
"test1\ntest2"
Command:

Write-line umieszcza automatycznie na kocu wyraenia kod przejcia do nowej linii.


Aby zapisa zagniedone dane typu acuchowego naley je poprzedzi znakiem "\".

GQSJOUG
Fprinf suy do formatowanego wywietlania w linii komend lub zapisania w pliku
danych typu acuchowego, cakowitego lub rzeczywistego. W przypadku list mog to
by wycznie listy reprezentujce punkty.
Fprintf wykonuje kody sterujce, np.:
Command: (fprintf '("test1\ntest2") file_id)

test1
test2 "test1\ntest2"
Command:

Fprintf nie umieszcza automatycznie na kocu wyraenia kodu przejcia do nowej


linii. Aby zapisa zagniedone dane typu acuchowego naley je poprzedzi znakiem
"\".

26/5/7/![bqjt!ebozd
26/5/7/![bqjt!ebozdi!x!qptubdj!
qjt!ebozdi!x!qptubdj!sflpse.x
i!x!qptubdj!sflpse.x
Przedstawione do tej pory przykady zapisu danych do pliku bazoway na zaoeniu, e
wewntrz danej nie wystpuj spacje. Podczas zapisu danych do pliku moemy je
dodatkowo ustawi w kolumnach (dla zapewnienia lepszej czytelnoci pliku). Nie
zmienia to jednak faktu, e podczas odczytu danych z pliku poszczeglne linie rozbijamy
na podacuchy, gdzie kocem podacucha jest miejsce wystpienia pierwszej spacji.
Przykadowo, linia danych
"

34000

11

25"

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

68:

zostanie rozbita na podacuchy


"1" "2" "34000" "1" "11" "25"

W wikszoci typowych zastosowa taki sposb interpretowania danych w pliku jest


wystarczajcy. Przypumy jednak, e chcemy zapisa w pliku dane z tabliczki rysunku
zoeniowego uchwytu frezarskiego.
Pod pozycj Nazwa czci mog by umieszczone midzy innymi:
Podstawa
Tulejka
Klocek
Pokrywka
Waek mimorodowy
ruba z bem z gniazdem M6x25
Koek stokowy 5x35
Koek oporowy 10x6
Wkrt M6x8
Rkoje B80
Jak wida, podczas odczytu tak zapisanych danych nie moemy stosowa zasady
podziau na podacuchy zakoczone spacj, gdy np. linia
"Koek oporowy 10x6"

zostanie rozbita na podacuchy


"Koek" "oporowy" "10x6"

co nie jest tym, czego oczekiwalimy. Oczywicie, gdy kada nazwa czci zajmuje
osobn lini i nie ma ju w tej linii innych danych (np. numeru rysunku, numeru normy,
materiau czci itp.), nie musimy rozbija linii na podacuchy (caa linia stanowi
wwczas jedn dan). Najczciej jednak w jednej linii umieszczamy wszystkie dane
opisujce jedn cz na rysunku. W takim wypadku przy zapisie i odczycie danych
musimy si posuy zapisem rekordowym (jest to zapis stosowany w bazach danych).
Rekord jest to linia danych, podzielona na poszczeglne pola, z ktrych kade zajmuje
w rekordzie cile okrelon pozycj. Poszczeglne pola oddzielone s od siebie jedn
spacj. Liczba znakw w polu musi by na tyle dua, aby pomieci najduszy
acuch. Typ pola (numeryczne lub znakowe) wskazuje na sposb wyrwnania danych
w polu. Dane acuchowe wyrwnywane s do lewej, dane numeryczne wyrwnywane
s za do prawej.
Aby pokaza, jak wyglda zapis w postaci rekordw, posuymy si wybranymi
rekordami z bazy danych zawartej w pliku INVENTRY.DBF. Plik ten jest czci
pakietu AutoCAD i znajduje si na doczonej dyskietce.
W poniszej tabeli podano charakterystyk pl tworzcych jeden rekord.

691

BvupMJTQ!!qsbluzd{oz!lvst

Tabela 15.5. Charakterystyka pl tworzcych jeden rekord w pliku INVENTRY.DBF


Name

Type

Length

Decimals

Justification

Fields

INV_ID

Numeric

12

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

right

133 144

PRICE

Numeric

10

right

146 155

ROOM

Character

left

157 161

EMP_ID

Numeric

12

right

163 174

Poszczeglne kolumny tabeli oznaczaj: nazw pola (name), typ pola numeryczne
lub znakowe (type), dugo pola w znakach dla pl numerycznych wlicza si
dodatkowo kropk oraz miejsca dziesitne (length), liczb miejsc dziesitnych
(decimals), sposb wyrwnania pola lewostronne lub prawostronne (justification)
oraz pooenie pola w rekordzie pozycja pocztkowa i kocowa (fields). Poszczeglne pola w rekordzie oddzielone s od siebie jedn spacj.
W poniszej tabeli zestawiono dane wybranych rekordw bazy danych zawartej w pliku
INVENTRY.DBF. Nagwek tabeli zawiera nazwy pl w rekordzie, poszczeglne
wiersze zawieraj zawartoci rekordw.
Tabela 15.6. Wybrane rekordy z pliku INVENTRY.DBF
INV TYPE
_ID

DESCRIPT MFR

MODEL

COMP PRICE ROOM EMP


_CFG
_ID

FURNITURE

6x3 couch

couches
are us

lounge cat

800.00

101

1000

FURNITURE

adjustable
chair

chairs R
us

comp pro

200.00

101

1000

FURNITURE

two piece
desk

office
master

desk3

400.00

101

1000

FURNITURE

one piece
desk

office
master

desk4

200.00

109

1006

FURNITURE

42x18 file
cabinet

office
master

fc42x18d

40.00

101

1000

FURNITURE

36x48 file flat office


master

ff36x48d

60.00

122

1010

FURNITURE

36x12 file
cabinet

office
master

fc36x12d

30.00

101

1000

HARDWARE personal
inventry

hardwire
hardware

cpu1

1300.00

101

1000

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 TYPE
_ID

DESCRIPT MFR

MODEL

COMP PRICE
_CFG

ROOM EMP
_ID

10

FURNITURE

6 foot table

office
master

2x6tb

33.00

121

1000

11

FURNITURE

3 foot filing
case

office
master

fc3

60.00

111

1000

12

FURNITURE

8 foot table

office
master

2x8tb

40.00

128

1000

Poniszy program pokazuje sposb zapisu pliku danych w postaci rekordw kada
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
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
;
;=================================================

694

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 zawierajcego 12


rekordw, z ktrych kady umieszczony jest w osobnym wierszu.
Omwmy teraz wyrnione linie i bloki programu.
 Wchodzimy w ptl repeat i rozpoczynamy przetwarzanie listy glob_lista_1,
zawierajcej dane tworzce poszczeglne rekordy. Lista zawiera dane typu
acuchowego i numerycznego zgodne z typem pl w rekordzie.
 W bloku tym pobieramy dane tworzce jeden rekord i podstawiamy je pod
zmienne, ktrych nazwy pokrywaj si z nazwami pl w rekordzie.
Pole TYPE zostao 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 acuchowe, formatujemy


dugoci acuchw oraz wyrwnujemy zawartoci pl do lewej lub do prawej.
 W bloku tym, uywajc funkcji strcat, czymy poszczeglne pola w rekord
pamitajc o tym, e pola oddzielone s od siebie jedn spacj.
 Zapisujemy utworzony rekord do pliku.

Jeli chcemy odczyta dane z pliku, mamy do dyspozycji nastpujce funkcje: readchar, read-line lub SSCANF. Poniej przedstawiono przykady zastosowa poszczeglnych funkcji. Wszystkie programy korzystaj ze zbiorw danych przygotowanych
wczeniej przez funkcje do zapisu danych w pliku (pliki $FILE_01.DAT
$FILE_08.DAT).

26/6/2/!Ped{zu!ebozdi!qpk
6/6/2/!Ped{zu!ebozdi!qpkfezod{p!{ob
bozdi!qpkfezod{p!{obl!qp
fezod{p!{obl!qp
{oblv
W celu odczytania danych z pliku pojedynczo znak po znaku posugujemy si funkcj
read-char o skadni:
(read-char [file-desc])

Funkcja odczytuje jeden znak z wejciowego 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 koca pliku funkcja
zwraca nil.
Poniszy program pokazuje wykorzystanie funkcji read-char oraz write-char do
wywietlenia na ekranie tekstowym zawartoci 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 skada si z funkcji gwnej WYSWIETL_PLIK_1, wywietlajcej zawarto


podanego pliku oraz funkcji testujcej C:TEST, zadaniem ktrej jest pobranie nazwy
pliku do wywietlenia oraz przekazanie jej funkcji gwnej.
Omwmy teraz wyrnione linie i bloki funkcji WYSWIETL_PLIK_1.
 Otwieramy do odczytu plik podany w argumencie wywoania funkcji.
 Ten blok instrukcji wykonywany jest wwczas, gdy plik zosta otwarty do
odczytu.
 W bloku tym wchodzimy w ptl while i rozpoczynamy przetwarzanie pliku
znak po znaku. Ptl while wykonujemy tak dugo, a funkcja read-char nie
zwrci znacznika koca pliku (nil). Warto zwrotn funkcji read-char podstawiamy pod zmienn znak.
 Wypisujemy odczytany znak na ekranie tekstowym.

26/6/3/!Ped{zu!e
26/6/3/!Ped{zu!ebozdi!1b2dvdib
3/!Ped{zu!ebozdi!1b2dvdibnj
bozdi!1b2dvdibnj
W celu odczytania danych z pliku wierszami posugujemy si funkcj read-line o
skadni:
(read-line [file-desc])

Funkcja odczytuje acuch alfanumeryczny z wejciowego bufora klawiatury lub z otwartego pliku wskazywanego przez deskryptor file-desc. Funkcja zwraca odczytany acuch.
W przypadku odczytu z pliku po napotkaniu znacznika koca pliku funkcja zwraca nil.
Poniszy program pokazuje wykorzystanie funkcji read-line oraz write-line do wywietlenia na ekranie tekstowym zawartoci 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

Dziaanie funkcji WYSWIETL_PLIK_2 jest analogiczne do funkcji WYSWIETL


_PLIK_1 funkcj read-char zastpiono przez read-line, za funkcj write-char
zastpia funkcja write-line.
Moesz wyprbowa dziaanie funkcji na ktrym ze zbiorw danych $FILE_01.DAT
$FILE_08.DAT, wywietli plik z programem w AutoLISPIE czy te dowolny inny
plik tekstowy.

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

69:

Program, ktry przedstawi poniej, pokazuje wykorzystanie funkcji read-line, funkcji


operujcych na acuchach, listach oraz listach DXF elementw. Program pokazuje
sposb wczytania zbioru danych dla MES celem jego dalszej obrbki (tworzenie
nowych wzw siatki, nowych elementw, kasowanie czci siatki MES itp.). Efektem
wczytania zbioru danych jest narysowanie siatki MES konstrukcji oraz utworzenie
globalnych list wzw i elementw. Przedstawiony poniej program jest najduszym
programem w tej ksice, mona niejako powiedzie, e stanowi jej podsumowanie.
Przedstawiam go jednak wiadomie, gdy wiem z wasnego dowiadczenia, jak trudno
jest przej od prostych przykadw do realizacji zada, z ktrymi spotkasz si
w Swojej codziennej pracy zawodowej. Nie przejmuj si, jeeli nie zrozumiesz programu od razu lub nie bdziesz widzia celowoci zastosowania w nim niektrych
funkcji. Przedstawiony program jest tylko fragmentem (5%) aplikacji sucej do tworzenia 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
(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:2

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
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:8

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
(+ (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))

6::

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
(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)

712

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
;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)
;----------

714

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
;---------;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)

716

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 bdzie nastpujce:


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
odnonie elementu o najwikszym numerze
Typ Elementu = 34000

Grupa = 3

Material = 3

natomiast ekran graficzny zawiera nastpujcy rysunek siatki:

Program zawiera nastpujce funkcje:

GPS
Definicja ptli FOR w AutoLISPie.

SZTVOFL`QSPUPU
SZTVOFL`QSPUPUZQPXZ
FL`QSPUPUZQPXZ
Ustawienia pocztkowe rodowiska pracy programu.

[NJFOOF`HMPCBMOF
NJFOOF`HMPCBMOF
Ustawienie zmiennych globalnych, rejestracja aplikacji.

PECJFS[`[CJPS`EBOZDI
ECJFS[`[CJPS`EBOZDI
Funkcja gwna odbioru zbioru danych.

D[ZUBK`[CJ
D[ZUBK`[CJPS`EBO
UBK`[CJPS`EBOZDI
PS`EBOZDI
Czytanie zbioru danych. Wywoanie funkcji czytajcych wzy i elementy.

719

BvupMJTQ!!qsbluzd{oz!lvst

D[ZUBK`NPEVM`
D[ZUBK`NPEVM`OPEFT
K`NPEVM`OPEFT
Czytanie moduu wzw. Utworzenie listy wzw.

D[ZUBK`NPEVM`FMFNF
[ZUBK`NPEVM`FMFNFOUT
PEVM`FMFNFOUT
Czytanie moduu elementw. Utworzenie listy elementw.

PCT[BS`NPE
PCT[BS`NPEFMV
BS`NPEFMV
Ustalenie takich granic rysunku, aby bya widoczna caa konstrukcja.

NJO`NBY`OPE
NJO`NBY`OPEFT
BY`OPEFT
Znalezienie dwch skrajnych wzw, w obrbie ktrych mieci si caa konstrukcja.

HSBOJDF
HSBOJDF
Funkcja pomocnicza przy powikszeniach/pomniejszeniach.

PECJFS[`XF[MZ
PECJFS[`XF[MZ
Odbir wzw narysowanie i opisanie wzw, dodanie danych dodatkowych do
wza, uzupenienie listy wzw.

PECJFS[`FMFNFOUZ
PECJFS[`FMFNFOUZ
Odbir elementw narysowanie i opisanie elementw, dodanie danych dodatkowych
dla elementu, uzupenienie listy elementw.

VTUBX`NPEFNB
VTUBX`NPEFNBDSP
NPEFNBDSP
Ustawienie zmiennej MODEMACRO.

PECJFS[`FMFNFOU`
PECJFS[`FMFNFOU`3X
[`FMFNFOU`3X
Odebranie elementu 2-wzowego.

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

71:

PECJFS[`FMFNFO
PECJFS[`FMFNFOU`4X
FS[`FMFNFOU`4X
Odebranie elementu 3-wzowego.

PECJFS[`FMFNF
PECJFS[`FMFNFOU`5X
CJFS[`FMFNFOU`5X
Odebranie elementu 4-wzowego.

EPQJT[`OVNFS`FMFNFOU
PQJT[`OVNFS`FMFNFOUV
NFS`FMFNFOUV
Funkcja dopisuje numer utworzonego elementu do listy wzw dla podanego wza.

D;UFTU
Funkcja testujca odbir zbioru danych $FILE_08.DAT.
Poniej omwiono poszczeglne funkcje programu:

SZTVOFL`QSPUPUZQP
ZTVOFL`QSPUPUZQPXZ
QSPUPUZQPXZ
Funkcja ustawia rodowisko pracy programu: wycza echo komend i znaczniki
punktw, wcza identyfikatory elementw, tworzy warstwy i przyporzdkowuje im
kolory oraz ustala wygld punktu na rysunku.

[NJFOOF`HMPC
[NJFOOF`HMPCBMOF
OOF`HMPCBMOF
Funkcja ustawia wartoci nastpujcych zmiennych globalnych:
glob_lista_wezlow
glob_lista_elementow
glob_punkt_ld, glob_punkt_pg

glob_appname

glob_h_tekstu

lista danych o wzach,


lista danych o elementach,
wsprzdne lewego dolnego i prawego grnego
rogu okna podstawowego, wzgldem ktrego
ustawiana jest pocztkowa wielko tekstu oraz
wielko punktu,
nazwa, pod ktr zarejestrujemy aplikacj jest
to potrzebne, gdy chcemy doda dane dodatkowe
dla wybranych elementw rysunkowej bazy
danych AutoCADa,
wielko tekstu opisujcego numer wza i elementu dla okna obejmujcego ca konstrukcj
w chwili startu programu jest ona rwna wielkoci
tekstu dla okna podstawowego 12x9,

721

BvupMJTQ!!qsbluzd{oz!lvst
glob_h_tekstu_0

glob_delta_tekstu

glob_wielkosc_punktu

glob_wielkosc_punktu_0

glob_typ_elementu
glob_grupa_elementu
glob_material_elementu

wielko tekstu opisujcego numer wza i elementu dla okna podstawowego nie ulega zmianie przez cay czas dziaania programu,
odlego tekstu opisujcego numer wza i elementu w osi X i Y od rodka wza i elementu,
wielko punktu reprezentujcego wze konstrukcji dla okna obejmujcego ca konstrukcj
w chwili startu programu jest ona rwna wielkoci
punktu dla okna podstawowego 12x9,
wielko punktu reprezentujcego wze konstrukcji dla okna podstawowego nie ulega zmianie
przez cay czas dziaania programu,
typ elementu (belka) w momencie startu programu,
grupa elementu w momencie startu programu,
materia elementu w momencie startu programu.

Na samym kocu rejestrujemy aplikacj wykorzystujc funkcj regapp o skadni:


(regapp application)

Funkcja rejestruje nazw aplikacji (programu uytkowego) w aktualnym rysunku AutoCADa. Nazwa programu uytkowego, przekazywana w argumencie application, jest
podstawowym parametrem wykorzystywanym do grupowania, przechowywania, uzyskiwania i modyfikowania zdefiniowanych przez taki program dodatkowych danych elementw.

PECJFS[`[CJPS`E
PECJFS[`[CJPS`EBOZDI
CJFS[`[CJPS`EBOZDI
Funkcja odbiera zbir danych przekazany w argumencie wywoania funkcji
nazwa_zbioru. Po otwarciu pliku danych do odczytu, ustawiamy globalny ukad
wsprzdnych (wsprzdne wzw zapisane w pliku podane s w ukadzie globalnym), po czym wykonujemy funkcje czytajce zbir danych, tworzce listy wzw
i elementw oraz rysujce na ich podstawie siatk MES konstrukcji.

D[ZUBK`[CJ
D[ZUBK`[CJPS`EBO
UBK`[CJPS`EBOZDI
PS`EBOZDI
Funkcja czyta zbir danych i wywouje funkcje odbioru wzw i elementw. Funkcja
dziaa w ptli jeszcze1, ktra wykonywana jest do chwili odczytania linii
"END.OF.DATA" lub do osignicia koca zbioru. Poszczeglne linie pliku
odbieramy za pomoc funkcji read-line i podstawiamy pod zmienn linia. Gdy linia
pliku zawiera acuch "NODES", wywoywana jest funkcja CZYTAJ_MODUL
_NODES, odbierajca modu wzw, po czym nastpuje powrt do ptli while
jeszcze1. Gdy linia pliku zawiera acuch "ELEMENTS", wywoywana jest funkcja
CZYTAJ_MODUL_ELEMENTS, odbierajca modu elementw, po czym nastpuje
powrt do ptli while jeszcze1.

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

722

D[ZUBK`NPEVM`
D[ZUBK`NPEVM`OPEFT
K`NPEVM`OPEFT
Funkcja czyta modu wzw i tworzy na tej podstawie list wzw. Funkcja dziaa
w ptli jeszcze2, ktra wykonywana jest do chwili odczytania linii "C END.OF
.NODES". Jeeli odczytana linia nie jest kocem moduu wzw, sprawdzamy
dodatkowo, czy nie jest to linia komentarza (dua litera C w pierwszej kolumnie, po
ktrej wystpuje co najmniej jedna spacja). Jeli odczytana linia nie jest komentarzem,
rozbijamy j na list acuchw za pomoc funkcji PODZIEL_NA_
PODLANCUCHY. Warto zwrotn funkcji podstawiamy pod zmienn lista1.
Nastpnie sprawdzamy, czy zerowy element listy nie jest nagwkiem moduu wzw
("NODE.NUMBER" lub "NODE"). Jeli nie, oznacza to, e lista zawiera dane
o wle. Pobieramy z niej wwczas dane odnonie numeru wza (numer) oraz jego
wsprzdnych X i Y (wsp_x, wsp_y). Jeli wsprzdna Z wza zostaa podana,
podstawiamy j pod zmienn wsp_z, w przeciwnym wypadku ustawiamy warto
wsprzdnej Z na 0. Nastpnie czymy wsprzdne wza w list wsp_wz, tworzymy
list opis_wzla, zawierajc numer wza oraz jego wsprzdne, oraz doczamy opis
wza do listy glob_lista_wezlow.
Przykadowo, dla linii danych
"

1.0000

1.0000

0.0000"

lista opis_wezla ma posta


(1 (1.0 1.0 0.0))

D[ZUBK`NPEVM`FMFNF
[ZUBK`NPEVM`FMFNFOUT
PEVM`FMFNFOUT
Funkcja czyta modu elementw i tworzy na tej podstawie list elementw. Funkcja
dziaa w ptli jeszcze2, ktra wykonywana jest do chwili odczytania linii "C END
.OF.ELEMENTS". Jeeli odczytana linia nie jest kocem moduu elementw,
sprawdzamy dodatkowo, czy nie jest to linia komentarza (dua litera C w pierwszej
kolumnie, po ktrej wystpuje co najmniej jedna spacja). Jeeli odczytana linia nie jest
komentarzem, rozbijamy j na list acuchw za pomoc funkcji PODZIEL_NA
_PODLANCUCHY. Warto zwrotn funkcji podstawiamy pod zmienn lista1. Nastpnie sprawdzamy, czy zerowy element listy nie jest nagwkiem moduu elementw
("NUMBER"). Jeli nie, oznacza to, e lista zawiera dane o elemencie. Pobieramy
z niej wwczas dane odnonie numeru elementu, jego grupy, typu, materiau oraz
topologii, tworzymy list opisu elementu opis_elementu oraz doczamy opis elementu
do listy glob_lista_elementow.
Przykadowo, dla linii danych
"

34000

lista opis_elementu ma posta


(1 1 34000 1 1 2)

1 2"

723

BvupMJTQ!!qsbluzd{oz!lvst

PCT[BS`NPE
PCT[BS`NPEFMV
BS`NPEFMV
Funkcja ustawia takie granice rysunku, aby by w nich widoczny cay model siatki
MES.

NJO`NBY`OPE
NJO`NBY`OPEFT
BY`OPEFT
Funkcja pomocnicza, wywoywana w funkcji OBSZAR_MODELU, znajdujca wsprzdne dwch punktw (wzw), w obrbie ktrych mieci si caa konstrukcja.
Funkcja zmienia wartoci zmiennych globalnych glob_punkt_ld oraz glob_punkt_pg.
W przypadku, gdy na licie wzw znajduje si tylko jeden wze, umieszczamy go w
rodku okna o wymiarach 12x9.
Jeli konstrukcja zawiera dwa lub wicej wzw, znajdujemy wsprzdne jej dwch
skrajnych punktw (x_min y_min), (x_max y_max), nastpnie znajdujemy dugoci
bokw prostokta, ktrego przeciwlege wierzchoki rozpite s na tych punktach
x_odl, y_odl. Majc obliczone dugoci bokw prostokta, obliczamy odlegoci x_r
i y_r, o jakie powikszymy dugoci obliczonych bokw. W ten sposb wok
konstrukcji powstanie dodatkowy wolny obszar (odpowiada to w przyblieniu komendzie AutoCADa ZOOM 0.9X).
Kolejn czynnoci wykonywan przez funkcj jest skalowanie granic rysunku.
Rozrniamy tutaj dwa przypadki:
wymiar prostokta w osi Y jest mniejszy od wymiaru w osi X skalujemy
przez wspczynnik 0.75 (9 / 12) i dopasowujemy wymiary okna w osi Y,
wymiar prostokta w osi Y jest wikszy lub rwny od wymiaru w osi X
skalujemy przez wspczynnik 1.3333 (12 / 9) i dopasowujemy wymiary okna w
osi X.
Na koniec obliczamy wsprzdne skrajnych brzegw rysunku po przeskalowaniu p1
i p2 oraz ustawiamy wartoci zmiennych globalnych glob_punkt_ld i glob_punkt_pg.

HSBOJDF
HSBOJDF
Funkcja wywoywana jest z dwoma argumentami: p1 i p2, okrelajcymi skrajne brzegi
rysunku, w obrbie ktrych mieci si caa konstrukcja. Funkcja stosowana jest przy
powikszeniach/pomniejszeniach, a jej zadaniem jest zachowanie na ekranie staej
wielkoci punktu reprezentujcego wze, staej wysokoci tekstu opisujcego wzy
i elementy oraz staej odlegoci opisu wza i elementu od rodka wza i rodka elementu. Skalowanie wymiarw przeprowadzamy w stosunku do okna podstawowego
12x9. Funkcja zmienia wartoci 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[`XF[MZ
PECJFS[`XF[MZ
Funkcja odbiera wzy rysuje i opisuje wze, dodaje dane dodatkowe do wza i uzupenia brakujce dane na licie glob_lista_wezlow. Funkcja dziaa w ptli FOR, przegldajc kolejne dane o wzach. Procedura odbioru wza przedstawia si nastpujco:
pobierz dane kolejnego wza z listy glob_lista_wezlow: dane o wle (wezel),
numer wza (glob_numer_wezla) oraz jego wsprzdne (wsp_wz),
narysuj wze na warstwie "WEZLY",
pobierz identyfikator wza (id_wz),
utwrz dane dodatkowe dla wza (dane_dodatkowe), zawierajce numer wza.
Przy tworzeniu danych dodatkowych korzystamy z nazwy aplikacji
umieszczonej w zmiennej globalnej glob_appname,
docz dane dodatkowe do listy DXF opisu wza (nowa_lista_dxf),
dokonaj modyfikacji listy nowa_lista_dxf, opisujcej wze (lista zawiera ju
dane dodatkowe),
opisz nowo powstay wze (wstaw numer wza na warstwie "NUMERY
_WEZLOW"),
pobierz identyfikator opisu wza,
utwrz list opisujc wze, zawierajc wszystkie niezbdne informacje,
wymie opis wza na licie glob_lista_wezlow,
bdc ju poza ptl FOR, a wic po przetworzeniu caej listy wzw, ustaw
warto zmiennej w_max na najwikszy numer wza wystpujcego na licie
glob_lista_wezlow,
ustaw warto zmiennej glob_numer_wezla jako w_max + 1.

PECJFS[`FMFNFOUZ
PECJFS[`FMFNFOUZ
Funkcja odbiera elementy pobiera dane o elemencie i wywouje funkcje odbioru elementu w zalenoci od jego typu (liczby wzw). Funkcja dziaa w ptli FOR, przegldajc
kolejne dane o elementach. Procedura odbioru wza przedstawia si nastpujco:
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 elementu (glob_material_elementu),
w zalenoci od typu elementu (liczby jego wzw), wywoaj odpowiedni
funkcj do odbioru elementu,

725

BvupMJTQ!!qsbluzd{oz!lvst
bdc ju poza ptl FOR, a wic po przetworzeniu caej listy elementw, ustaw
warto zmiennej el_max na najwikszy numer elementu wystpujcego na licie
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,
zwiksz numer elementu o 1.

VTUBX`NPEFNB
VTUBX`NPEFNBDSP
NPEFNBDSP
Funkcja ustawia now warto zmiennej systemowej MODEMACRO. Funkcja
wywoywana jest w nastpujcych przypadkach:
ustalenia nowej biecej grupy elementu,
ustalenia nowego biecego typu elementu,
ustalenia nowego biecego materiau elementu,
odbioru zbioru danych DAT.

PECJFS[`FMFNFOU`
PECJFS[`FMFNFOU`3X
[`FMFNFOU`3X
Funkcja odbiera element 2-wzowy. Jest ona wywoywana z funkcji ODBIERZ
_ELEMENTY (korzysta ze zmiennej lokalnej tej funkcji o nazwie element) i wykonuje
nastpujce czynnoci:
pobiera topologie elementu numery wzw w1 i w2,
pobiera dane o wzach z listy glob_lista_wezlow i dokonuje transformacji ich
wsprzdnych do ukadu lokalnego,
rysuje element jako lini na warstwie "ELEMENTY",
pobiera identyfikator elementu,
tworzy list danych dodatkowych dla elementu numer elementu,
docza dane dodatkowe do listy opisujcej element,
modyfikuje list opisujc element (lista zawiera ju dane dodatkowe),
oblicza wsprzdne rodka cikoci elementu,
opisuje element na rysunku (numer elementu na warstwie
"NUMERY_ELEMENTOW"),
pobiera identyfikator opisu elementu,
tworzy list opisujc element,

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

726

wymienia opis elementu na licie glob_lista_elementow,


wywouje funkcj DOPISZ_NUMER_ELEMENTU.

PECJFS[`FMFNFO
PECJFS[`FMFNFOU`4X
FS[`FMFNFOU`4X
Funkcja odbiera element 3-wzowy. Z uwagi na dugo pliku przykadowego oraz na
to, e w zbiorze danych wystpuj tylko elementy 2-wzowe, kod funkcji zosta
pominity w przykadzie.

PECJFS[`FMFNF
PECJFS[`FMFNFOU`5X
CJFS[`FMFNFOU`5X
Funkcja odbiera element 4-wzowy. Z uwagi na dugo pliku przykadowego oraz na
to, e w zbiorze danych wystpuj tylko elementy 2-wzowe, kod funkcji zosta
pominity w przykadzie.

EPQJT[`OVNFS`FMFNFOU
PQJT[`OVNFS`FMFNFOUV
NFS`FMFNFOUV
Funkcja dopisuje numer utworzonego elementu do listy glob_lista_wezlow dla zmiennych w1, w2, w3 i w4 (numery wzw), w zalenoci od typu elementu.

D;UFTU
Funkcja testujca, wywoujca poszczeglne funkcje programu.

26/6/4/!Ped{zu!ebozdi!
26/6/4/!Ped{zu!ebozdi!x!qptubdj!mjtu
{zu!ebozdi!x!qptubdj!mjtuz
x!qptubdj!mjtuz
Program PROG_116 pokaza nam sposb zapisu wybranych moduw zbioru danych
programu PAFEC FE (modu sterujcy, dane o wzach i dane o elementach) w postaci
jednej listy. Tak utworzony zbir danych nie moe by bezporednio wczytany przez program obliczeniowy PAFEC, by to jednak przykad na zapis zbioru danych w innej postaci.
Zadaniem programu przedstawionego poniej jest wczytanie tak utworzonego zbioru danych
do jednej listy oraz wyodrbnienie z niej listy wzw i listy elementw. Tak przygotowane
listy s ju gotowe do dalszego przetwarzania (odbir wzw, odbir elementw).
;*************************************************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 powyszego programu bdzie nastpujce.


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:

Omwmy teraz wyrnione linie i bloki programu.


 Wykorzystujc funkcj findfile, szukamy pliku podanego w argumencie wywoania funkcji WCZYTAJ_PLIK.
 Ten blok instrukcji wykonywany jest w przypadku znalezienia pliku.
Wykorzystujc funkcj load, wczytujemy plik, podstawiajc pod zmienn lista
warto zwrotn funkcji load. Jak zapewne wiesz, funkcja load zwraca warto
ostatniego wyraenia w pliku. Poniewa jedynym wyraeniem w pliku $FILE
_04.DAT jest lista poprzedzona znakiem kwotowania, jest ona zwracana bez
ewaluacji przez funkcj load. Nastpnie wykorzystujc funkcj cdr w poczeniu z assoc, tworzymy listy danych o wzach i elementach.
 Ten blok instrukcji jest wykonywany wwczas, gdy funkcja findfile nie znalaza
szukanego pliku.

26/6/5/!Gpsnbupxboz!ped
26/6/5/!Gpsnbupxboz!ped{zu!ebozdi
bupxboz!ped{zu!ebozdi
Interpreter AutoLISPu zawarty w pakiecie AutoCAD posiada tylko dwie funkcje do odczytu
danych z pliku dyskowego: readchar odczytujc jeden znak i zwracajc kod ASCII
odczytanego znaku oraz read-line odczytujc i zwracajc acuch alfanumeryczny.
Uytkownikom AutoLISPu przydaaby si uniwersalna funkcja do obsugi czytania
danych z plikw dyskowych (taka jak funkcja read w jzyku FORTRAN czy fscanf
w jzyku C). Poniej zostanie zaprezentowana trjargumentowa funkcja SSCANF,
zawarta w pliku SCANF1.LLB, realizujca powysze zadanie.
Plik przetwarzany funkcj SSCANF powinien spenia nastpujce warunki:
plik moe mie dowoln struktur moe mie zmienn dugo linii, zawiera
dowolnie zoone listy, pary kropkowe itp.,
linia pliku moe zawiera dane numeryczne, acuchy i listy umieszczone w dowolnej kolejnoci,

729

BvupMJTQ!!qsbluzd{oz!lvst
dane mog by oddzielone od siebie dowoln liczb spacji,
jeli w linii danych ma znajdowa si acuch zagniedony np. "to jest
"acuch" w acuchu" dan tak naley umieci w licie ("to jest
"acuch" w acuchu"),
kada linia tekstu jest traktowana jako jeden acuch tekstowy decyzj, ile
linii tekstu zostanie przekazanych do bufora (argumentu input_string)
podejmuje uytkownik.
Funkcja SSCANF czyta dane ze strumienia wejciowego. Strumie ten naley utworzy
wczeniej otwierajc plik do odczytu funkcj open i czytajc jedn lub wicej linii
funkcj read-line. W przypadku, gdy strumie wejciowy ma zawiera kilka linii
z pliku, naley je poczy w jeden acuch funkcj strcat. Tego typu rozwizanie
posiada nastpujce zalety w porwnaniu z bezporednim odczytem z pliku:
mona bardzo atwo pomin linie, ktrych nie chcemy przetwarza funkcj
SSCANF,
moemy atwo zmienia liczb linii, ktre s jednorazowo adowane do
strumienia jest to szczeglnie wane w przypadku zmiennej liczby linii
tworzcych poszczeglne moduy danych,
funkcja SSCANF moe by rwnie uyta do czytania danych podanych z klawiatury w tym przypadku strumie wejciowy pobieramy wykorzystujc
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
(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

734

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
;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

736

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 gwna SSCANF definiuje nastpujce funkcje pomocnicze:

741

BvupMJTQ!!qsbluzd{oz!lvst

QBVTF`2
Funkcja zatrzymuje realizacj programu do chwili nacinicia klawisza ENTER.

FSSPS`TTDB
FSSPS`TTDBOG
PS`TTDBOG
Funkcja ta zapewnia wewntrzn obsug bdw. Wywoywana jest z jednym argumentem, bdcym acuchem z komunikatem o bdzie. Komunikat ten jest wywietlany w linii komend AutoCADa, po czym wywoywana jest funkcja exit, przerywajca
dziaanie funkcji SSCANF. Kontroli podlegaj nastpujce dane i operacje:
sprawdzenie, czy wszystkie argumenty funkcji SSCANF s acuchami,
sprawdzenie, czy lista nie zaczyna si nawiasem prawym,
sprawdzenie, czy nawias zamykajcy listy jest nawiasem lewym,
sprawdzenie, czy zostay zamknite ostatni acuch lub ostatnia lista,
sprawdzenie typu zmiennej w argumencie format,
sprawdzenie nazwy zmiennej w argumencie format,
sprawdzenie, czy dugo listy typu zmiennych jest rwna dugoci listy nazw
zmiennych.

DIFDL`BSHVN
DIFDL`BSHVNFOU`UZQF
BSHVNFOU`UZQF
Funkcja sprawdza, czy zmienna podana w argumencie argument_name jest odpowiedniego typu (REAL, INT, STR, itp.), ktry podajemy w argumencie argument_type.
W przypadku, gdy zmienna nie spenia wymaga co do typu, pod zmienn podan w argumencie output_message podstawiany jest odpowiedni komunikat o bdzie.

SFBE`MJTQ`EBUB
SFBE`MJTQ`EBUB
Funkcja rozbija acuch podany w argumencie input_string_1 na list acuchw
i podstawia otrzyman list pod nazw zmiennej przekazanej w argumencie output
_list_1. Separatorem podziau acucha na podacuchy jest spacja. Funkcja dodatkowo

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

742

sprawdza, czy w przypadku podacucha reprezentujcego list zgodny jest typ oraz
liczba nawiasw otwierajcych i zamykajcych oraz czy zostay zamknite ostatni
acuch lub ostatnia lista.

DIFDL`BSHVNFOU`
DIFDL`BSHVNFOU`GPSNBU
HVNFOU`GPSNBU
Funkcja rozbija acuch podany w argumencie format na poszczeglne typy zmiennych
i nazwy zmiennych. Typ zmiennej musi rozpoczyna si znakiem %, po ktrym
wystpuje litera d (liczba cakowita), f (liczba rzeczywista), s (acuch) 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 gwna wykonuje nastpujce czynnoci:
uaktywnia wasn obsug bdw ERROR_SSCANF,
sprawdza argumenty wywoania funkcji posugujc si funkcj CHECK
_ARGUMENT_TYPE. W przypadku bdnych argumentw wypisywany jest
zbiorczy komunikat o bdach (zmienna msg_all), po czym dziaanie funkcji
zostaje przerwane,
sprawdza, czy argument format wskazuje na czytanie formatowane czy na
czytanie swobodne,
w przypadku czytania formatowanego:
rozbija argument input_string na poszczeglne dane, wykorzystujc
funkcj READ_LISP_DATA,
rozbija argument format na poszczeglne typy zmiennych i nazwy
zmiennych, wykorzystujc funkcj CHECK_ARGUMENT_FORMAT,
sprawdza, czy lista typw zmiennych i lista nazw zmiennych s tej samej
dugoci. Jeli nie, wypisywany jest komunikat o bdzie po czym dziaanie funkcji zostaje przerwane,
jeli powyszy warunek jest speniony, nastpuje podstawienie pod
odpowiednie zmienne ich wartoci po ich uprzednim przeformatowaniu
na podany typ,
w przypadku czytania swobodnego:
rozbija argument input_string na poszczeglne dane, wykorzystujc
funkcj READ_LISP_DATA,
podstawia list rozbitych argumentw pod zmienn przekazan w argumencie output_list,
powraca do standardowej obsugi bdw.
Poniszy program pokazuje sposb 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
;---------);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")

744

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
(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

746

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 powyszego programu bdzie nastpujce:


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 moesz przejrze globalne listy wzw i elementw


podstawione pod zmienne glob_lista_wezlow i glob_lista_elementow.
Funkcja SSCANF zostaa tutaj zastosowana do odbioru danych z moduu wzy
(NODES) i elementy (ELEMENTS).

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

748

Dla odbioru danych o wzach wywoanie funkcji SSCANF przedstawia si nastpujco:


(SSCANF
linia
"%d %f %f %f &numer &wsp_x &wsp_y &wsp_z"
""
)

gdzie:
linia
%d &numer
%f &wsp_x

%f &wsp_y

%f &wsp_z

linia danych do przetworzenia odczytana z pliku,


numer wza (liczba cakowita) zapisany pod zmienn numer,
wsprzdna X wza (liczba rzeczywista) zapisana pod
zmienn wsp_x,
wsprzdna Y wza (liczba rzeczywista) zapisana pod
zmienn wsp_y,
wsprzdna Z wza (liczba rzeczywista) zapisana pod
zmienn wsp_z. W przypadku braku w linii danych wsprzdnej Z funkcja SSCANF ustawia warto zmiennej
wsp_z na nil. Jest to sprawdzane w dalszej czci funkcji
CZYTAJ_MODUL_NODES i w takim przypadku zmiennej wsp_z nadawana jest warto 0.0.

Dla odbioru danych o elementach wywoanie funkcji SSCANF przedstawia si


nastpujco:
(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 cakowita) zapisany pod zmienn numer,

%d &grupa

grupa elementu (liczba cakowita) zapisana pod zmienn grupa,

%d &typ

typ elementu (liczba cakowita) zapisany pod zmienn typ,

%d &material

materia elementu (liczba cakowita) zapisany pod zmienn


material,

%d &w1

numer pierwszego wza elementu (liczba cakowita) zapisany


pod zmienn w1,

%d &w2

numer drugiego wza elementu (liczba cakowita) zapisany


pod zmienn w2,

749

BvupMJTQ!!qsbluzd{oz!lvst
%d &w3

numer trzeciego wza elementu (liczba cakowita) zapisany


pod zmienn w3. W przypadku, gdy element jest belk brak
danych dla wza trzeciego funkcja SSCANF ustawia
warto zmiennej w3 na nil,

%d &w4

numer czwartego wza elementu (liczba cakowita) zapisany


pod zmienn w4. W przypadku, gdy element jest belk lub
pyt 3-wzow brak danych dla wza czwartego
funkcja SSCANF ustawia warto zmiennej w4 na nil.

26/6/6/!Ped{zu!ebozdi!x!q
6/6/6/!Ped{zu!ebozdi!x!qptubdj!sflpse
bozdi!x!qptubdj!sflpse.x
ptubdj!sflpse.x
W programie PROG_119 przedstawiem sposb zapisu danych w postaci rekordw
zapis do pliku $FILE_07.DAT. Obecnie, wykorzystujc utworzony plik danych,
dokonamy jego wczytania na globaln list danych, gdzie kady element listy jest
podlist zawierajc 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
;
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)


74:

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
;
;=================================================
;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
;

752

753

BvupMJTQ!!qsbluzd{oz!lvst
;=================================================
(load "prog_061")
(princ "\nProgram zaladowany. ")
(princ "Komenda TEST uruchamia testowanie.")
(princ)
;=================================================
;*************************************************KONIEC

Wykonanie powyszego programu bdzie nastpujce.


Command: (load "prog_125")

Program zaladowany. Komenda TEST uruchamia testowanie.


Command: test

Zawartosc listy rekordow.


(1 .....)
.....
(12 .....)
Command:

Omwmy teraz wyrnione linie i bloki programu.


 Obliczamy dugo listy opisujcej rekord liczb pl w rekordzie. Tym
samym funkcja jest uniwersalna moemy j zastosowa do dowolnego
rekordu danych.
 Wchodzimy w ptl while i rozpoczynamy przetwarzanie poszczeglnych linii
z pliku. Ptl while wykonujemy do chwili osignicia znacznika koca pliku.
 W bloku tym ustawiamy zmienne pocztkowe do przetworzenia kolejnego rekordu.
 Wchodzimy w ptl repeat i rozpoczynamy przetwarzanie kolejnego pola
w rekordzie.
 Pobieramy dane opisujce kolejne pole rekordu.
 W przypadku pola numerycznego, dokonujemy konwersji acucha na liczb
cakowit lub rzeczywist.
 W przypadku pola znakowego, obcinamy puste spacje na pocztku i na kocu
acucha.
 Dodajemy pole do listy opisujcej rekord oraz zwikszamy warto zmiennej
licznik o 1, umoliwiajc tym samym przetworzenie kolejnego pola w rekordzie.
Bdc poza ptl repeat, dodajemy list opisujc cay rekord do listy globalnej
glob_lista_rekordow.

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

754

Jeli istniejcy 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 istniejcego
pliku spowoduje jego utworzenie; jeli za plik ju istnieje, to nowe informacje bd do
niego dopisywane.
Kiedy dodajemy dane na kocu, na nas spada odpowiedzialno za to, aby ju istniejce
dane i wieo wprowadzone byy w tym samym formacie.
Poniszy 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. Zakoczenie wpisywania danych do pliku nastpuje w momencie
podania z klawiatury linii "end" (niezalenie od wielkoci 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 powyszego programu moe by nastpujce.


Command: (load "prog_126")

Program zaladowany. Komenda TEST uruchamia testowanie.


Command: test

Utworzenie pliku $FILE_09.DAT.


Nacisnij ENTER...

Zapis do
Linia do
Linia do
Linia do
Linia do
Otwarcie
Nacisnij

pliku $FILE_09.DAT.
zapisu [END - koniec]
zapisu [END - koniec]
zapisu [END - koniec]
zapisu [END - koniec]
pliku $FILE_09.DAT do
ENTER...

Zapis
Linia
Linia
Linia
Linia
Linia

pliku $FILE_09.DAT.
zapisu [END - koniec]
zapisu [END - koniec]
zapisu [END - koniec]
zapisu [END - koniec]
zapisu [END - koniec]

do
do
do
do
do
do

>: test 1

>: test 2

>: test 3

>: end

dopisywania.

>:
>:
>:
>:
>:

test 4

test 5

test 6

end

Command:

Po powyszym wykonaniu programu zawarto pliku $FILE_09.DAT bdzie nastpujca.


test 1
test 2
test 3
test 4
test 5
test 6

Omwmy teraz wyrnione linie i bloki programu.


 Wchodzimy w ptl while i rozpoczynamy pobieranie linii do zapisu do pliku.
 Wykorzystujc funkcj getstring, pobieramy lini danych do zapisu.
 Sprawdzamy, czy wprowadzono sowo koczce pobieranie danych. Jeli tak,
opuszczamy ptl while oraz zamykamy plik, w przeciwnym wypadku zapisujemy wprowadzon lini do pliku.

757

BvupMJTQ!!qsbluzd{oz!lvst

Potrzeba uywania drukarki nie wymaga komentarza. W instrukcjach wyjcia dla


systemu DOS traktowana jest ona jako plik o wyrnionej nazwie: LPT1 lub PRN.
Poniszy program wykorzystuje okno dialogowe getfiled do wyboru pliku, ktry
nastpnie moe by wywietlony na ekranie lub wydrukowany na drukarce podczonej
do portu LPT1. Na zaczonej dyskietce znajduje si plik $FILE_10.DAT, ktry moesz
wykorzysta do testowania dziaania programu.
Poniewa z poziomu AutoLISPu nie mona sprawdzi stanu drukarki,
zakadam, e w chwili testowania wysyania 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
(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)
;----------

758

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 skada si z dwch gwnych funkcji:

XZTXJFUM`QMJL
XZTXJFUM`QMJL
Funkcja wywietla na ekranie plik podany w argumencie wywoania funkcji nazwa
_pliku. Podany plik zostaje otwarty w trybie do odczytu, na ekranie tekstowym
wywietlona zostaje nazwa wybranego pliku, po czym zostaje wywietlona zawarto
pliku. W przypadku dugich plikw s one dzielone na fragmenty po 24 linie realizacja
programu jest zatrzymywana do chwili nacinicia przez uytkownika klawisza ENTER.

ESVLVK`QMJL
ESVLVK`QMJL
Funkcja drukuje plik podany w argumencie wywoania funkcji nazwa_pliku. Podany
plik zostaje otwarty w trybie do odczytu (file_in), plik reprezentujcy drukark zostaje
natomiast otwarty w trybie do zapisu (file_out). Przesyanie danych na drukark odbywa si w ptli while do czasu osignicia znacznika koca pliku w pliku wejciowym.

Rozdzia ten zapozna Ci z obsug plikw tekstowych w jzyku AutoLISP.


Przedstawione programy pokazay, jak t sam informacj zapisa i odczyta na wiele
rnych sposobw. Umiejtno posugiwania si informacj zapisan w plikach sprawia, e nie musisz si ju posugiwa tylko plikami rysunkowymi AutoCADa. Moesz
wyuskiwa z plikw DWG potrzebne informacje i zapisywa je do pliku tekstowego,
eksportowa do innych programw (np. arkuszy kalkulacyjnych), moesz tworzy
interfejsy pomidzy AutoCADem a programami obliczeniowymi czy graficznymi,
moesz rwnie pisa rozbudowane aplikacje w jzyku AutoLISP lub ADS.

761

BvupMJTQ!!qsbluzd{oz!lvst
Rozdzia ten koczy omawianie podstaw jzyka AutoLISP. Mam nadziej, e po
wnikliwej lekturze tej ksiki, analizie programw znajdujcych si na dyskietce oraz
wasnej inwencji twrczej, doszede do wniosku, e sama znajomo komend
AutoCADa ju Ci nie wystarcza. Wkrocz zatem w fascynujcy wiat jzyka AutoLISP,
aby przekona Siebie samego i Twoich kolegw w pracy, e nauka programowania
AutoCADa jest bardzo opacalna. Niechaj Twoje programy wynagrodz Ci czas
spdzony na lekturze tej ksiki.

You might also like