gpt4 book ai didi

delphi - 如何比较包含非英语字符的unicode字符串以字母顺序排序?

转载 作者:行者123 更新时间:2023-12-03 14:35:14 26 4
gpt4 key购买 nike

我正在尝试根据其中包含非英语字符的unicode字符串值对数组/列表/任何数据进行排序,我希望它们按字母顺序正确排序。

我写了很多代码(D2010,赢得XP),我认为这对于将来的国际化来说是非常可靠的,但事实并非如此。它全部使用unicodestring(string)数据类型,到目前为止,我只是将英文字符放入unicode字符串中。

看来我必须承担一个非常严重的unicode错误。我与我的德国朋友交谈,并尝试了一些德国的ß(ß是'ss',应该在S之后,在字母T之前)和ö's等(请注意变音符号),我的排序算法都不再起作用。结果非常复杂。垃圾。

从那时起,我一直在广泛阅读并学到许多与unicode整理有关的不愉快的事情。事情看起来很严峻,比我预想的要糟糕得多,我已经把事情搞砸了。我希望我错过了一些东西,但事情实际上并没有现在出现的那么严峻。我一直在修补Windows API调用(RtlCompareUnicodeString),但没有成功(保护错误),我无法使其正常工作。我了解到的API调用问题是,它们在各种较新的Windows平台上都会发生变化,并且随着delphi即将跨平台使用,后来在linux下,我的应用程序是客户端服务器,因此我需要担心这一点,但是情况是什么是(不好)我将不胜感激任何前进的进展,即特定于Win API。

是否使用Win API函数RtlCompareUnicodeString来解决问题?如果是这样的话,我真的应该再试一次,但是与Unicode排序规则有关的所有问题让我感到吃惊,无论如何我还是不清楚我应该做些什么来比较这些字符串。

我了解了IBM ICU c ++开源项目,尽管有旧版本的ICU,也有一个delphi包装器。似乎是一个非常全面的解决方案,与平台无关。当然可以,我不能为此目的创建一个delphi包装器(或更新现有的包装器),以获得针对Unicode排序规则的良好解决方案?

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

A)Windows特定的非便携式解决方案,此刻我会很高兴,忘记了客户端服务器的后果!
B)一种更可移植的解决方案,不受unicode api函数的各种XP / vista / win7变体的影响,因此使我在XE2 mac支持和将来的linux支持方面处于有利地位,更不用说客户端服务器的复杂性了。

顺便说一句,我真的不想做“解决方案”解决方案,在比较之前扫描字符串并替换某些我已经读过的棘手字符等。我在上面给出了德语示例,这只是一个例子,我想让它适用于所有(或至少大多数,远东,俄语)语言,我不想针对一两种特定语言进行解决。我也不需要有关排序算法的任何建议,它们很好,只是字符串比较位是错误的。

我希望我想念/做一些愚蠢的事情,这一切看起来都很头疼。

谢谢。



编辑,Rudy,这是我尝试调用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!

回顾一下,进行的基本任务是比较两个字符串,并根据当前Windows区域设置中指定的字符排序顺序进行比较。

谁能肯定地说ansicomparetext是否应该这样做?它对我不起作用,但是其他人说应该这样做,而我读过的其他内容也建议这样做。

这是在德语语言环境中使用AnsiCompareText时使用31个测试字符串得到的结果(以空格分隔-没有字符串包含空格):-


arßAsßasßaßsnonöööönooöööoöoöoööppöss SSßaßßbßsßSßa
Sßbßßssss SSSSßßsssßßSSßßßzßzßz zzz




编辑2。

我仍然很想听听我是否应该期望AnsiCompareText使用语言环境信息来工作,就像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,0,@k,3,@l,3);

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

end;


经历了很多痛苦之后,我觉得自己现在到了某个地方。很高兴了解AnsiCompareText,以及上面的CompareStringW api调用在做什么方面的问题。谢谢。



编辑3

首先,我自己修复了对CompareStringW的api调用,当我应该执行PString(mystring)时,我传入了@mystring。现在一切正常。

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


现在,您可以想象当我仍然获得与刚开始时一样的排序结果时,我会多么沮丧...


arßasßaßsAsßnonöönööööööoööoööppöss SSßaßßbßsßSßa
Sßbßßssss SSSSßßsssßßSSßßßzßzßz zzz


您还可以想象,当我意识到排序顺序是正确的,并且刚开始时是正确的时,我的极端沮丧就不用提同时喜悦了!这么说让我感到不舒服,但一开始从来没有任何问题-这完全归功于我缺乏德语知识。我认为排序是错误的,因为您可以看到上面的字符串以S开头,然后又以ß开头,然后又是s并返回到ß等。好吧,我不会说德语,但是我仍然可以清楚地看到它们的排序不正确-我的德国朋友告诉我ß在S之后,在T之前……我错了!发生的是,字符串函数(AnsiCompareText和winapi CompareTextW)正在用“ ss”替换每个“ß”,并用一个普通的“ o”替换每个“ö” ...因此,如果我将这些结果放在上面并进行搜索并按说明更换我得到...


rs as SS no SS SS SS SS s s s s SS SS SS
sss sss sssb sss ssss SSSS sssss sssss SSssss ssz sszss z zzz


对我来说看起来很正确!而且一直如此。

我非常感谢您提供的所有建议,也非常抱歉浪费您这样的时间。那些德语ß让我感到困惑,内置的delphi函数或其他任何功能都没有错。看起来就像那里。我在测试数据中将它们与普通的's'组合在一起时犯了一个错误,任何其他字母都不会造成这种未排序的错觉!弯曲的ß使我看起来很傻! !

Rudy和lkessler我们都特别乐于助人,无论如何,我必须接受lkessler的回答是最正确的,对不起Rudy。

最佳答案

如果要在任何语言环境中使用完全相同的排序,请尝试使用CompareStr区分大小写,或CompareText区分大小写。

如果希望排序特定于用户的语言环境,请使用AnsiCompareStr区分大小写,或AnsiCompareText区分大小写。

有关更多信息,请参见:How can I get TStringList to sort differently in Delphi

关于delphi - 如何比较包含非英语字符的unicode字符串以字母顺序排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7051323/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com