;;因为tokens被赋予了3个参数,目的是从一个字符串以不符合某些条件的字符为分隔符,获得分隔符之间的string对象的列表
(defun tokens (str test start)
(let ((p1 (position-if test str :start start))) ;;把p1设置为第一个符合test字符的位置
(if p1
(let ((p2 (position-if #'(lambda (c)
(not (funcall test c))) ;;返回不符合条件的字符的位置
str :start p1)))
(cons (subseq str p1 p2) ;;
(if p2
(tokens str test p2)
nil)))
nil)))
;;字符是graphic小于127的字符,即ascii里面的字符就行。并且不等于空格
(defun constituent (c)
(and (graphic-char-p c)
(not (char= c #\ ))))
注意当你所得到的string对象的列表,如果该string调用parse-integer的话,必须确保里面自由数字和空格
(defun parse-date (str)
(let ((toks (tokens str #'constituent 0)))
(list (parse-integer (first toks))
(parse-month (second toks))
(parse-integer (third toks)))))
(defconstant month-names
#("jan" "feb" "mar" "apr" "may" "jun"
"jul" "aug" "sep" "oct" "nov" "dec"))
(defun parse-month (str)
(let ((p (position str month-names
:test #'string-equal)))
(if p
(+ p 1)
nil)))
(defun read-integer (str)
(if (every #'digit-char-p str) ;;;首先所有的char必须是一个数字形式
(let ((accum 0))
(dotimes (pos (length str))
(setf accum (+ (* accum 10)
(digit-char-p (char str pos)))))
accum)
nil))
CL-USER> (tokens "ar2012 aug 09f" #'constituent 0) ;;意思是以空格或者大于127的字符为分隔符,然后返回这些分隔符之间string的list。
("ar2012" "aug" "09f")
CL-USER> (tokens "rr2010m10n02rr69" #'digit-char-p 0) ;;基本上就是下面的read-integer的相同目的,只是read-integer将会返回一个这些分割出来的string对象连接起来的整数形式
("2010" "10" "02" "69")
CL-USER> (read-integer "rr2010m10n02rr69")
2010100269
CL-USER> (parse-date "2012 aug 03") ;;虽然刚开始的时候是graphic,并且仅仅用空格为分隔符,但是你像第一个第一个或者第3个string段,因为分段后需要进行parse-integer操作,故必须是数字,而中间的字符串要么是month-names 匹配,要么是数值。因为parse-month。
(2012 8 3)
下面一个程序实现提取一个字符串中的整数有多个注意点1:digit-char-p意思是判断Returns true iff char is a digit,别误解为判断是否为char/digit.
2:(char str pos)返回一个字符,当你想用digit-char-p的值时,必须调用一下digit-char-p函数转化字符为相应的整数值。注意字符只能是(0-9).所以说现在digit-char-p共有两个用途
3:digit-char 把数字转化成char形式如9->#\9
4:关于dotimes的返回值,是它的第三个字符,默认为nil.所以你必须在let最后一个表达式为accum,否则let的值将是nil.
5:与上面read-integer的区别就是,上面的方法只限于string中的每个字符都是一个数字形式。
(defun read-integer (str)
(let ((accum 0))
(dotimes (pos (length str))
(if (digit-char-p (char str pos))
(setf accum (+ (* accum 10) (digit-char-p (char str pos))))))
accum))