全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4994
推到 Plurk!
推到 Facebook!

請問一下有關取部分字串(字串分割)的問題

答題得分者是:maomfh
小蚊子
中階會員


發表:55
回覆:267
積分:94
註冊:2002-06-08

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-07-02 19:51:17 IP:220.132.xxx.xxx 訂閱
程式碼來源 : http://www.swissdelphicenter.ch/torry/showcode.php?id=2275

此程式用法 是要 "" 非常高速 """ 的處理字串

// after optimizations with delphi it comes a
// time for some assembler; also the memory
// management (slow result allocation) has been
// taken care of...
// note : You MUST have the following global
// variables :
// var
// Splitresult : Array[0..1023] of Char;
// P_SplitResArray : Pointer;
// then on form1.create assign Pointer :
// P_SplitResArray := @SplitResult;
// variable Splitresult will contain
// the result after procedure has been completed

procedure split5(const input: string; schar: Char; s: Byte); register;
asm
PUSH ECX
PUSH EAX //registers :
PUSH EDX //EAX = input
PUSH EDI //DH = s
TEST EAX, EAX //if input = '' then
JZ @NoWords // goto @NoInput
@WeHaveIt:MOV DH, CL //DL = schar
MOV EDI, EAX //EDI := Addr(input);
MOV ECX, [EDI-4] //ECX := length(input);
@GoGo: MOV AL, DL //AL := Schar;
CMP DH, 2 //IF DH = 2 then
JE @StartCo // goto @StartCo
MOV AH, 2 //AH (upper 8 bits of AX) will be our separator counter initial value is 2, max 256
@Lop: INC AH //AH := AH 1
REPNE SCASB //while (EDI^<>AL) and (ECX>0) begin INC EDI; DEC ECX; end;
CMP AH, DH //if AH < DH then
JB @Lop // goto @Lop
TEST ECX, ECX //IF ECX > 0 then
JG @StartCo // goto @StartCp
@NoWords: MOV EDI,[P_SplitResArray] //result :=
MOV BYTE PTR [EDI], $0 // ''
JMP @TotalEnd
@StartCo: PUSH ESI
MOV ESI, EDI
MOV EDI, [P_SplitResArray]
@CopyLoop:MOV AH, BYTE PTR[ESI 0] //32 bit aligned loop.. hopefully :)
CMP AH, DL //1. test, 8 bits
JE @Endword
MOV BYTE PTR [EDI 0], AH
INC EDI
MOV AH, BYTE PTR[ESI 1]
CMP AH, DL //2. test, 8 bits -> 16 bits..
JE @Endword
MOV BYTE PTR [EDI 0], AH
INC EDI
MOV AH, BYTE PTR[ESI 2]
CMP AH, DL //3. test, 8 bits -> 24 bits..
JE @Endword
MOV BYTE PTR [EDI 0], AH
INC EDI
MOV AH, BYTE PTR[ESI 3]
CMP AH, DL //4. test, 8 bits -> 32 bits..
JE @Endword
MOV BYTE PTR [EDI 0], AH
INC EDI
ADD ESI, 4
SUB ECX, 4
CMP ECX, 0
JG @Copyloop
@EndWord: MOV BYTE PTR [EDI], $0 //lisää nolla
POP ESI
@TotalEnd:POP EDI
POP EDX
POP EAX
POP ECX
@Final: RET


// = = = = = = = = = = = = = = = = = = = = = = = = =


STR := 'ABCD$123456$JDNDHURYR';

split5( STR , '$' , 0 );

showmessage(Splitresult);

會傳回 123456

想請問 split5( const input: string; schar: Char; s: Byte);

問 1 : input 前加 const 的用意??? 我試過,有加 const 與 不加,似乎必影響結果
問 2 : s 變數的作用是..... 我用 0 或 1 都不影響結果.

謝謝您




shunaaron
高階會員


發表:13
回覆:94
積分:106
註冊:2006-10-06

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-07-02 22:35:07 IP:220.134.xxx.xxx 訂閱
const可以很明確compiler前讓記憶體知所定議之型態
如果沒有加而是在要compiler後才會知是所定議之型態
------
程式沒有這麼難
只是還沒打通其中要絕
maomfh
初階會員


發表:3
回覆:10
積分:27
註冊:2008-01-05

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-08-08 18:17:30 IP:218.163.xxx.xxx 訂閱
問 1 : input  前加  const 的用意???  我試過,有加 const 與 不加,似乎必影響結果
答 1 : (1) 加 const 代表是一個常數變數, 則函數內不可更動該參數的數值, 否則 compiler 會報錯, 無法通過編譯, 好處是,不會因自個兒不小心,動到來源參數的內容了.
(2) 呼叫需傳入 有const 為參數的函數, 則compiler 可以不須再產生一個暫時變數, 這樣可以加速程式速度,也減少堆疊的耗用.

問 2 : s 變數的作用是..... 我用 0 或 1 都不影響結果.
答 2: s 變數是用來選取第幾個分割字串的, 但對原程式有些不明白, 傳入 0, 1 都會傳回第一分割字串, 但傳入2, 3, 4, 5 會分別傳回 第 0, 1,2,3個分割字串,
例如 : 'ABCD$123456$JDNDHURYR
0 : '123456'
1 : '123456'
2 : 'ABCD'
3 : '123456'
4 : 'JDNDHURYR'
5~255 : '' 傳回空字串

------
Maomfh
roviury
一般會員


發表:3
回覆:49
積分:15
註冊:2008-08-28

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-05-11 18:48:06 IP:203.186.xxx.xxx 訂閱
用const ...:string在asm中很重要喔..
delphi都幫你搞好,
其實在asm中,不使用const的string,只是得到一個地址,還需要進一步存取
所以非必要就不要使用沒有const的
100%能夠加快速度

不過回傳很怪
* split5( STR , '$' , 0 )=123456;
* split5( STR , '$' , 1 )=123456;
下面才正常
split5( STR , '$' , 2 );
split5( STR , '$' , 3 );
split5( STR , '$' , 4 );

上樓也提到這個問題吧..
這個問題很重要...沒解決好..這個函數就是失敗

另外,回傳值也十分不方便,又要作出更多的處理,即使多麼快也沒有用


我給一個相同功能的給你,短小快捷
function split6(const input: string; schar: Char; s: cardinal):string;
var
i,k:cardinal;
begin
k:=0;
for i := 0 to length(input)-1 do
begin
if input[i 1]=schar then begin
if s=0 then begin
result:=copy(input,k 1,i-k 1);
exit;
end;
dec(s);
k:=i 1;
end;
end;
result:=copy(input,k 1,i-k 1);
end;

STR := 'ABCD$123456$JDNDHURYR';
showmessage(split6( STR , '$' , 2 )); //JDNDHURYR

你喜歡速度就自己測試吧...一定不會慢

(你會留意到我寫的時候把s改成cardinal,你要處理大字串的話,byte一定不夠用)

STR := 'ABCD$123456$JDNDHURYR';
showmessage(split6( STR , '$' , 100 )); //3或以後都會出現JDNDHURYR
編輯記錄
roviury 重新編輯於 2009-05-11 18:53:55, 註解 無‧
roviury 重新編輯於 2009-05-11 18:57:13, 註解 無‧
roviury 重新編輯於 2009-05-11 18:58:20, 註解 無‧
roviury 重新編輯於 2009-05-11 19:06:47, 註解 無‧
roviury 重新編輯於 2009-05-11 19:07:58, 註解 無‧
roviury 重新編輯於 2009-05-11 19:11:42, 註解 無‧
eaglewolf
資深會員


發表:4
回覆:268
積分:429
註冊:2006-07-06

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-09-14 15:27:31 IP:211.75.xxx.xxx 訂閱
改一下紅色字的部份
傳0回傳 ABCD
傳1回傳123456
傳2回傳JDNDHURYR
傳3以上回傳 空字串
===================引 用 小蚊子 文 章===================
程式碼來源 : http://www.swissdelphicenter.ch/torry/showcode.php?id=2275

此程式用法 是要 "" 非常高速 """ 的處理字串

