string Delphi中是否有必要将字符串转换为WideString?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1024515/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 00:28:27  来源:igfitidea点击:

Is it necessary to convert string to WideString in Delphi?

delphistringwidestring

提问by Mariusz Schimke

I found a Windows API function that performs "natural comparison" of strings. It is defined as follows:

我找到了一个执行字符串“自然比较”的 Windows API 函数。它的定义如下:

int StrCmpLogicalW(
    LPCWSTR psz1,
    LPCWSTR psz2
);

To use it in Delphi, I declared it this way:

为了在 Delphi 中使用它,我是这样声明的:

interface
  function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall;

implementation
  function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

Because it compares Unicodestrings, I'm not sure how to call it when I want to compare ANSI strings. It seems to be enough to cast strings to WideString and then to PWideChar, however, I have no idea whether this approach is correct:

因为它比较Unicode字符串,所以当我想比较 ANSI 字符串时,我不确定如何调用它。将字符串转换为 WideString 然后转换为 PWideChar 似乎就足够了,但是,我不知道这种方法是否正确:

function AnsiNaturalCompareText(const S1, S2: string): integer;
begin
  Result := StrCmpLogicalW(PWideChar(WideString(S1)), PWideChar(WideString(S2)));
end;

I know very little about character encoding so this is the reason of my question. Is this function OK or should I first convert both the compared strings somehow?

我对字符编码知之甚少,所以这就是我提出问题的原因。这个函数是否可以,或者我应该先以某种方式转换两个比较的字符串?

采纳答案by gabr

Keep in mind that casting a string to a WideString will convert it using default system codepage which may or may not be what you need. Typically, you'd want to use current user's locale.

请记住,将字符串转换为 WideString 将使用默认系统代码页将其转换,这可能是也可能不是您需要的。通常,您希望使用当前用户的语言环境。

From WCharFromCharin System.pas:

WCharFromCharSystem.pas 中:

Result := MultiByteToWideChar(DefaultSystemCodePage, 0, CharSource, SrcBytes,
  WCharDest, DestChars);

You can change DefaultSystemCodePage by calling SetMultiByteConversionCodePage.

您可以通过调用SetMultiByteConversionCodePage来更改 DefaultSystemCodePage 。

回答by Ian Boyd

The easier way to accomplish the task would be to declare your function as:

完成任务的更简单方法是将函数声明为:

interface
   function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall;

implementation
   function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

Because a WideStringvariable isa pointer to a WideChar(in the same way an AnsiStringvariable isa pointer to an AnsiChar.)

因为WideString变量指向 a 的指针WideChar(就像AnsiString变量指向AnsiChar.)

And this way Delphi will automatically "up-convert" an AnsiString to a WideStringfor you.

这样,Delphi 会自动将 AnsiStringWideString为您“向上转换”为 a 。

Update

更新

And since we're now in the world of UnicodeString, you would make it:

既然我们现在在 的世界UnicodeString,你会做到:

interface
   function StrCmpLogicalW(const sz1, sz2: UnicodeString): Integer; stdcall;

implementation
   function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

Because a UnicodeStringvariable is still a pointer to a \0\0terminated string of WideChars. So if you call:

因为UnicodeString变量仍然是指向\0\0终止字符串的指针WideChars。所以如果你打电话:

var
    s1, s1: AnsiString;
begin
    s1 := 'Hello';
    s2 := 'world';

    nCompare := StrCmpLogicalW(s1, s2);
end;

When you try to pass an AnsiStringinto a function that takes a UnicodeString, the compiler will automatically call MultiByteToWideCharfor you in the generated code.

当您尝试将 an 传递给采用AnsiStringa 的函数时,UnicodeString编译器将自动MultiByteToWideChar在生成的代码中调用您。

CompareString supports numeric sorting in Windows 7

CompareString 支持 Windows 7 中的数字排序

Starting in Windows 7, Microsoft added SORT_DIGITSASNUMBERSto CompareString:

从 Windows 7 开始,Microsoft 添加SORT_DIGITSASNUMBERSCompareString

Windows 7:Treat digits as numbers during sorting, for example, sort "2" before "10".

Windows 7:在排序时将数字视为数字,例如将“2”排在“10”之前。

None of this helps answer the actualquestion, which deals with when you have to convert or cast strings.

这些都无助于回答实际问题,该问题涉及何时必须转换或强制转换字符串。

回答by PatrickvL

There might be an ANSI variant for your function to (I haven't checked). Most Wide API's are available as an ANSI version too, just change the W suffix to an A, and you're set. Windows does the back-and-forth conversion transparantly for you in that case.

您的函数可能有一个 ANSI 变体(我还没有检查过)。大多数 Wide API 也可以作为 ANSI 版本使用,只需将 W 后缀更改为 A,就可以了。在这种情况下,Windows 会为您透明地进行来回转换。

PS: Here's an article describing the lack of StrCmpLogicalA : http://blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx

PS:这是一篇描述缺少 StrCmpLogicalA 的文章:http: //blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx

回答by NGLN

Use System.StringToOleStr, which is a handy wrapper around MultiByteToWideChar, see Gabr's answer:

使用System.StringToOleStr,这是一个方便的包装器MultiByteToWideChar,请参阅Gabr 的回答

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;

But then, Ian Boyd's solutionlooks and is much nicer!

但是,伊恩博伊德的解决方案看起来更好!