找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 693|回复: 7

[LISP函数]:子函数产生错误时,如何避免整个程序的退出?

[复制链接]
发表于 2005-1-30 17:36:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
通常情况下,如果子函数执行过程中出现错误,会导致整个程序自动结束。但并不是每种错误都是不能容忍的。我想知道有没有什么办法可以避免主程序因这些特定的错误而退出呢?一般情况下,子函数出错了会返回什么值呢?还是不返回任何值,而直接调用*error*结束程序啊?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
发表于 2005-1-30 23:14:13 | 显示全部楼层
返回cad的出错提示

catch-all-error-p
(if ...)
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1个

财富等级: 恭喜发财

发表于 2005-1-31 17:09:34 | 显示全部楼层
若是系统错误,我想可能没有办法,因为系统出错,它就直接调用错误处理函数了。
但一般函数出错都是调用时变量有问题,这里我们可以加一个容错处理点。
在函数开始处用一个变量判断点,来判断传入的变量是否是你需要的变量类型、值范围等。若是则继续,若变量达不到要求,则跳至函数尾并返回一个值(逻辑假或负值。。。等与函数正常值不一样就行)

  1. ;;;====================================================
  2. (defun setclayer (slist / cname cor ctmp tmp lsty)
  3. ;;出错后帮助提示信息
  4.   (setq        ctmp (strcat "\n(setclayer '(层名 颜色))!"
  5.                      "\n(setclayer "轴线")设置当前图层"
  6.              ) ;_ end of strcat
  7.   ) ;_ end of setq
  8. ;;若变量是表则
  9.   (cond        ((= (type slist) 'LIST)
  10.          (setq cname (car slist)
  11.                cor   (cadr slist)
  12.                lsty (caddr slist)
  13.          ) ;_ end of setq
  14.          (if (not lsty)(setq lsty "CONTINUOUS"))
  15.         )
  16.         ((= (type slist) 'STR)
  17.          (setq cname slist)
  18.         )
  19.   ) ;_ end of cond
  20. ;;若是用问号调用则直接显示帮助
  21.   (cond        ((= slist '?)
  22.          (alert ctmp)
  23.         )
  24.      ;若变量不是表则。
  25.         ((not slist)
  26.          (if clayer_old
  27.            (setvar "clayer" clayer_old)
  28.            (setvar "clayer" "0")
  29.          ) ;_ end of if
  30.         )
  31.         ((and cname cor (= (type cname) 'STR) (= (type cor) 'INT))
  32.          (if (and (tblobjname "LAYER" cname)
  33.                   (setq tmp (entget (tblobjname "LAYER" cname)))
  34.              ) ;_ 结束and
  35.            (progn (setq        tmp (subst (cons 62 cor)
  36.                                    (assoc 62 tmp)

  37.                                    tmp
  38.                             ) ;_ 结束subst
  39.                         tmp (subst (cons 70 0) (assoc 70 tmp) tmp)
  40.                   ) ;_ 结束setq
  41.                   (entmod tmp)
  42.            ) ;_ 结束progn
  43.            (entmake (list
  44.                       '(0 . "LAYER")
  45.                       '(100 . "AcDbSymbolTableRecord")
  46.                       '(100 . "AcDbLayerTableRecord")
  47.                       (cons 6 lsty)
  48.                       (cons 62 cor)
  49.                       '(70 . 0)
  50.                       (cons 2 cname)
  51.                     ) ;_ end of list
  52.            ) ;_ end of entmake

  53.          ) ;_ end of if
  54.          (setq clayer_old (getvar "clayer"))
  55.          (setvar "clayer" cname)
  56.         )
  57.         ((and (= (type cname) 'STR))
  58.          (if (setq tmp (entget (tblobjname "LAYER" cname)))
  59.            (progn (setvar "clayer" cname)
  60.                   (setq        tmp (subst (cons 62 cor)
  61.                                    (assoc 62 tmp)
  62.                                    tmp
  63.                             ) ;_ 结束subst
  64.                         tmp (subst (cons 70 0) (assoc 70 tmp) tmp)
  65.                   ) ;_ 结束setq
  66.                   (entmod tmp)
  67.            ) ;_ 结束progn
  68.            (progn (entmake (list
  69.                              '(0 . "LAYER")
  70.                              '(100 . "AcDbSymbolTableRecord")
  71.                              '(100 . "AcDbLayerTableRecord")
  72.                              (cons 6 lsty)
  73.                              (cons 62 7)
  74.                              '(70 . 0)
  75.                              (cons 2 cname)
  76.                            ) ;_ end of list
  77.                   ) ;_ end of entmake
  78.            ) ;_ end of progn
  79.          ) ;_ end of if
  80.          (setq clayer_old (getvar "clayer"))
  81.          (setvar "clayer" cname)
  82.         )
  83.                      ;;若变量不对,则出现提示
  84.         (T (progn (alert (strcat "\n数据错误:" ctmp))))
  85.   ) ;_ end of cond
  86.   (princ)
  87. ) ;_ end of defun

这上面就使用了若错误使用变量调用时的容错方式,当调用变量不是我所需要的格式时,将出现提示,之后程序继续执行。
上面的程序是我几年前编的,当时是想能让一个函数使用不同的变量格式调用。
且若变量不对的情况可以继续执行,主要用来调试程序时用,当所有程序调试完后,再将其中判断语句注释掉。
后改正过很多BUG,但源码不在这台机子上。呵呵^_^ 
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-2-1 00:13:25 | 显示全部楼层
呵呵,谢谢两位的帮助。其实的想要实现的东西没这么复杂:)。netbee斑竹的代码看起来还有点吃力。
我碰到这个问题实际上确实是因为变量格式所导致。我在用ssget时,没法让程序接受键盘输入的字符,象getpiont之类命令一样,initget之后就允许字符输入,作为改变程序下一步操作的关键字。最后我参考别人的方法,做了一个ssget的结果是否为空值的判断,勉强实现了可选择操作。代码如下:
(IF (NULL (SETQ SS1 (SSGET '((-4 . "<OR") (-4 . "<AND")
                                (0 . "TEXT")
                                (1 . "*x")
                                (-4 . "AND>")
                                (-4 . "<AND")
                                (0 . "TEXT")
                                (1 . "*Y*")
                                (-4 . "AND>")
                                (-4 . "<AND")
                                (0 . "TEXT")
                                (1 . "*X*")
                                (-4 . "AND>")
                                (-4 . "OR>")
                               )
                        )
              )
        )  
      (PROGN
.......
       );PROGN
);IF

但这样的结果我还是不太满意。因为它也只能提供两个可选择方式,要么选中物体,执行第一步,要么不选任何物体,直接回车执行第二选择。万一有第三、第四选择,就比较麻烦了:(

还有一个小问题。我自己定义了*error*函数的部分内容,以便恢复一些系统变量。但由于该*error*子函数被释放到内存中,导致每次别的cad自带命令出错时也调用这个自定义的*error*,进而产生更多的错误(说缺少某些变量值。。那些我自己的程序里定义的变量)。不知道大家一般怎么处理的?怎么样在程序用完以后把*error*恢复原样?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 593个

财富等级: 财运亨通

发表于 2005-2-1 05:46:14 | 显示全部楼层
这个一个写了一半的测试程序,想模拟 CAD 中的“刷子”方式。

  1. (defun c:tt (/ key ss pt pts ptm)
  2.   (if (progn (initget 6 "S All CP W WP L F C B G")
  3.              (setq key (getpoint "\n选择目标实体[设置(S)]: "))
  4.       )
  5.     (progn
  6.       (cond
  7.         ((= key "ALL")
  8.          (setq ss (ssget "all"))
  9.         )
  10.         ((member (strcat key) '("CP" "WP" "F"))
  11.          (setq msg "\n第一栏选点: ")
  12.          (while        (progn (if (and pts (> (length pts) 1) (/= pt "U"))
  13.                          (grdraw (car pts) (cadr pts) -1)
  14.                          (if (and pts ptm)
  15.                            (grdraw (car pts) ptm -1)
  16.                          )
  17.                        )
  18.                        (initget "U")
  19.                        (setq pt        (if pts
  20.                                   (getpoint (car pts) msg)
  21.                                   (getpoint msg)
  22.                                 )
  23.                        )
  24.                 )
  25.            (if (= (type pt) 'LIST)
  26.              (setq pts (cons pt pts))
  27.              (if pts
  28.                (setq ptm (car pts)
  29.                      pts (cdr pts)
  30.                )
  31.              )
  32.            )
  33.            (setq msg "\n指定直线的端点或 [放弃(U)]:")
  34.          )
  35.          (if pts
  36.            (setq ss (ssget key pts))
  37.          )
  38.         )
  39.         (t)
  40.       )
  41.     )
  42.   )
  43.   ss
  44. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-2-1 08:48:48 | 显示全部楼层
先保存旧的错误函数,再将新的错误函数setq给*error*,最后再程序结束之前再恢复原先保存的错误函数:

(setq olderr *error*)
(setq *error* newerr)
.
.
.
(setq *error* olderr)
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 488个

财富等级: 日进斗金

发表于 2005-2-3 23:37:28 | 显示全部楼层
最初由 eachy 发布
[B]这个一个写了一半的测试程序,想模拟 CAD 中的“刷子”方式。
[code]
(defun c:tt (/ key ss pt pts ptm)
  (if (progn (initget 6 "S All CP W WP L F C B G")
             (setq key (getpoint "\n选择目标实体[设置... [/B]


我虽然没写,但也考虑过怎么写:
(ssget ":s")
应该是一句话搞定!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-2-4 08:40:58 | 显示全部楼层
(ssget ":s")很好用,可单选,可框选
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2025-9-27 22:47 , Processed in 0.185394 second(s), 46 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表