هل من الضروري تحويل السلسلة إلى WideString في Delphi؟

StackOverflow https://stackoverflow.com/questions/1024515

  •  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;

ولكن بعد ذلك ، حل إيان بويد تبدو أجمل بكثير!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top