在 Delphi Alexandria RTL 中,它們具有以下功能:
function ScanChar(const S: string; var Pos: Integer; Ch: Char): Boolean;
var
C: Char;
begin
if (Ch = ' ') and ScanBlanks(S, Pos) then
Exit(True);
Result := False;
if Pos <= High(S) then
begin
C := S[Pos];
if C = Ch then
Result := True
else if (Ch >= 'a') and (Ch <= 'z') and (C >= 'a') and (C <= 'z') then
Result := Char(Word(C) xor $0020) = Char(Word(Ch) xor $0020)
else if Ch.IsLetter and C.IsLetter then
Result := ToUpper(C) = ToUpper(Ch);
if Result then
Inc(Pos);
end;
end;
我無法理解這種比較的目的:
else if (Ch >= 'a') and (Ch <= 'z') and (C >= 'a') and (C <= 'z') then
Result := Char(Word(C) xor $0020) = Char(Word(Ch) xor $0020)
看起來和這樣做是一樣的:
else if (Ch >= 'a') and (Ch <= 'z') and (C >= 'a') and (C <= 'z') then
Result := c = Ch
這是真的?
uj5u.com熱心網友回復:
else if (Ch >= 'a') and (Ch <= 'z') and (C >= 'a') and (C <= 'z') then Result := Char(Word(C) xor $0020) = 字符(字(Ch)xor $0020)
如果字符是純 ASCII 字母,則此比較的目的是優化和進行更快的比較,并避免通過ToUpper可以處理 Unicode 字符的函式對 WinAPI 進行昂貴的呼叫。
或者至少如果比較本身不會被嚴重破壞,那會發生什么。
比較檢查兩個字符是否都是小寫字母,是否在小寫字母a(ASCII 值 97)和小寫字母z(ASCII 值 122)之間的范圍內。但它實際上應該檢查的是,這兩個字符都在 large letter A(ASCII value 65) 和 small letterz之間的范圍內,無論大小寫如何,都覆寫了整個 ASCII 字母范圍。(該范圍內幾乎沒有非字母字符,但這些不相關,因為任何這些字符Result都不會產生賦值。)True
一旦修復了,我們還需要修復Result賦值運算式,因為它不能正確比較小寫和大寫字母。為此,我們可以簡單地or對所有字符使用運算子,它將大寫字符轉換為小寫,并保持小寫不變。如前所述,在代碼的這一點上,可以安全地忽略該范圍內的非字母字符。
該部分ScanChar功能的正確代碼是:
...
else
if (Ch >= 'A') and (Ch <= 'z') and (C >= 'A') and (C <= 'z') then
Result := Word(Ch) or $0020 = Word(C) or $0020
else
...
注意:即使原始ScanChar函式包含不正確的代碼,函式的結果仍然是正確的,因為相同的字母在不同的情況下代碼總是會經過ToUpper部分 if 分支。
uj5u.com熱心網友回復:
我想它與 不完全相同C = Ch,但結果是相同的。
比較是多余的,恕我直言。它XOR用于將小寫 ASCII 字母轉換為大寫 ASCII 字母(因為它們僅相差 1 位),然后比較大寫字母是否相等。但是下面使用IsLetter 的比較ToUpper做同樣的事情,只適用于任何字母,而不僅僅是 ASCII 字母。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/509903.html
