fools 发表于 2007-2-7 10:47:06

[LISP函数]:纯LISP写的状态行进度条

显示进度条常用的方法是通过express或doslib,使用上有些局限性.
以下提供一种纯lisp方法供大家讨论:


(DEFUN c:test (/ i)
(GRTEXT -1 "测试进程")
(SETQ i -1)
(REPEAT 10000 (progress (SETQ i (1+ i)) 10000 3))
(GRTEXT)
)

(DEFUN progress        (i n bit / BOX INTEGER NUM REMAINDER)
(SETQ        box (NTH bit
               '(("")
                   ("" "▌")
                   ("" "▎" "▌" "▊")
                   ("" "▏" "▎" "▍" "▌" "▋" "▊" "▉")
                  )
          )
)
(SETQ num (EXPT 2 bit))
(SETQ integer (FIX (/ (* 20 num i) n)))
(SETQ remainder (REM integer num))
(GRTEXT -2
          (STRCAT (SUBSTR "████████████████████"
                          1
                          (* 2 (FIX (/ integer num)))
                  )
                  (NTH remainder box)
          )
)
)


函数解释:
1.progress函数中的bit参数可以理解为状态行显示精度,也就是希望将黑块"█"细化为几份.接受0,1,2,3四个精度值.
2.使用nth的理由见下面的速度测试,毕竟不值得在显示进度条时花费不必要的时间.
3. (GRTEXT -1 "测试进程")语句需独立出来,不得加入进度条函数,否则状态行会频繁闪动,影响显示效果.
4."████████████████████"可根据需要替代为间断的,如"▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊"


(DEFUN Box1 (/ BOX I)
(SETQ i -1)
(REPEAT 8
    (SETQ i (1+ i))
    (SETQ box (NTH i '("" "▏" "▎" "▍" "▌" "▋" "▊" "▉")))
)
)

(DEFUN Box2 (/ BOX I)
(SETQ i -1)
(REPEAT 8
    (SETQ i (1+ i))
    (COND ((= i 0) (SETQ box ""))
          ((= i 1) (SETQ box "▏"))
          ((= i 2) (SETQ box "▎"))
          ((= i 3) (SETQ box "▍"))
          ((= i 4) (SETQ box "▌"))
          ((= i 5) (SETQ box "▋"))
          ((= i 6) (SETQ box "▊"))
          ((= i 7) (SETQ box "▉"))
    )
)
)
(DEFUN Box3 (/ BOX I)
(SETQ i -1)
(REPEAT 8
    (SETQ i (1+ i))
    (SETQ box (STRCAT (CHR 168) (CHR (- 136 i))))
)
)
(DEFUN Box4 (/ BOX BOX0 BOX1 BOX2 BOX3 BOX4 BOX5 BOX6 BOX7 I)
(SETQ Box0 "")
(SETQ Box1 "▏")
(SETQ Box2 "▎")
(SETQ Box3 "▍")
(SETQ Box4 "▌")
(SETQ Box5 "▋")
(SETQ Box6 "▊")
(SETQ Box7 "▉")
(setq i -1)
(REPEAT 8
    (SETQ i (1+ i))
    (setq box (EVAL (READ (STRCAT "Box" (ITOA i)))))
)
)

;;Benchmarking .................Elapsed milliseconds / relative speed for 16384 iteration(s):
;;
;;    (BOX1).....1234 / 1.72 <fastest>
;;    (BOX2).....1469 / 1.45
;;    (BOX3).....1656 / 1.28
;;    (BOX4).....2125 / 1 <slowest>


执行效果:

fools 发表于 2007-2-8 12:53:51

因为频繁调用grtext写状态行影响执行效率,
故再次改进如下,在不影响进度条显示的前提下,减少调用grtext的次数.保留首贴的目的是方便比较两种方式.
执行次数已经改变为100000,但最多调用160次grtext,显示效果不变

(DEFUN c:test (/ i)
(GRTEXT -1 "测试进程")
(SETQ i -1)
(REPEAT 100000 (progress (SETQ i (1+ i)) 100000 3))
(GRTEXT)
)

(DEFUN progress        (i n bit / BOX INTEGER NUM REMAINDER)
(SETQ num (EXPT 2 bit))
(IF (OR (<= n (* num 20))
          (AND (> n (* num 20)) (= (REM i (FIX (/ n num 20))) 1))
      )
   (PROGN (SETQ box (NTH bit
                          '(("")
                          ("" "▌")
                          ("" "▎" "▌" "▊")
                          ("" "▏" "▎" "▍" "▌" "▋" "▊" "▉")
                           )
                     )
           )
           (SETQ integer (FIX (/ (* 20 num i) n)))
           (SETQ remainder (REM integer num))
           (GRTEXT -2
                   (STRCAT (SUBSTR "████████████████████"
                                   1
                                   (* 2 (FIX (/ integer num)))
                           )
                           (NTH remainder box)
                   )
           )
    )
)
)

eobser 发表于 2007-3-7 22:11:47

中间的算法看不大懂,收藏,回去再好好学学。

jx2008 发表于 2007-3-22 00:09:06

最初由 WHGF 发布
显示效果不错,算你很!!!!
收藏

是不是流浪水手阿?

上面的进度条很好,收藏了!

jx2008 发表于 2007-5-16 12:06:00

能否,改进一下,增加百分数显示,且百分数显示的位置固定在进度条的中间。搂主没有联系方式,联系不上!

killer9806 发表于 2007-8-15 18:36:47

进度时间,相当的OK

cjwlyg 发表于 2009-9-2 23:39:11

程序不错

maobangyan 发表于 2009-9-12 18:26:45

看看

shaojingjing 发表于 2010-1-9 23:02:30

不错的东东,代码思维需要慢慢琢磨消化,谢谢LZ.

yjch 发表于 2013-6-12 13:17:12

他山之石可以攻玉,慢慢研究

张和平 发表于 2013-8-14 14:12:53

这个牛逼了。。。

XDnpu349 发表于 2014-3-9 15:58:15

不错。。有对话形式的吗?

拉契 发表于 2014-7-11 15:43:33

挺不错的,就是不知道怎么用、什么情况用!!

kkt123 发表于 2015-2-12 10:08:17

是不是流浪水手阿;P

479274135 发表于 2018-1-31 16:24:08

厉害了    顶顶顶
页: [1] 2
查看完整版本: [LISP函数]:纯LISP写的状态行进度条