日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

string substitution

發布時間:2024/1/18 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 string substitution 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
(defstruct bufvec (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) #\t CL-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))) 6 CL-USER> (file-subst " th" "z" "d:/emacs/string.txt" "d:/emacs/stringold.txt") NIL

總結

以上是生活随笔為你收集整理的string substitution的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。