Delete 函數中,有這兩句:CALL Move和CALL_LstrSetLength。其中Move函數是將一個內存塊拷貝到另一個地址,LstrSetLength函數將改變字符串的長度,其中也有對內存進行分配的代碼。這些對內存進行操作的函數都是極其消耗CPU運行時間的,所以Delete函數也是一個極其消耗CPU運行時間的函數。為了盡量避免使用這些函數,我對自定義函數RightPos進行了改寫。
修改後不再使用Delete及Pos函數,直接通過指針對內存操作,提高了效率。
function RightPosEx(const Substr,S: string): Integer;
var
iPos: Integer;
TmpStr:string;
i,j,len: Integer;
PCharS,PCharSub:PChar;
begin
PCharS:=PChar(s); //將字符串轉化為PChar格式
PCharSub:=PChar(Substr);
Result:=0;
len:=length(Substr);
for i:=0 to length(S)-1 do
begin
for j:=0 to len-1 do
begin
if PCharS[i+j]<>PCharSub[j] then break;
end;
if j=len then Result:=i+1;
end;
請看第一句PCharS:=PChar(s),它的作用是將Delphi字符串強制轉化為PChar 格式(PChar 是Windows中使用的標准字符串,不包含長度信息,使用0為結束標志),並得到指向PChar字符串的指針PcharS。
下面就要對自定義函數的運行時間進行測量,為了提高測量的精度,減小隨機性,我們計算重復10000次所需的時間。代碼如下:
var
i,len,iPos: Integer;
PerformanceCount1,PerformanceCount2,Count:int64;
begin
len:=10000; //重復次數
QueryPerformanceCounter(PerformanceCount1);//開始計數
for i:=0 to len-1 do
begin
iPos:=RightPos(’12’,Edit1.Text); //被測試的函數
end;
QueryPerformanceCounter(PerformanceCount2); //結束計數
Count:=(PerformanceCount2-PerformanceCount1);
Label1.Caption:=inttostr(iPos)+’ time=’+inttostr(Count);
End;
我的配置是Duron700,256M內存,測試中RightPos函數重復了10000遍,RightPos使用的參數為:Substr=12,S=Edit12ewew12tet。得到的測量結果是Count=217000,又對其他幾個函數作了對比,結果如下:
函數名 重復次數 QueryPerformanceCounter 計數值 Pos 10000 150000 RightPos 10000 217000 RightPosEx 10000 160000可以看出測試的結果是比較滿意的,改進過的RightPosEx函數效率比RightPos高很多,考慮到測試用的字符串比較短,使用長字符串效果更明顯。如果直接使用Delphi的字符串格式而不用轉為PChar格式,則效率又可提高一步。但字符串格式是Delphi語言自定義的,存在兼容性問題。所以這一版本的字串搜索函數就不列出來了,讀者在前面代碼的基礎上很容易就可寫出來的。代碼優化到底要執行到哪一步,是仁者見仁,智者見智的問題。有的人偏重於提高效率,有的人偏重於保證兼容性,這需要在實際使用過程中作取捨。