明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2845|回复: 11

[源码] [原创.源码]让strlen跟substr支持中文汉字等双字节文字

[复制链接]
发表于 2015-10-8 21:29:56 | 显示全部楼层 |阅读模式
本帖最后由 tryhi 于 2015-10-9 18:59 编辑

大家都知道,由于汉字是双字节字符,所以用strlen跟subst的时候一个汉字当成两个字符计算,有时候我们想要按常规做法(像excel的left公式一样)来处理,这时就容易出错,所以写个子函数来调用






  1. ;;例子(try-substr "数1数456" 2 3) => "1数4"
  2. ;;截取字符串,仿substr,但是支持中文
  3. ;;参数3 nil表示后面全部保留
  4. (defun try-substr(str start len / lst)
  5.     (setq lst ( _Str2List str))
  6.     (setq lst (try-lst-move-head lst (1- start)))
  7.     (if (not len)nil(setq lst (try-lst-read-head lst len)))
  8.     (apply 'strcat lst)
  9. )
  10. ;;例子(try-strlen "数一数123") => 6
  11. ;;返回一个字符串中的字符数量(支持中文)
  12. (defun try-strlen(str / i strx)
  13.     (setq i 0)
  14.     (setq strx(vl-string->list str))
  15.     (if (not(= str ""))
  16.         (while
  17.             (if(<(car strx)129)
  18.                 (setq i (1+ i) strx(cdr strx))
  19.                 (setq i (1+ i) strx(cddr strx))
  20.             )
  21.         )
  22.     )
  23.     i
  24. )

  1. ;;字符串拆分为单一的表(支持单双字节混合)
  2. (defun _Str2List(str / a);注:引用73的函数
  3.   (setq str(vl-string->list str))
  4.   (while
  5.         (if(<(car str)129)
  6.             (setq a(cons(chr(car str))a)str(cdr str))
  7.             (setq a(cons(strcat(chr(car str))(chr(cadr str)))a)str(cddr str))))
  8.   (reverse a)
  9. )

  10. (defun try-lst-move-head (lst i)
  11.   (if (<= i 0)lst
  12.         (repeat i (setq lst (cdr lst))))
  13. )
  14. (defun try-lst-read-head(lst i / lstt)
  15.   (if (<= i 0)lst
  16.         (progn
  17.             (setq lstt '())
  18.             (repeat i
  19.                 (setq lstt (cons (car lst) lstt))
  20.                 (setq lst(cdr lst))
  21.             )
  22.             (reverse lstt)
  23.             
  24.         )
  25.   )
  26. )

本帖子中包含更多资源

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

x

点评

不知道保留双字节字符长度为2这个习惯好些还是计为1更好  发表于 2015-10-9 10:52

评分

参与人数 4明经币 +4 收起 理由
jinan1913 + 1 很给力!
qiuhai1991 + 1
zctao1966 + 1
USER2128 + 1 赞一个!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下

本帖被以下淘专辑推荐:

发表于 2015-10-9 10:43:14 | 显示全部楼层
本帖最后由 llsheng_73 于 2015-10-10 10:22 编辑

  1. (defun Str2lst(a / c)
  2.   (setq a(vl-string->list a))
  3.   (while(if(<(car a)129)
  4.           (setq c(cons(chr(car a))c)a(cdr a))
  5.           (setq c(cons(strcat(chr(car a))(chr(cadr a)))c)a(cddr a))))
  6.   (reverse c))
  7. (defun CharsOfStr(a)(length(Str2lst a)));;字符串中的字符个数,双字节字符与单字节字符均计为一个字符
  8. (defun Substrs(a s l / i)
  9.   (mapcar'set'(l i)(list(if l(+ s l -1)(strlen a))0))
  10.   (apply'strcat(vl-remove-if-not'(lambda(x)(<= s(setq i(1+ i))l))(Str2lst a))))


先前对长度的处理有问题,谢谢各位指出

评分

参与人数 2明经币 +2 收起 理由
jinan1913 + 1 很给力!
tryhi + 1 赞一个!

查看全部评分

回复 支持 1 反对 0

使用道具 举报

发表于 2015-10-9 06:25:24 | 显示全部楼层
感谢 tryhi 分享程序!
发表于 2015-10-9 08:18:54 | 显示全部楼层
感谢 tryhi 分享程序!
发表于 2015-10-9 08:29:07 | 显示全部楼层
不错,赞一个
发表于 2015-10-9 13:40:30 | 显示全部楼层
llsheng_73 发表于 2015-10-9 10:43

Substrs返回的位置和长度都不对
发表于 2015-10-9 14:19:24 | 显示全部楼层
mj0000 发表于 2015-10-9 13:40
Substrs返回的位置和长度都不对

这个和CAD系统的算法有点不一样的是,只要是字符都按一个计算的,不管是否双字节字符。。。。跟楼主的一样,虽然我也觉得这样自成一套有点不太好
发表于 2015-10-9 14:27:40 来自手机 | 显示全部楼层
不要纠结这,alisp一直就是char,计算机先有,宽字符是都要用计算机结果
 楼主| 发表于 2015-10-9 19:25:02 | 显示全部楼层
llsheng_73 发表于 2015-10-9 10:43

代码很简洁
可惜好像有点问题
(Substrs "1234567890" 4 2); => ""
这句返回空值


(try-Substr "1234567890" 4 2);=> "45"
我的返回是的"45
(Substr "1234567890" 4 2);=> "45"
系统函数也是"45"
 楼主| 发表于 2015-10-9 19:28:25 | 显示全部楼层
本帖最后由 tryhi 于 2015-10-9 19:38 编辑
llsheng_73    不知道保留双字节字符长度为2这个习惯好些还是计为1更好




因为我接触过的,不管BAT也好,其他脚本也好,office也好,双字节字符的处理都是按一个处理的,所以就我习惯而言,是没必要保留了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-12-23 20:14 , Processed in 0.184777 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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