// after optimizations with delphi it comes a
// time for some assembler; also the memory
// management (slow result allocation) has been
// taken care of...
// note : You MUST have the following global
// variables :
// var
// Splitresult : Array[0..1023] of Char;
// P_SplitResArray : Pointer;
// then on form1.create assign Pointer :
// P_SplitResArray := @SplitResult;
// variable Splitresult will contain
// the result after procedure has been completed

procedure split5(const input: string; schar: Char; s: Byte); register;
asm
PUSH ECX
PUSH EAX //registers :
PUSH EDX //EAX = input
PUSH EDI //DH = s
TEST EAX, EAX //if input = '' then
JZ @NoWords // goto @NoInput
@WeHaveIt:MOV DH, CL //DL = schar
MOV EDI, EAX //EDI := Addr(input);
MOV ECX, [EDI-4] //ECX := length(input);
@GoGo: MOV AL, DL //AL := Schar;
CMP DH, 0 //IF DH = 0 then
JE @StartCo // goto @StartCo
MOV AH, 0 //AH (upper 8 bits of AX) will be our separator counter initial value is 0
@Lop: INC AH //AH := AH 1
REPNE SCASB //while (EDI^<>AL) and (ECX>0) begin INC EDI; DEC ECX; end;
CMP AH, DH //if AH < DH then
JB @Lop // goto @Lop
TEST ECX, ECX //IF ECX > 0 then
JG @StartCo // goto @StartCp
@NoWords: MOV EDI,[P_SplitResArray] //result :=
MOV BYTE PTR [EDI], $0 // ''
JMP @TotalEnd
@StartCo: PUSH ESI
MOV ESI, EDI
MOV EDI, [P_SplitResArray]
@CopyLoop:MOV AH, BYTE PTR[ESI 0] //32 bit aligned loop.. hopefully :)
CMP AH, DL //1. test, 8 bits
JE @Endword
MOV BYTE PTR [EDI 0], AH
INC EDI
MOV AH, BYTE PTR[ESI 1]
CMP AH, DL //2. test, 8 bits -> 16 bits..
JE @Endword
MOV BYTE PTR [EDI 0], AH
INC EDI
MOV AH, BYTE PTR[ESI 2]
CMP AH, DL //3. test, 8 bits -> 24 bits..
JE @Endword
MOV BYTE PTR [EDI 0], AH
INC EDI
MOV AH, BYTE PTR[ESI 3]
CMP AH, DL //4. test, 8 bits -> 32 bits..
JE @Endword
MOV BYTE PTR [EDI 0], AH
INC EDI
ADD ESI, 4
SUB ECX, 4
CMP ECX, 0
JG @Copyloop
@EndWord: MOV BYTE PTR [EDI], $0 //lis nolla
POP ESI
@TotalEnd:POP EDI
POP EDX
POP EAX
POP ECX
@Final: RET




------
先查HELP
再查GOOGLE
最後才發問

沒人有義務替你解答問題
在標題或文章中標明很急
並不會增加網友回答速度

Developing Tool:
1.Delphi 6
2.Visual Studio 2005
3.Visual Studio 2008
DBMS:
MS-SQL
編輯記錄
eaglewolf 重新編輯於 2009-09-14 15:28:52, 註解 無‧
macchen
初階會員


發表:66
回覆:102
積分:33
註冊:2006-07-07

發送簡訊給我
#6 引用回覆 回覆 發表時間:2010-08-27 11:25:02 IP:219.87.xxx.xxx 訂閱
非常好用的文章,謝謝。
------
DELPHI初學者
編輯記錄
macchen 重新編輯於 2010-08-27 11:45:19, 註解 自已沒看清楚原文說明。‧
系統時間:2017-10-20 9:33:50
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!