呵呵,好久没见到 悲酥清风 上来了啊:)
//哪位收藏有的话请发给我一份,谢谢
呵呵,我还是直接贴出来吧,其他富翁恐怕也想要一份:)
我用了 FastPos 作为基础改的,加几个外壳就可以了嘛:
(注意这个 FastPos 也是我改过的,修正了个 bug,如果你有以前版本的请更新为这个)
// 快速字符串查找函数
// This TYPE declaration will become apparent later.
//The first thing to note here is that I’m passing the SourceLength and FindL
//ength. As neither Source nor Find will alter at any point during FastReplace
//, there’s no need to call the LENGTH subroutine each time!
function FastPos(
const aSourceString, aFindString : String;
const aSourceLen, aFindLen, StartPos : Integer
) : Integer;
begin
// Next, we determine how many bytes we need to
// scan to find the "start" of aFindString.
// Remove by SunLujiang
{
SourceLen := aSourceLen;
SourceLen := SourceLen - aFindLen;
if (StartPos-1) > SourceLen then begin
Result := 0;
Exit;
end;
SourceLen := SourceLen - StartPos;
SourceLen := SourceLen +2;
}
// Remove end
// The ASM starts here.
asm
// Delphi uses ESI, EDI, and EBX a lot,
// so we must preserve them.
push ESI
push EDI
push EBX
// Add by SunLujiang
Mov ECX, aSourceLen
Mov EAX, aFindLen
// Add by beta begin
//make sure that aFindLen > 0, or it may cause a exception
Cmp EAX, 0
Jle @Result0
// Add by beta end
Sub ECX, EAX
JL @Result0
Mov EAX, StartPos
Dec EAX
Sub ECX, EAX
JL @Result0
Inc ECX
// Add end
// Get the address of sourceString[1]
// and Add (StartPos-1).
// We do this for the purpose of finding
// the NEXT occurrence, rather than
// always the first!
mov EDI, aSourceString
add EDI, StartPos
Dec EDI
// Get the address of aFindString.
mov ESI, aFindString
// Note how many bytes we need to
// look through in aSourceString
// to find aFindString.
// Remove by SunLujiang
// mov ECX, SourceLen
// Remove end
// Get the first char of aFindString;
// note how it is done outside of the
// main loop, as it never changes!
Mov Al, [ESI]
// Now the FindFirstCharacter loop!
@ScaSB:
// Get the value of the current
// character in aSourceString.
// This is equal to ah := EDI^, that
// is what the [] are around [EDI].
Mov Ah, [EDI]
// Compare this character with aDestString[1].
cmp Ah,Al
// If they're not equal we don't
// compare the strings.
jne @NextChar
// If they're equal, obviously we do!
@CompareStrings:
// Put the length of aFindLen in EBX.
mov EBX, aFindLen
// We DEC EBX to point to the end of
// the string
that is, we don't want to
// add 1 if aFindString is 1 in length!
dec EBX
// add by ShengQuanhu
// If EBX is zero, then we've successfully
// compared each character
i.e. it's A MATCH!
// It will be happened when aFindLen=1
Jz @EndOfMatch
//add end
//Here’s another optimization tip. People at this point usually PUSH ESI and
//so on and then POP ESI and so forth at the end–instead, I opted not to chan
//ge ESI and so on at all. This saves lots of pushing and popping!
@CompareNext:
// Get aFindString character +
// aFindStringLength (the last char).
mov Al, [ESI+EBX]
// Get aSourceString character (current
// position + aFindStringLength).
mov Ah, [EDI+EBX]
// Compare them.
cmp Al, Ah
Jz @Matches
// If they don't match, we put the first char
// of aFindString into Al again to continue
// looking for the first character.
Mov Al, [ESI]
Jmp @NextChar
@Matches:
// If they match, we DEC EBX (point to
// previous character to compare).
Dec EBX
// If EBX <> 0 ("J"ump "N"ot "Z"ero), we
// continue comparing strings.
Jnz @CompareNext
//add by Shengquanhu
@EndOfMatch:
//add end
// If EBX is zero, then we've successfully
// compared each character
i.e. it's A MATCH!
// Move the address of the *current*
// character in EDI.
// Note, we haven't altered EDI since
// the first char was found.
mov EAX, EDI
// This is an address, so subtract the
// address of aSourceString[1] to get
// an actual character position.
sub EAX, aSourceString
// Inc EAX to make it 1-based,
// rather than 0-based.
inc EAX
// Put it into result.
mov Result, EAX
// Finish this routine!
jmp @TheEnd
@NextChar:
//This is where I jump to when I want to continue searching for the first char
//acter of aFindString in aSearchString:
// Point EDI (aFindString[X]) to
// the next character.
Mov Ah, [EDI]//先把第一个字符移到Ah中,后面判断是否中文
Inc EDI
// Dec ECX tells us that we've checked
// another character, and that we're
// fast running out of string to check!
dec ECX
// If EBX <> 0, then continue scanning
// for the first character.
//add by shengquanhu
//if ah is chinese char,jump again
jz @Result0
cmp ah, $80
jb @ScaSB
Inc EDI
Dec ECX
//add by shengquanhu end
jnz @ScaSB
//add by shengquanhu
@Result0:
//add by shengquanhu end
// If EBX = 0, then move 0 into RESULT.
mov Result,0
// Restore EBX, EDI, ESI for Delphi
// to work correctly.
// Note that they're POPped in the
// opposite order they were PUSHed.
@TheEnd:
pop EBX
pop EDI
pop ESI
end;
end;
function MyPos(substr, str: string): Integer;
begin
Result := FastPos(str, substr, Length(str), Length(substr), 1);
end;
// 字符串反向查找,思路是将源字符串和目标字符串都反序,然后查找
function FastPosUp(
const aSourceString, aFindString : String;
const aSourceLen, aFindLen, StartPos : Integer
) : Integer;
var
i, tstart: Integer;
tstr, tsub: string;
begin
SetLength(tstr, aSourceLen);
SetLength(tsub, aFindLen);
for i := 1 to aSourceLen do //reverse the source string
tstr := aSourceString[aSourceLen + 1 - i];
for i := 1 to aFindLen do //reverse the find string
tsub := aFindString[aFindLen + 1 - i];
tstart := aSourceLen + 1 - StartPos;
tstart := FastPos(tstr, tsub, aSourceLen, aFindLen, tstart);
if tstart > 0 then
Result := aSourceLen + 1 - tstart - aFindLen + 1
else
Result := 0;
end;
function MyBackPos(substr, str: string): Integer;
begin
Result := FastPosUp(str, substr, Length(str), Length(substr), Length(str));
end;
// 字符串替换
//replace all the "ss" in "text" to "ds"
procedure StringReplaceAll(var text: string
const ss, ds: string);
var
p: Integer;
begin
p := MyPos(ss, text);
while p > 0 do
begin
Delete(text, p, Length(ss));
Insert(ds, text, p);
p := MyPos(ss, text);
end;
end;
// 出现频率统计
function MyCount(substr, str: string): Integer;
var
Start: Integer;
begin
Result := 0;
Start := 1;
repeat
Start := FastPos(str, substr, Length(str), Length(substr), Start);
if Start > 0 then
begin
Inc(Result);
Inc(Start, Length(substr));
end
else
Break;
until Start = 0;
end;
// 将 pFlag 和 nFlag 分别当做左右括号,查找括号内的内容的起始位置和长度,
// 为后面的去字符串中间部分作准备
//return the range of the matching pFlag and nFlag in aText, start with aStart
procedure GetRange(aText: string
aStart: Integer
pFlag, nFlag: string;
var sStart, sLength: Integer
LevelSearch: Boolean = False);
var
pCount, tStart, tEnd, sLevel: Integer;
ts: string;
begin
sStart := -1;
sLength := 0;
if (Length(aText) > 2) and (aStart < Length(aText) - 1) then
begin
sStart := FastPos(aText, pFlag, Length(aText), Length(pFlag), aStart + 1);
Dec(sStart)
//convert to index
if sStart > -1 then //found the pFlag
begin
tStart := sStart + Length(pFlag);
tEnd := FastPos(aText, nFlag, Length(aText), Length(nFlag), tStart + 1);
Dec(tEnd)
//convert to index
if tEnd > -1 then //found the nFlag
begin
tEnd := tEnd + Length(nFlag);
if LevelSearch then
begin //level search
ts := Copy(aText, tStart + 1, tEnd - tStart + 1);
sLevel := MyCount(pFlag, ts);
while sLevel > 0 do //not in the same level
begin
tStart := tEnd + Length(nFlag);
tEnd := FastPos(aText, nFlag, Length(aText), Length(nFlag), tStart + 1);
Dec(tEnd)
//convert to index
if tEnd > -1 then
begin
Dec(sLevel);
tEnd := tEnd + Length(nFlag);
ts := Copy(aText, tStart + 1, tEnd - tStart + 1);
pCount := MyCount(pFlag, ts);
if pCount > 0 then //more pFlags, so, get into further level
sLevel := sLevel + pCount;
end
else
Exit;
end;
end;
sLength := tEnd - sStart;
end;
end;
end;
end;
// 去字符串 Src 中 在 Prefix 之后且在 Postfix 之前的内容(不含)
function StrBetween(Src, Prefix, Postfix: string): string;
var
Start, Len: Integer;
begin
GetRange(Src, 1, Prefix, Postfix, Start, Len, True);
Result := Copy(Src, Start + Length(Prefix), Len - Length(Prefix)
- Length(Postfix));
end;
// 返回 Src 中在字符串 Flag 后面的部分
function StrAfter(Src, Flag: string): string;
var
p: Integer;
begin
p := MyPos(Flag, Src);
Result := Copy(Src, p + Length(Flag), MaxInt);
end;
// 返回 Src 中在字符串 Flag 前面的部分
function StrBefore(Src, Flag: string): string;
var
p: Integer;
begin
p := MyPos(Flag, Src);
Result := Copy(Src, 1, p - Length(Flag));
end;
//获取字符串A中最后一个字符串B后面的字符串值,并且返回这个字符串间隔符B的起始位置
//f('abcabc','b',s)=5 s='c'
function StrAfterEx(Src, Flag: string
var Res: string): Integer;
begin
Result := MyBackPos(Flag, Src);
Res := Copy(Src, Result + Length(Flag), MaxInt);
end;
//获取字符串A中最后一个字符串B前面的字符串值,并且返回这个字符串间隔符B的起始位置
//f('abcabc','b',s)=5 s='abca'
function StrBeforeEx(Src, Flag: string
var Res: string): Integer;
begin
Result := MyBackPos(Flag, Src);
Res := Copy(Src, 1, Result - Length(Flag));
end;
呼,累啊,写的差不多了吧,我直接在这里写的,没有调试哦,自己试一试吧:)