string substitution
来源:互联网 发布:蓝可儿死亡 知乎 编辑:程序博客网 时间:2024/06/07 03:02
(defstruct buf vec (start -1) (used -1) (new -1) (end -1))(defun bref (buf n) (svref (buf-vec buf) (mod n (length (buf-vec buf)))));;;扩展setf方法,注意下面调用的方式(defun (setf bref) (val buf n) (setf (svref (buf-vec buf) (mod n (length (buf-vec buf)))) val))(defun new-buf (len) (make-buf :vec (make-array len)))(defun buf-insert (x b) (setf (bref b (incf (buf-end b))) x))(defun buf-pop (b) (prog1 (bref b (incf (buf-start b))) (setf (buf-used b) (buf-start b) (buf-new b) (buf-end b))))(defun buf-next (b) (when (< (buf-used b) (buf-new b)) (bref b (incf (buf-used b)))))(defun buf-reset (b) (setf (buf-used b) (buf-start b) (buf-new b) (buf-end b)));;;都设置成-1,为了实现对buffer的清空(defun buf-clear (b) (setf (buf-start b) -1 (buf-used b) -1 (buf-new b) -1 (buf-end b) -1));;只有一种情况buf-used为-1,说明到文件结束时,刚读入到buffer的字符都匹配,未出现pop逻辑,故-1+1=0,也就是从头开始princ.(defun buf-flush (b str) (do ((i (1+ (buf-used b)) (1+ i))) ((> i (buf-end b))) (princ (bref b i) str)))(setf bref) 它重载了setf方法,为了是mod n 然后得到ring buffer。只有在insert的时候才调用了这个setf方法。n是buf-end +1之后的值,length最后的结果是buffer的长度,是个定值。比方说只剩下第二个b的时候,buf-end = 3. (3+1) mod 4 = 0,所以接下来的a就加入到了第一个位置。
buf-insert 关键就是里面的扩展的setf 方法。
buf-next只有在输入的时候是从buffer里面来的时候才用buf-next。它是先比较当前位置used是否小于buf-new,如果是就把下面那个输出来。所以说第二b仍旧会读出来进行匹配测试,当它执行完以后,然后再call buf-next的话,发现used跟new已经相等了,所以只能是read里面读取数据了。
buf-pop 它是从栈出来,只有执行了princ才会输出到out里面。所以说你看zerop pos首先是princ,然后才是出栈。
buf-flush 是为了解决一种情况:假设pattern为baro,现在文本中最后几个字符为bar。因为整个循环是到文件尾结束,现在bar还在buffer里面就结束了,所以将会显示不出来。其他情况的话buf-flush要不要没影响。
(defun file-subst (old new file1 file2) (with-open-file (in file1 :direction :input) (with-open-file (out file2 :direction :output :if-exists :supersede) (stream-subst old new in out))))(defun stream-subst (old new in out) (let* ((pos 0) (len (length old)) (buf (new-buf len)) ;buffer的长度跟pattern串长度一样, (from-buf nil)) (do ((c (read-char in nil :eof) ;初始时读取一个字符 (or (setf from-buf (buf-next buf)) ;因为有短路现象,要么从buffer中读取,要不从流中。 (read-char in nil :eof)))) ((eql c :eof)) ;循环结束条件是碰到了结尾 (cond ((char= c (char old pos)) ;如果读入的字符等于old中的一个字符 (incf pos) ;pos+1,因为凡是匹配成功的话,pattern中的指标就要加+指到下一位 ;;内部cond判断两次 (cond ((= pos len) ; 3 因为上面pos已经加1了,所以说只需相等就行了。 (princ new out) ;把它输出来 (setf pos 0) ;pos 变为0 (buf-clear buf)) ;buffer 清空 ((not from-buf) ; 2 (buf-insert c buf)))) ((zerop pos) ; 1 (princ c out) (when from-buf (buf-pop buf) (buf-reset buf))) (t ; 4 (unless from-buf (buf-insert c buf)) (princ (buf-pop buf) out) (buf-reset buf) (setf pos 0)))) (buf-flush buf out)))start : 当我们pop一个元素,他就会增加,增加buf-stard。
end :当我们插入一个元素的时候他会增加,先增加buf-end,然后再往这个buf-end里面添加值。
used : 当我们pop完一个元素,然后就会调用bufnext,他会在里面累加。
new : 当试着匹配buffer里面的字符时,开始调用used/new,一旦buffer中匹配开始,new就会绑定到end,因为end就相当于是buffer里面最后一个元素,然后调用buf-next,进行迭代匹配,直到used=new。也就是说一旦检测buffer的话,会把buffer里面所有的都试着匹配一遍,然后才会开始接受从read中读取。
1:ring buffer空间只要跟pattern一样就行。
2:短路现象中,在b-a-r的过程中因为虽然这个时候buf-used< buf-new当时取到的值为nil,所以仍旧是从流中读取
from-buf意思就是从buf里面读取数据成功。
3:什么时候第一次给used/new赋值的呢?也就是在第一次pop的时候进行reset的时候才会给used/new进行赋值。就像图5,因为前面的时候used/new都是-1,所以也都是按流读入的。
Case1:zerop pos 首先表示的是一个新的匹配,并且前面没有字符匹配成功的话,就把他输出来。如u/s直接输出来了。都没有到buffer里面还有一种情况就是这个字符已经在buffer里面了,但是前面没有字符匹配成功,他就需要从buffer中出来,并且重新设置pos为0(指向pattern的第一个位置)
Case2:当匹配开始,也就是说前面有字符匹配已经匹配上了。当读入的字符不是来自于buffer(from-buf 为假),就将字符输入到buffer里面。pos 指定到old string上面。当字符与在pattern string的pos +1值一样时,说明整个串匹配成功。
Case3:pos + 1 跟new string的长度一样,并且匹配在这个位置的元素匹配成功,就输出一个新的string。重新把pattern匹配的起始位置设置为0,因为你已经匹配成功了,下一个再进行匹配的话,只能是从头开始。把buffer里面的东西请空。 因为先处理完buffer里面的东西,才会继续从读入新的值。比如当你匹配a弹出的时候,他会再(setf from-buf (buf-next buf))
Case4:匹配到中途在这个位置不匹配了。pop第一个字符出栈,然后reset,并且设置pos从pattern头开始重新匹配。因为你输入的时候就是两种情况输入的,一个是读进去,一个是from-buf.所以在你处理的时候也同样是两种情况处理。
首先按照匹配是否成功,然后再按照是否来自于文件输入或者是buffer部分读取。
CL-USER> (char "string" 1)#\tCL-USER> (new-buf 6)#S(BUF :VEC #(0 0 0 0 0 0) :START -1 :USED -1 :NEW -1 :END -1)CL-USER> (length (buf-vec (new-buf 6)))6CL-USER> (file-subst " th" "z" "d:/emacs/string.txt" "d:/emacs/stringold.txt")NIL
- string substitution
- String substitution in scripts
- ruby String substitution
- Ruby String Replacement, Substitution and Insertion
- Substitution控件
- substitution控件
- Bad substitution
- [Cryptography]Simple Substitution Cipher
- Substitution.MethodName 属性
- Liskov Substitution Principle
- Confusion, diffusion, Collision, Substitution
- Substitution 控件学习
- zoj 1831 Substitution Cypher
- ASP.NET Substitution控件
- zoj 1831 Substitution Cypher
- Bash Commands - $ # Variable Substitution
- [Linux] [bash] Command Substitution
- ZOJ 1831 Substitution Cypher
- poj 1265 ||poj2954 pick公式 网格
- poj3384 Feng Shui 半平面交
- 获取Android设备硬件信息
- Hibernate Hibernate包已经添加,做数据库实体映射不显示项目名,Hibernate Reverse Engineering
- android单元测试AndroidTestCase
- string substitution
- poj3525 半面交+二分
- 基类成员在派生类中的调整
- web流程 定义 (网页上的工作流程定义 javascirpt版)
- 兼容性白皮书
- poj1755 Triathlon 半平面交
- Networking
- 完成web开发必知工具
- 手把手教你写游戏修改器