delphi – 如何比较包含非英文字符的unicode字符串进行排序?

前端之家收集整理的这篇文章主要介绍了delphi – 如何比较包含非英文字符的unicode字符串进行排序?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试排序数组/列表/任何数据基于unicode字符串值包含非英文字符,我希望他们按字母顺序排序。

我写了很多代码(D2010,win XP),我认为这对于未来的国际化来说是非常稳固的,但不是。它全部使用unicodestring(string)数据类型,到目前为止,我刚刚把英文字符放入unicode字符串。

似乎我必须拥有一个非常严重的unicode错误。我跟德国朋友谈过,并尝试了一些德国的ß,(ß是’ss’,应该是S和T之后的字母表)和ö等(注意umlaut),我的排序算法都没有工作了。结果非常混乱。垃圾

从那时起,我一直在阅读广泛,并学习了很多关于unicode整理的不愉快的事情。事情看起来很严峻,比以前预想的要严峻,我已经把这个弄得很厉害了。我希望我错过了一些东西,事实上并不像现在看起来那么严峻。我一直在琢磨着看着windows api调用(RtlCompareUnicodeString),没有成功(保护错误),我无法让它工作。 API调用的问题我学到的是,它们在各种较新的Windows平台上发生变化,并且随着delphi的跨平台也越来越快,随着linux,我的应用程序是客户端服务器,所以我需要关心这一点,但是,是(坏)我会感激任何进步,即胜利api具体。

是否使用win api函数RtlCompareUnicodeString来明显的解决方案?如果是这样,我应该再次尝试,但是我已经对unicode整理涉及到的所有问题感到吃惊,我不清楚我应该做什么来比较这些字符串。

我了解到IBM ICU c opensource项目,但是有一个delphi包装器,尽管是旧版本的ICU。这似乎是一个非常全面的解决方案,是平台独立的。当然,我无法看到为此创建一个delphi包装(或更新现有的),以获得unicode整理的一个很好的解决方案?

我会很高兴听到两个层面的建议:

A)一个Windows特定的非便携式解决方案,我会很高兴,目前,忘记了客户端服务器的后果!
B)一个更便携的解决方案可以免除unicode api功能的各种XP / vista / win7变体,因此使我在XE2 mac支持和未来的linux支持方面取得了很好的成绩,更不用说客户端服务器的并发症。

Btw我真的不想做’make-do’解决方案,在比较之前扫描字符串并替换某些棘手的字符等,我已经阅读了。我给了上面的德语例证,这只是一个例子,我想让它为所有(或至少大多数,远东,俄语)语言工作,我不想为特定语言或两个语言做出解决方法。我也不需要任何关于排序算法的建议,它们很好,它只是字符串比较位是错误的。

我希望我失踪/做一些愚蠢的事情,这一切都是头痛的。

谢谢。

编辑,鲁迪,这里是我如何调用RtlCompareUnicodeString。对不起,迟到我一直在这个可怕的时间。

program Project26

{$APPTYPE CONSOLE}

uses
  SysUtils;


var
  a,b:ansistring;

  k,l:string;
  x,y:widestring;
  r:integer;

procedure RtlInitUnicodeString(
  DestinationString:pstring;
  SourceString:pwidechar) stdcall; external 'NTDLL';

function RtlCompareUnicodeString(
  String1:pstring;
  String2:pstring;
  CaseInSensitive:boolean
  ):integer stdcall; external 'NTDLL';


begin

  x:='wef';
  y:='fsd';

  RtlInitUnicodeString(@k,pwidechar(x));
  RtlInitUnicodeString(@l,pwidechar(y));

  r:=RtlCompareUnicodeString(@k,@l,false);

  writeln(r);
  readln;

end.

我意识到这很可能是错的,我不习惯直接调用api的行为,这是我最好的猜测。

关于你的StringCompareEx api函数。这看起来真的很好,但仅在Vista上使用,我正在使用XP。 StringCompare是在XP,但这不是Unicode!

要概述,基本任务是比较两个字符串,并根据当前窗口区域设置中指定的字符排序顺序进行比较。

