如何修改Delphi 7的AnsiStrPos函数以返回整数偏移并支持起始位置
嗨,我来帮你搞定Delphi 7里这个带起始偏移的字符串查找问题!我会一步步给你讲清楚怎么修改代码,以及如何从PChar获取正确的整数偏移。
核心知识点:从PChar获取整数偏移
首先要明确两种偏移的区别:
- 字节偏移:两个PChar指针直接相减得到的就是字节数(比如
FoundPtr - StrPtr),直接转成Integer就是相对于原字符串起始的字节位置(0-based)。 - 字符偏移(和AnsiPos一致):因为Delphi 7用的是MBCS(多字节字符集),一个字符可能占1-2字节,所以需要把字节偏移转换成字符位置,这时候可以用
AnsiStrings单元里的ByteToCharIndex函数,它能把字节偏移转成0-based的字符索引,加1就是AnsiPos那样的1-based字符位置。
修改后的函数实现
我们基于你提供的AnsiStrPos代码,添加起始偏移参数,并返回和AnsiPos一致的整数结果(找到返回1-based字符位置,没找到返回0):
首先要确保你的代码引用了AnsiStrings单元(Delphi 7默认可能需要手动添加),然后用下面的函数:
uses AnsiStrings; function MyAnsiPosEx(const SubStr, Str: string; StartOffset: Integer): Integer; var PStr, PSubStr, FoundPtr: PChar; L1, L2: Cardinal; ByteType: TMbcsByteType; StartByteOffset: Integer; OriginalStrPtr: PChar; begin Result := 0; // 输入合法性检查 if (Str = '') or (SubStr = '') then Exit; if (StartOffset < 1) or (StartOffset > Length(Str)) then Exit; OriginalStrPtr := PChar(Str); PStr := OriginalStrPtr; PSubStr := PChar(SubStr); // 把1-based的起始字符位置转成字节偏移,移动指针到起始查找位置 StartByteOffset := AnsiStrings.CharToByteIndex(OriginalStrPtr, StartOffset - 1); Inc(PStr, StartByteOffset); L1 := StrLen(PStr); L2 := StrLen(PSubStr); if L2 > L1 then Exit; // 子串比剩余字符串长,直接返回0 FoundPtr := StrPos(PStr, PSubStr); while (FoundPtr <> nil) and ((L1 - Cardinal(FoundPtr - PStr)) >= L2) do begin // 检查找到的位置是否是合法的字符起始(不是多字节字符的 trailing byte) ByteType := StrByteType(OriginalStrPtr, Integer(FoundPtr - OriginalStrPtr)); if (ByteType <> mbTrailByte) and (AnsiCompareStr(FoundPtr, PSubStr) = 0) then begin // 转换为1-based字符位置,返回结果 Result := AnsiStrings.ByteToCharIndex(OriginalStrPtr, Integer(FoundPtr - OriginalStrPtr)) + 1; Exit; end; // 跳过无效的位置,继续查找 if (ByteType = mbLeadByte) then Inc(FoundPtr); Inc(FoundPtr); FoundPtr := StrPos(FoundPtr, PSubStr); end; end;
测试你的示例
用你给的测试场景验证:
var TestStr: string; begin TestStr := 'sub_string'; // 从字符位置4开始查找'string',结果返回0(没找到) ShowMessage(IntToStr(MyAnsiPosEx('string', TestStr, 4))); // 从字符位置5开始查找,结果返回5(找到的起始位置) ShowMessage(IntToStr(MyAnsiPosEx('string', TestStr, 5))); end;
如果你需要字节偏移而不是字符位置
如果你的需求是返回字节偏移而不是字符位置,只需要修改返回结果的那一行:
// 返回1-based字节偏移 Result := Integer(FoundPtr - OriginalStrPtr) + 1; // 或者返回0-based字节偏移 // Result := Integer(FoundPtr - OriginalStrPtr);
内容的提问来源于stack exchange,提问作者John Boe
相关产品推荐
相关产品推荐

