lisp几种数组定义较全
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.首先,定义如下简单的子例程:atob (DEFUN ATOB(A NO / L)
;** e.g. A="A" NO=1 THEN B=A1 ** (SETQ L (ITOA NO))
(SETQ B (STRCAT A L)) (READ B) );END ATOB-DEFUN 有了这个小东西
,接下来的就好办了。 举个例子,有个表list_a ,里面有N个数据,
而且随每次程序执行的不同,N的值不同。 要建立一个数组 A(n),n=1~N
,每个 A(n)等于对应的表中的数据,可以这样实现:
(setq list_no (length list_a)) (setq cur_no 0) (while (< cur_no list_no)
(setq n (+ 1 cur_no)) (set (atob "A" n) (nth cur_no list_a))
(setq cur_no (+ 1 cur_no)) );; end while
需要使用A(n)的时候这样用: (setq the_val (eval(atob "A" n)))
这个时候得到的the_val就是所需要的A(n)值。
2.设一个表为连续的数组存储地址
我设计了如下取二维数组的程序请大家指正!
(a b c d e g g g g g g g g g g g g g g g g)
;;;二维数组的取操作
;;;如有数组m(5,6) 取m(1,4) 输入(drr 5 6 1 4 dl) dl为数组表
(defun drr (b c e f dl / n)
(setq b (* b c))
(setq n (length dl))
(cond ((> n b) (setq e (+ (* (- e 1) c) e))
(nth e dl)
)
((= n b) (setq e (+ (* (- e 1) c) (- f 1)))
(nth e dl)
)
);;;cond
);;;defun
注意:表中数据可以大于数组确定的数据数量,这样我可以假设
任何表为一数组!
5.6 在 AutoLISP 中定义和使用多维数组
“表”是 AutoLISP 中最常用的数据库纪录类型,也是它最善于操作的、特有的数据类型。利用“表的生成和处理”有关函数,可以定义通常概念中的多维数组,可利用“表的查询和检索”的有关函数,可对这个表进行方便快速的数据提取。以下的模拟程序参见Tools.LSP:
(Defun C:DataIO ()
(PrinC "\n三维数组建立...")
(SetQ l nil
x0 (GetInt "\nX 维数: ")
y0 (GetInt "\nY 维数: ")
z0 (GetInt "\nZ 维数: ")
x 1 y 1 z 1 vlx '() vly '() vlz '()
)
(Repeat z0
(Repeat y0
(Repeat x0
(PrinC "\n(") (PrinC z)(PrinC y)(PrinC x)(PrinC ")")
(SetQ vlx (Cons (GetReal " 元素数据: ") vlx)
x (1+ x)
)
)
(SetQ vly (Cons (Reverse vlx) vly)
y (1+ y)
vlx '() x 1
)
)
(SetQ vlz (Cons (Reverse vly) vlz)
z (1+ z)
vly '() y 1
)
)
(SetQ l (Reverse vlz))
(While (Progn (InitGet 7 "Exit Find ")
(SetQ k (GetKWord "\nExit(结束)/
(/= k "Exit")
)
(SetQ x (1- (GetInt (StrCat "\nX维序号(" (IToA x0) "): ")))
y (1- (GetInt (StrCat "\nY维
序号(" (IToA y0) "): ")))
z (1- (GetInt (StrCat "\nZ维序号(" (IToA z0) "): ")))
)
(PrinC (Nth x (Nth y (Nth z l))))
)
(PrinC)
)
C:DataIO用于建立一个三维数组,之后提取和显示该数组中指定的数据。数组保存在变量L之中。
值得注意的是,这样的数组要占用堆区空间,不可以过于巨大,
但是 AutoLISP 数组处理功能是相当强的,
笔者用一台128M内存的PII 333主机,制作了生成一百万个元素的数组(每个元素是三个实数和一个索引组成):
'(1259 123.456 17.377 98706.964)
定义数组,解释运行耗时约20.7秒,编译运行耗时15.9秒。而引用任一元素仅是瞬间的事。
这种数组创建和引用的能力,将能顺利解决解析程序中大规模矩阵运算的基础设施问题,
也是AutoLISP具有特色的功能:简单、快速、容易控制、数据量大。
t 点评
用表类型数据结构组建数组,是一种典型的用法。“表”是 AutoLISP 中一种万能的数据结构容器,
发挥你的想象力,利用表构建专业程序中的各种应用数据结构,
就会体验到 AutoLISP 程序设计独特的优点,甚至在外挂工程数据文件中,也应当使用表结构。
3.类似数组定义
(setq i 3 j 1) ;;这里的i值就相当于VB中数组的下标
(repeat i)
(eval (read (strcat "(setq s" (itoa j) " j)")))
(setq j (+1 j))
)
AutoLISP没有VB中类似数组的定义,这就造成有时在程序中需要对一系列关联数据进行储存处理时比较麻烦,
因为这些关联数据是程序运行的过程中产生的,个数往往是不确定的,可能是三个数据,也可能是五个数
在VB中,你可以通过定义一个数组来解决这个问题,不必考虑数据的个数,只要保证程序运行中产生的数据
数不超过所定义数组的下标就可以了。但在AutoLISP中因为不能定义数组,就比较麻烦。
一个可行的解决办法是将所有数据保存在一个表中,如(A B C ……),然后就可以用nth函数访问表
中的某个元素。但这种方法有个缺点:对表中某个数据的修改比较麻烦。所以更好的办法是把数据以点对的形式保存在一个表中,
例如((1.A) (2.B) (3.C) ……),通过assoc函数就可以对各个数据进行访问,通过subst函数即可实现对表中某个数据的修改。
第二种方法是把所有数据保存在一个文本文件中,可以每个数据一行,通过对文本文件的读取和写入操作也可以实现类似数组的功
但最简单的方法是下面这种:用eval函数和read函数来实现!
一个代码片断例子:
……
(setq i 3 j 1) ;;这里的i值就相当于VB中数组的下标
(repeat i)
(eval (read (strcat "(setq s" (itoa j) " j)")))
(setq j (+1 j))
)
……
执行上面的代码后,会产生3个新的变量:s1=1、s2=2、s3=3,在接下来的程序中,就可以对这三个变量直接调用了。
;; 用 a 置換表 l 中 第 n 个元素(可以是子表);
;|
用法:(EA:SUBST-N '(0 2) '(99 22) '((1 2 3) 2 55 99 66)) 替换第一个子表第三项
((1 2 (99 22)) 2 55 99 66)
(EA:SUBST-N '(2 1) '(99) '(1 2 (55) 99 66)) 替换第二个子表第二项
(1 2 (55 ((99))) 99 66)
(EA:SUBST-N 2.0 '(99) '(1 2 55 99 66)) 替换第二个原子
(1 2 (99) 99 66)
|;
(defun subst-n (n a l)
(cond
((numberp n)
(if (zerop n)
(append (list a) (cdr l))
(cons (car l) (subst-n (1- n) a (cdr l)))
)
)
((listp n)
(cond
((equal (length n) 1)
(if (zerop (car n))
(append (list a) (cdr l))
(cons (car l) (subst-n (1- (car n)) a (cdr l)))
)
)
((> (length n) 1)
(if (zerop (car n))
(cons (subst-n (cdr n) a (car l)) (cdr l))
(cons (car l)
(subst-n (append (list (1- (car n))) (cdr n)) a (cdr l))
)
)
)
)
)
)
)
4.一种数组定义:
(progn
(setq i 0) ;数组下标初始化
(while(< i 10)
(set (read(strcat "NUM[" (rtos i) "]")) (* i i i i))
(princ (strcat "\nNUM[" (rtos i) "]=" (rtos (eval(read(strcat "NUM[" (rtos i) "]"))))))
(setq i (+ 1 i))
)
(princ)
)
(1)数组元素赋值函数seta(alist)返回赋值后的数组表alist。
(defun seta(alist)
(setq alist ′())
(setq a t) ;a为输入控制变量
(while a
(initget ″number angle point″)
(setq str1(getkword ″\nnumber/angle/point/″)) ;选择元素类型
(if(null str1)(setq a nul)) ;结束输入
(if(equal str1) ″number″) ;输入数
(progn
(setq va(getreal ″\ninput a number:″))
(setq alist(cons va alist))
)
)
(if (equal str1 ″angle″) ;输入角
(progn
(setq va(getangle ″\ninput a angle:″))
(setq alist(cons va alist))
)
)
(if(equal strl ″point″) ;输入点
(progn
(setq va(getpoint ″\ninput a point:″))
(setq alist(cons va alist))
)
)
(if(equal str1 ″point″) ;输入点
(progn
(setq va(getpoint ″\ninput a point:″))
(setq alist(cons va alist))
)
)
)
(reverse alist)
)
(2)数组元素输出函数geta(alist i)返回数组alist的第i个元素。
(defun geta(alist i)
(nth (1-i) alist)
)
(3)数组元素修改函数modia(alist i)对数组表alist的第i个元素进行修改,返回修改扣的数组表。
(defun modia(alist i)
(initget ″number
angle point″)
(setq str1(getkword ″\nnumber/angle/point(″)) ;选择元素类型
(if(equal str1 ″number″) ;输入数
(setq va(getreal ″\ninput a number:″))
)
(if(equal str1 ″angle″) ;输入角
(setq va(getangle ″\ninput a angle:″))
)
(if(equal str1 ″point″) ;输入点
(setq va(getpoint ″\ninput a point:″))
)
(setq vlist alist) ;建立临时表vlist
(setq alist ′())
(setq n(length vlist))
(setq ii(-n 1))
(setq j 0)
(while(<=j ii)
(setq vb(nth j vlist))
(if(=(1-j) i)
(setq alist(cons va alist))
(setq alist(cons vb alist)) ;其它元素不变
(setq j(1+j))
)
(reverse alist)
)
(4)添加数组元素函数appenda(alist var)为数组alist添加元素var,返回添加后的数组表。
(defun appenda(alist var)
(initget ″number angle point″)
(setq str1(getkword ″\nnumber/angle/point/″)) ;选择元素类型
(if(equal str1 ″number″) ;输入数
(setq va(getreal ″\ninput a number:″))
)
(if(equal str1 ″angle″) ;输入角
(setq va(getangle ″\ninput a angle:″))
)
(if(equal str1 ″point″) ;输入点
(setq va(getpoint ″\ninput a point:″))
)
(setq alist(reverse alist)) ;将元素顺序颠倒
(setq alist(cons va alist)) ;添加元素
(reverse alist)
)
从上述几个函数可以看出,数组可以包含各种类型的数据如点的x、y坐标值可作为一个元素,同一数组元素的数据类型可以不一致,有的可以是表(点坐标),有的可以是字符,有的可以是数字,数组也不再受维数的限制,同时数组可以有任意多个元素,具有动态数组的功能。因此,用表模拟数组(可称为数组表)时,数组表包含的信息比高级语言中数组包含的信息更丰富,操作也很方便。