明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 733|回复: 4

[经验] 哪怕程序出错也强制让它完成到底

[复制链接]
发表于 2021-12-10 11:23 | 显示全部楼层 |阅读模式
昨天编了一个程序急用
主要是对随机图元进行打断、拉伸等随机操作
打断位置、拉伸的向量都是随机计算的
时间关系
很多操作都是用command来完成的
程序编完调试发现
由于缺少对操作对象的判定
程序会时不时出错中断
花了点时间纠错但是没能完成
一怒之下将程序结构改成出错也强制执行到底
现将关键思路放上来
供大家参考

方法其实也很简单
出错函数放到主程序之外
并如下定义
(defun *error*(msg)
(vla-sendcommand *doc* "自定义命令 ")
)
主程序中可能出错的循环
不使用while、mapcar、foreach
而是使用repeat
并将循环次数设定为《总数-当前计数》

模拟代码如下
(defun c:moni()   ;;定义一个外壳程序来调用主程序
(moni_err)    ;;对error的重定义,不要放到主程序里
(c:moni_main)
(moni_no_err)
(princ)
)
(defun c:moni_main()
(if (null curr_w) (setq curr_w 0))  ;;外循环计数
(if (null curr_n) (setq curr_n 0))  ;;内循环计数

(repeat (- tot_w外循环总次数 curr_w)
  (repeat (- tot_n内循环总次数 curr_n)
   (dosomething1)
   (setq curr_n (1+ curr_n))
  )
  (dosomething2)
  
  (setq curr_w (1+ curr_w))
  (setq curr_n 0)
)

;;内外循环完成后计数归0
(setq curr_w 0)
(setq curr_n 0)
(princ)
)
(defun moni_err()
(setq idx_err 0)
(setq moniolderr *error* )

(defun *error*(msg)
  ;;(setq curr_n (1+ curr_n))     ;;如果需要跳过上次出错位置,取消句首屏蔽
  (setq idx_err (1+ idx_err))     ;;出错计数
  (vla-sendcommand *doc* "moni_main ")  ;;出错后用vla-sendcommand强制执行主程序
)
   (defun moni_no_err()
  (setq *error* moniolderr)
  (if (< 0 idx_err) (princ idx_err))   ;;报告出错次数
   )
(princ)
)

评分

参与人数 3明经币 +3 收起 理由
bssurvey + 1 赞一个!
434939575 + 1 很给力!
gaics + 1 学习了

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2021-12-13 09:17 | 显示全部楼层
  1. ;;我的话,会这么弄
  2. (defun c:tt nil
  3.   (setq a (strcat 1 2 3))
  4.   (setq b 1)
  5.   (setq c 2)
  6.   (princ a)
  7.   (prin1)
  8. )

  9. ;;正常的话,运行第一句(setq a (strcat 1 2 3)) ,程序就中断了
  10. ;;b ,c就不会有值

  11. ;;利用vl-catch-all-apply出错也可以运行的原理
  12. ;;程序改造一下

  13. (defun tryexp (x / catch)
  14.   (vl-catch-all-apply
  15.     '(lambda () (setq catch (eval x)))
  16.   )
  17.   catch
  18. )

  19. (defun c:tt nil
  20.   (mapcar 'tryexp
  21.           '(
  22.             (setq a (strcat 1 2 3))
  23.             (setq b 1)
  24.             (setq c 2)
  25.             (princ a)
  26.            )
  27.   )
  28.   (prin1)
  29. )




 楼主| 发表于 2021-12-19 21:13 | 显示全部楼层
本帖最后由 masterlong 于 2021-12-19 21:19 编辑

这个本质上是不一样的
你是在主程序中跳过出错
让程序在错误的情况下不发生“中断”

而我的方法
是在程序发生中断以后
再次调用主程序
让它接着或者跳过出错的位置往下运行

我的方法适用于大量循环的情况
即使是按了ESC试图中断
都能坚挺地继续
除此之外
还可以比较方便的建立出错日志

vl~apply也能做到记录错误
但是要麻烦很多

并不是说我的方法更好
而是要看具体的应用场景
正如首贴中我说的
作为一个临时性的应急程序
确实本身就不那么严谨
也没有时间去优化
每一步都在生成随机数
在随机区域中对随机图元执行随机操作
复制、移动、缩放、旋转、拉伸、打断、延伸
出错的可能太多太多

另外再说一点
vl~apply也不是万能的
最近两天我编程时就遇到一个怪事
代码上看没有一点问题
比如对块执行(vla-get-isxref blkobj)
结果偏偏就是出错
命令行单步执行
提示是“ActiveX 服务器返回错误:未知名称:Isxref”
也就是说“ActiveX 服务器本身出了错”
就因为这里的代码用了vl~apply去监测
返回的永远都是“错误”
导致程序运行结果始终不符合预期
而且怎么也查不出出错根源
debug好久才确定了不是代码的问题
最终只能改变程序流程绕开vla-get-*
这种情况以前也碰到过
但都属于偶发性
出错的原因至今不清楚





发表于 2023-8-30 22:07 | 显示全部楼层
怎么使用呢?这个?
发表于 2023-8-31 17:38 | 显示全部楼层
jh3030912 发表于 2023-8-30 22:07
怎么使用呢?这个?

一般不需要,编程碰上无伤害的出错也无所谓且需要继续的时候才需要
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-5-1 21:10 , Processed in 0.515007 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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