Delphi XE2中CompareStringW忽略变音符号对比失效求助
Delphi XE2忽略变音符号对比字符串失败的原因及解决办法
可能的问题点:
- 区域设置干扰:你使用的
LOCALE_USER_DEFAULT依赖系统当前区域,部分区域的语言规则中,u和ü可能被视为不同语义的字符,导致即使添加忽略变音符号的标志也无法判定相等。 - 标志位冲突或无效:
NORM_LINGUISTIC_CASING是用于大小写比较的标志,和NORM_IGNORENONSPACE组合使用时可能覆盖或干扰变音符号的忽略逻辑;另外部分系统中LINGUISTIC_IGNOREDIACRITIC的支持存在兼容性问题。 - 字符编码形式异常:如果
ü是以**组合字符(基字符u+单独变音符号)**存储的,而非预组合的单个Unicode字符(U+00FC),你传入的长度参数1会错误截断字符,导致对比失败。
解决方法:
1. 使用中立区域设置避免区域干扰
将区域参数改为LOCALE_INVARIANT,脱离系统区域的规则限制,确保忽略变音符号的逻辑生效:
var CompareResult: Integer; begin CompareResult := CompareStringW(LOCALE_INVARIANT, NORM_IGNORENONSPACE, PChar('u'), 1, PChar('ü'), 1); if CompareResult = CSTR_EQUAL then // 字符串相等逻辑 else // 字符串不等逻辑 end;
2. 先规范化字符串再对比
如果上述方法仍无效,可以先将字符串转换为无变音符号的形式,再直接对比:
function StripDiacritics(const ASource: string): string; var NormalizedStr: string; NormLen, I: Integer; CurrChar: WideChar; begin // 将字符串转换为规范分解形式(基字符与变音符号分离) NormLen := NormalizeString(NormalizationD, PWideChar(ASource), Length(ASource), nil, 0); SetLength(NormalizedStr, NormLen); NormalizeString(NormalizationD, PWideChar(ASource), Length(ASource), PWideChar(NormalizedStr), NormLen); // 过滤掉所有变音符号(Unicode标记字符范围) Result := ''; for I := 1 to NormLen do begin CurrChar := NormalizedStr[I]; if not (CurrChar in [#$0300..#$036F, #$1DC0..#$1DFF, #$20D0..#$20FF, #$FE20..#$FE2F]) then Result := Result + CurrChar; end; end; // 使用示例 if StripDiacritics('u') = StripDiacritics('ü') then ShowMessage('字符串相等');
3. 验证字符长度
检查你的ü是否为单个字符:
ShowMessage(IntToStr(Length('ü'))); // 正常预组合字符返回1,组合字符返回2
如果返回2,说明是组合字符,对比时需要将长度参数改为2:
CompareStringW(LOCALE_INVARIANT, NORM_IGNORENONSPACE, PChar('u'), 1, PChar('ü'), 2);
内容的提问来源于stack exchange,提问作者Wolf Country
相关产品推荐
相关产品推荐