如果ansicomparetext应该做到这一点吗?这对我来说并不奏效,但是有些人说应该这样做,其他我看过的建议应该是这样的。

当在德语区域设置中使用AnsiCompareText时,这是31个测试字符串所得到的(空格分隔 – 没有字符串包含空格): –

>ßßßöööööööööööss ss ss ss ss ss a a a a a a a
Sssbßßssss SSSSßßßssßßSSßßßzßzßz zzz

编辑2。

我还是很想知道如果我应该期望AnsiCompareText使用locale信息工作,就像lkessler所说的那样,lkessler也已经发布了关于这些主题的信息,并且似乎已经通过了这一点。

不过,从Rudy的建议来看,我也一直在检查CompareStringW – 它与CompareString共享相同的文档,所以它不是非Unicode的,如前所述。

即使AnsiCompareText不工作,虽然我认为应该是,win32api函数CompareStringW应该确实有效。现在我已经定义了我的API函数,我可以调用它,我得到一个结果,没有错误…但我得到相同的结果,无论输入字符串!它每次返回1 – 这意味着少于。这是我的代码

var
  k,l:string;

function CompareStringW(
  Locale:integer;
  dwCmpFlags:longword;
  lpString1:pstring;
  cchCount1:integer;
  lpString2:pstring;
  cchCount2:integer
  ):integer stdcall; external 'Kernel32.dll';

begin;

  k:='zzz';
  l:='xxx';

  writeln(length(k));
  r:=comparestringw(LOCALE_USER_DEFAULT,@k,3,3);

  writeln(r); // result is 1=less than,2=equal,3=greater than
  readln;

end;

我觉得我现在有了很多痛苦。很高兴知道AnsiCompareText,而且我在上面的CompareStringW api调用中做错了什么。谢谢。

编辑3

首先,我自己修改了比较字符串的API调用,当我应该做PString(mystring)时,我传递了@mystring。现在这一切都正常工作。

r:=comparestringw(LOCALE_USER_DEFAULT,pstring(k),-1,pstring(l),-1);

现在,我可以想象我的沮丧,当我仍然得到了一样的排序结果,因为我一开始就这样做

>ßßßßßßßßööööööööööss ss ss a a a a a a a a a a
Sssbßßssss SSSSßßßssßßSSßßßzßzßz zzz

当我意识到排序顺序是正确的时候,你也可能会想象我非常沮丧,不要提及同时的快乐,而且它在正确的位置正确地回到了!这使得生病的人说,但是从来没有任何问题,这一切都归功于我缺乏德国的知识。我觉得排序是错误的,因为你可以看到上面的字符串从S开始,然后他们从ß开始,然后再次回到ß等等。那么我不会说德语,但是我仍然可以清楚地看到他们没有被正确排序 – 我的德国朋友告诉我,ß来自S,之前,我错了!发生的是字符串函数(AnsiCompareText和winapi CompareTextW)都使用’ss’替代每个’ß’,并且每个’ö’都具有正常的’o’…所以如果我把这些结果和搜索结果并按照我所描述的替换

>屁股屁股屁股Asss no no o on oo oo ooo ooo op po ss ss ss ss ssss
sss Sssa Sssb ssss ssss SSSS ssssss ssssss SSssss ssz sszss z zzz

对我来说看起来很正确!而且它一直是。

我非常感谢所有的建议,非常抱歉浪费了你这样的时间。那些德国人的ß让我感到困惑,内置delphi功能或其他任何东西都没有错。它只是看起来像那里。在我的测试数据中,我错误地将它们与正常的’组合在一起,任何其他的信都不会产生这种无序排除的错觉!波澜不惊的ß使我看起来很傻! SSS!

Rudy和lkessler我们都特别有帮助,我们都不得不接受lkessler的答案是最正确的,对不起Rudy。

解决方法

尝试使用 CompareStr区分大小写,如果您希望在任何区域设置完全相同,则使用 CompareText不区分大小写。

并且使用AnsiCompareStr区分大小写,如果您希望您的排序特定于用户的区域设置,则使用AnsiCompareText不区分大小写。

有关这方面的更多信息,请参阅:How can I get TStringList to sort differently in Delphi

猜你在找的Delphi相关文章