Windows 上的任何程序都可以调用 shell-API 函数,这可以减少代码大小。像往常一样,从下往上阅读程序。这仅使用 Ascii 字符串进行了测试,而不是宽字符串。
program PrgDmoPosIns; {$AppType Console} // demo case-insensitive Pos function for Windows
// Free Pascal 3.2.2 [2022/01/02], Win32 for i386
// FPC.EXE -vq -CoOr -Twin32 -oPrgStrPosDmo.EXE PrgStrPosDmo.LPR
// -vq Verbose: Show message numbers
// -C Code generation:
// o Check overflow of integer operations
// O Check for possible overflow of integer operations - Integer Overflow checking turns on Warning 4048
// r Range checking
// -Twin32 Target 32 bit Windows operating systems
// 29600 bytes code, 1316 bytes data, 35,840 bytes file
function StrStrIA( pszHaystack, pszNeedle : PChar ) : PChar; stdcall; external 'shlwapi.dll'; // dynamic link to Windows API's case-INsensitive search
// https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-strstria
// "FPC\3.2.2\Source\Packages\winunits-base\src\shlwapi.pp" line 557
function StrPos( strNeedle, strHaystk : string ) : SizeInt; // return the position of Needle within Haystack, or zero if not found
var
intRtn : SizeInt; // function result
ptrHayStk , // pointers to
ptrNeedle , // search strings
strMchFnd : PChar ; // pointer to match-found string, or null-pointer/empty-string when not found
bolFnd : boolean; // whether Needle was found within Haystack
intLenHaystk , // length of haystack
intLenMchFnd : SizeInt; // length of needle
begin
strHayStk := strHayStk + #0 ; // strings passed to API must be
strNeedle := strNeedle + #0 ; // null-terminated
ptrHayStk := Addr( strHayStk[ 1 ] ) ; // set pointers to point at first characters of
ptrNeedle := Addr( strNeedle[ 1 ] ) ; // null-terminated strings, so API gets C-style strings
strMchFnd := StrStrIA( ptrHayStk, ptrNeedle ); // call Windows to perform search; match-found-string now points inside the Haystack
bolFnd := ( strMchFnd <> '' ) ; // variable is True when match-found-string is not null/empty
if bolFnd then begin ; // when Needle was yes found in Haystack
intLenMchFnd := Length( strMchFnd ) ; // get length of needle
intLenHaystk := Length( strHayStk ) ; // get length of haystack
intRtn := intLenHaystk - intLenMchFnd; // set function result to the position of needle within haystack, which is the difference in lengths
end else // when Needle was not found in Haystack
intRtn := 0 ; // set function result to tell caller needle does not appear within haystack
StrPos := intRtn ; // pass function result back to caller
end; // StrPos
procedure TstOne( const strNeedle, strHayStk : string ); // run one test with this Needle
var
intPos : SizeInt; // found-match location of Needle within Haystack, or zero if none
begin
write ( 'Searching for : [', strNeedle, ']' ); // bgn output row for this test
intPos := StrPos( strNeedle, strHaystk ); // get Needle position
writeln(' StrPos is ' , intPos ); // end output row for this test
end; // TstOne
procedure TstAll( ); // run all tests with various Needles
const
strHayStk = 'Needle in a Haystack'; // all tests will search in this string
begin
writeln( 'Searching in : [', strHayStk, ']' ); // emit header row
TstOne ( 'Noodle' , strHayStk ); // test not-found
TstOne ( 'Needle' , strHayStk ); // test found at yes-first character
TstOne ( 'Haystack' , strHayStk ); // test found at not-first character
end; // TstAll
begin // ***** MAIN *****
TstAll( ); // run all tests
end.