هل من الضروري تحويل السلسلة إلى WideString في Delphi؟
-
06-07-2019 - |
سؤال
لقد وجدت وظيفة واجهة برمجة تطبيقات Windows تؤدي "المقارنة الطبيعية" للسلاسل. يتم تعريفه على النحو التالي:
int StrCmpLogicalW(
LPCWSTR psz1,
LPCWSTR psz2
);
لاستخدامه في دلفي ، أعلنت ذلك بهذه الطريقة:
interface
function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
لأنه يقارن يونيكود الأوتار ، لست متأكدًا من كيفية تسميتها عندما أرغب في مقارنة سلاسل Ansi. يبدو أن الأمر كافٍ لإلقاء سلاسل على العرض ، ثم إلى pwidechar ، ومع ذلك ، ليس لدي أي فكرة عما إذا كان هذا النهج صحيحًا:
function AnsiNaturalCompareText(const S1, S2: string): integer;
begin
Result := StrCmpLogicalW(PWideChar(WideString(S1)), PWideChar(WideString(S2)));
end;
أنا أعرف القليل جدًا عن تشفير الشخصية ، لذلك هذا هو سبب سؤالي. هل هذه الوظيفة جيدة أم يجب أن أقوم أولاً بتحويل السلاسل المقارنة بطريقة ما؟
المحلول
ضع في اعتبارك أن إلقاء سلسلة إلى widestring سيقوم بتحويلها باستخدام نظام CodePage الافتراضي الذي قد يكون أو لا يكون ما تحتاجه. عادة ، تريد استخدام لغة المستخدم الحالية.
من WCharFromChar
في System.Pas:
Result := MultiByteToWideChar(DefaultSystemCodePage, 0, CharSource, SrcBytes,
WCharDest, DestChars);
يمكنك تغيير DefaultSystemCodePage عن طريق الاتصال setMultibyTeconversionCodePage.
نصائح أخرى
تتمثل الطريقة الأسهل لإنجاز المهمة في إعلان وظيفتك على النحو التالي:
interface
function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
لأن أ WideString
عامل هو مؤشر إلى WideChar
(بنفس الطريقة AnsiString
عامل هو مؤشر إلى AnsiChar
.)
وبهذه الطريقة ، ستقوم Delphi تلقائيًا بـ "Up-Convert" A Ansistring إلى أ WideString
لك.
تحديث
وبما أننا الآن في عالم UnicodeString
, ، ستجعلها:
interface
function StrCmpLogicalW(const sz1, sz2: UnicodeString): Integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
لأن أ UnicodeString
لا يزال المتغير مؤشرًا لـ \0\0
سلسلة من إنهاء WideChars
. لذلك إذا اتصلت:
var
s1, s1: AnsiString;
begin
s1 := 'Hello';
s2 := 'world';
nCompare := StrCmpLogicalW(s1, s2);
end;
عندما تحاول تمرير AnsiString
في وظيفة تأخذ ملف UnicodeString
, ، سوف يتصل المترجم تلقائيًا MultiByteToWideChar
لك في الكود الذي تم إنشاؤه.
يدعم المقارنة الفرز الرقمي في Windows 7
وأضافت Microsoft بدءًا من Windows 7 SORT_DIGITSASNUMBERS
إلى CompareString
:
ويندوز 7: تعامل مع الأرقام كأرقام أثناء الفرز ، على سبيل المثال ، الفرز "2" قبل "10".
لا شيء من هذا يساعد في الإجابة فِعلي سؤال ، والذي يتعامل معه عندما يتعين عليك تحويل السلاسل أو الإلقاء.
قد يكون هناك متغير ANSI لوظيفتك (لم أتحقق). تتوفر معظم API على نطاق واسع كإصدار ANSI أيضًا ، فقط قم بتغيير لاحقة W إلى A ، وأنت تم تعيينك. يقوم Windows بتحويل العودة والخلف بشكل شفافية لك في هذه الحالة.
ملاحظة: إليك مقالة تصف عدم وجود strcmplogicala: http://blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx
يستخدم System.StringToOleStr
, ، وهو غلاف مفيد حوله MultiByteToWideChar
, ، نرى إجابة غبر:
function AnsiNaturalCompareText(const S1, S2: string): integer;
var
W1: PWideChar;
W2: PWideChar;
begin
W1 := StringToOleStr(S1);
W2 := StringToOleStr(S2);
Result := StrCmpLogicalW(W1, W2);
SysFreeString(W1);
SysFreeString(W2);
end;
ولكن بعد ذلك ، حل إيان بويد تبدو أجمل بكثير!