字串
Ching-Tang Tseng
Hamilton, New Zealand
2 December 2018
貼文只是我的義務,不是責任。所以,我有空才貼,逐次貼。這一篇,慢慢貼。
1. 字串元素的建立
此處,
我們把傳統的包封字串稱為小字串,相關操作指令盡量以小寫的
s 起首。
我們把現行巨型包封字串稱為大字串,相關操作指令盡量以 $ 號為起首。
\\\\\\\\\\
以 Forth 程式語言描述此種字串之資料結構的建立方法為 :
: string
create allot
align ( n -- ) 創建時
does> ( -- addr ) 執行時
;
這樣的設計,對大小字串而言,同樣適用,創建時的宣告範例如 :
40 string
name1 小字串
4000 string name2
大字串
\\\\\\\\\\
事實上,可以不必這麼麻煩。上列程式,只是為了解說方便而寫,確實能夠達到資料結構的宣告目的。
改成下列的宣告方式,產生的結果,將完全相同,我們卻可以在系統中省下一個多餘指令
string 的用名。
解決一件事情的方法,如果可以有好幾個,那麼,最簡單的一個,就是最好的一個。
正規的宣告方式,可以經由下列所示完成 :
create name1 40 allot 小字串
create name2 4000 allot 大字串
2. 輸出顯示字串元素的內容
2.1 小字串
想要印出字串時的執行方法 :
name1 count type
count 的執行工作 :
count ( addr –
addr+1 len )
type 的執行要求 :
type ( addr+1 len
-- )
2.2 大字串
想要印出字串時的執行方法 :
name2 $@ type
$@ 的執行工作 :
$@ ( addr ---
addr+cell len )
type 的執行要求 :
type ( addr+cell
len -- )
請注意! 大字串直接使用 type 印出字串的方式,與小字串使用的方式類似。差別僅在大字串使用 $@,小字串使用 count 。
3. 輸入字串放進字串元素
採取能夠自動形成包封字串的指令 S” ……..” 直接輸入字串時,大小字串的程式寫法也類似。
例如 :
S” 此字串將存入小字串元素 name1”
name1 s! 小字串
S” 此字串將存入大字串元素 name2”
name2 $! 大字串
這樣的寫法,也可以寫進程式中使用。利用 2 中已介紹過的印出字串方法,則可以驗證執行結果。
S” ……..” 的執行結果,提供了s! 及 $! 所需要的前兩個參數,name1或name2則提供出第三個所需要的參數。
S” ……..” 也可以提供type執行前所需要的兩個參數。
S” ……..” ( -- addr len )
s! ( addr1 len addr2 -- ) 憑三個參數,將addr1處的指定字串,放進小字串元素addr2內。
在Lina64中,沒有現成的
s! 指令,簡單的高階定義設計如下:
: s! ( addr1 len addr2 -- )
2dup c! 1+ swap cmove ;
$! ( addr1
len addr2 -- ) 憑三個參數,將addr1處的指定字串,放進大字串元素addr2內。
4. 存取字串元素內容所需要的額外指令
字串元素的內容經常需要被進行額外的運作,尤其是常須逐漸地加大、加長,我可以舉出許多個自己曾經用過的這種例子。
例如:
想要逐次增加一個內容為龐大規模的字串,最後形成一個檔案。
字串可被分成幾個小段的文字,要先行組合完畢後,才能整串拿來當命令使用。
舉凡,大數字的輸出,都得逐個字元轉換,轉換完畢後,才一次性的印出來。不這樣做,系統的執行速度就會非常慢。
等等。
因此,在初次宣告出字串元素時,我們經常會先行配給較多或較大量的記憶體,供字串元素使用。
字串內容增長的方式具有規律性,是較為常見的需求,配合這種需要,系統提供現成的指令。
每次只增加單一個字元於字串尾部時,指令的慣用名稱為:
: sc+ ( c addr
-- ) 小字串
dup >r dup c@ + 1+ c! 1 r> c+! ;
$c+ ( c addr -- ) 大字串
每次要增加一個字串於原有字串的尾部時,指令的慣用名稱為:
: s+! ( addr1
len addr2 -- ) 小字串
dup c@ >r 2dup c+! 1+ r> + swap cmove
;
$+! ( addr1 len addr2 -- ) 大字串
在Lina64系統中,另有兩個現成較為常要用到的字串操作指令,此處僅列示其執行效果,不做深究。
String find
accorging to c :
$^ ( addr1 len c
-- addr2 )
String split
according to c :
$/ ( addr1 len1
c -- addr2 len2 addr3 len3 )
5. 字串元素的函數
像數學體系一樣,字串元素所形成的集合,也能進行函數方式的運算。這方面的擴展應用非常廣泛,無法窮舉,此處僅列舉一些用來建立概念的範例。
特別聲明:前兩個指令的原始設計人是 Hugh Aguilar,原始程式曾經由作者公開張貼於國際論壇,我將源程式修改成在 Lina64 系統可以使用的格式,特此致謝,表示尊重。
這幾個指令,都同樣可以使用於大或小字串的操作上,理由同上。
比較兩個字串是否一樣?所得結果為真或為假之值。
: str= ( adrA lenA adrB lenB -- flag ) \ compare the strings for equality
2 pick <> if drop drop drop false exit then
tuck + swap
?do \ -- adrA
dup c@ I c@ <> if drop false unloop exit then
1+
loop
drop true ;
將一個字串的內容就地反轉,產生的結果仍然放在原位址上,但為與原字串反向排列的新字串。
: $reverse ( addr len -- )
2dup + -rot \ -- limit-adr adr cnt
2/ over + swap
?do 1- \ -- last-adr
dup c@ I c@ \ -- last-adr last-char char
2 pick c! I c!
loop
drop ;
將兩個字串相加,結果放在後一個字串的內容上。
: $+ ( addr1 len1 addr2 len2 -- addr2 len3)
2swap swap 2over + 2 pick cmove + ;
6. 實際應用範例
整理出上述有關字串指令的資料,是為了用來解決實際問題。
我所設計的 ABC FORTH 系統,過去,只專注於純粹的數學計算,忽略了字串處理。
自從需要處理網路訊息的要求全面到來之後,電腦程式語言就必須面對夾雜了字串處理要求的問題。
我從不久前國際論壇論及的一個知名網站,取用一個簡單問題作為範例,也應特此聲明,表示尊重。
求解這種類似的問題,需要數學計算與字串處理雙方面配合起來應用,才能解決問題。
網址在:
https://projecteuler.net/problem=4
題目為:
Largest palindrome product
Problem 4
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
程式解:
create xy 4 cells allot
create yx 4 cells allot
: str= ( adrA lenA adrB lenB -- flag ) \ compare the strings for equality
2 pick <> if drop drop drop false exit then
tuck + swap ?do \ -- adrA
dup c@ I c@ <> if drop false unloop exit then
1+ loop
drop true ;
: $reverse ( addr len -- )
2dup + -rot \ -- limit-adr adr cnt
2/ over + swap
?do 1- \ -- last-adr
dup c@ I c@ \ -- last-adr last-char char
2 pick c! I c!
loop
drop ;
4 integers a b x n
: main
basic
10 let n = 0
20 for a = 999 to 100 step -1
30 for b = a to 100 step -1
40 let x = a * b
50 if x > n then 70
60 goto 120
70 run x (.) 2dup xy $! yx $! yx $@ $reverse
80 if xy $@ yx $@ str= then 100
90 goto 120
100 let n = a * b
110 print " a = " ; a ; " b = " ; b
120 next b
130 next a
140 print " n = " ; n
150 end
;
main
執行結果:
ching@center:~/lina64$ ./f
AMDX86 ciforth 5.3.0
fload palindromic.f
a : ISN'T UNIQUE
b : ISN'T UNIQUE
n : ISN'T UNIQUE
a = 995 b = 583
a = 993 b = 913
n = 906609 OK
.s
S[ ] OK
最終的答案是:906609
沒有留言:
張貼留言