===程序员
问题标题: 如何统计汉字的字数? 问题内容: 我想统计: "什么样的问题在 oschina 算是一个好问题?" 这个句子里面以oschina为分割总共有三部分: 什么样的问题在+ oschina +算是一个好问题? 如今想知道oschina前面有几个汉字?oschina有几个英文?oschina后面有几个汉字?不要直接去查找oschina字符串去计算啊,能够看成oschina是某个未知的英文单词,如何统计出来呢? ps.楼下的说个人表达能力有问题,看来我确实没有表达清楚:)再补充一下问题。 问题来源: http://www.oschina.net/question/583303_122530函数
===.net
这个问题的关键是如何让计算机区分汉字和英文, 具体分析就要涉及到中文和英文在计算机内部的表示方式, 那么一切以数字为准, 先把这段数据转换为数字格式, 以下代码:code
(defparameter *字符串* "什么样的问题在 oschina 算是一个好问题?") (defun 字符串-数字(字符串) (dotimes (序数 (length 字符串)) (print (char-code (elt 字符串 序数)))))
执行一下, 结果以下:字符串
CL-USER> (字符串-数字 *字符串*) 20160 20040 26679 30340 38382 39064 22312 32 111 115 99 104 105 110 97 32 31639 26159 19968 20010 22909 38382 39064 65311 NIL CL-USER>
咱们看到, 每个文字字符都被转化为一个数字值, 这个数字值就是计算机内部对这个字符的表示, 也就是说数字值和文字字符之间存在着一种对应关系. 其实到这里问题基本就解决一多半了, 剩下的就是对这些数字值的操做了.get
更简单的语句是:io
(defun 字符串-数字向量 (字符串) (map 'vector #'char-code 字符串))
与前面第一个函数的区别是, 本函数返回的结果是一个向量, 试试看:lambda
CL-USER> (字符串-数字向量 *字符串*) #(20160 20040 26679 30340 38382 39064 22312 32 111 115 99 104 105 110 97 32 31639 26159 19968 20010 22909 38382 39064 65311) CL-USER>
再试试日文:map
CL-USER> (字符串-数字向量 "日本语:平假名にほんご") #(26085 26412 35821 65306 24179 20551 21517 12395 12411 12435 12372) CL-USER>
如今就一目了然了, 这个句子也由适合人类阅读的形式转化为适合计算机阅读的数字形式了, 代码写到这一步, 程序员须要了解的知识就是人类和计算机之间的契约了, 如什么样的数字表明什么样的文字符号等等诸如此类的约定. 咱们通常都知道:程序
0~127 之间的数字表示制表打印控制字符,英文大小写字符以及英文标点符号, 也就是 ASCII 超过127 的数字表示中文字符和全角标点符号等(若是使用其余字符集, 那么就是其余字符, 如日文)
剩下的操做就是对数字的比较,分类等操做了.
这个问题给咱们的启示就是, 首先要把问题的表述形式变化为计算机能理解的数字形式, 而后再去翻找人类和计算机之间已经签定好的契约, 而后按照契约的规定来分析处理.
目前写了两个函数, 简单区分了一下英文(0~127 的数字)和非英文(大于 127 的数字), 以下:
(defun 字数统计函数 (字符串) (let ((汉字个数 0) (空格个数 0) (英文字母个数 0) (全角问号个数 0) (代码点 0)) (dotimes (序数 (length 字符串)) (setq 代码点 (char-code (elt 字符串 序数))) (cond ((= 代码点 32) (setf 空格个数 (1+ 空格个数))) ((= 代码点 65311) (setf 全角问号个数 (1+ 全角问号个数))) ((> 代码点 127) (setf 汉字个数 (1+ 汉字个数))) ((and (> 代码点 0) (<= 代码点 127)) (setf 英文字母个数 (1+ 英文字母个数))))) (values "空格个数:" 空格个数 "全角问号个数:"全角问号个数 "汉字个数:" 汉字个数 "英文字母个数" 英文字母个数))) (defun 字数统计函数-映射版 (字符串) (let ((汉字个数 0) (空格个数 0) (英文字母个数 0) (全角问号个数 0)) (map 'vector #'(lambda (代码点) (cond ((= 代码点 32) (setf 空格个数 (1+ 空格个数))) ((= 代码点 65311) (setf 全角问号个数 (1+ 全角问号个数))) ((> 代码点 127) (setf 汉字个数 (1+ 汉字个数))) ((and (> 代码点 0) (<= 代码点 127)) (setf 英文字母个数 (1+ 英文字母个数))))) (map 'vector #'char-code 字符串)) (values "空格个数:" 空格个数 "全角问号个数:"全角问号个数 "汉字个数:" 汉字个数 "英文字母个数" 英文字母个数)))
执行结果以下:
CL-USER> (字数统计函数 *字符串*) "空格个数:" 2 "全角问号个数:" 1 "汉字个数:" 14 "英文字母个数" 7 CL-USER> (字数统计函数-映射版 *字符串*) "空格个数:" 2 "全角问号个数:" 1 "汉字个数:" 14 "英文字母个数" 7 CL-USER>