如何通过索引访问 WideString 的字符?

4

我有以下代码片段,无法编译:

procedure Frob(const Grob: WideString);
var
   s: WideString;
begin
   s := 
       Grob[7]+Grob[8]+Grob[5]+Grob[6]+Grob[3]+Grob[4]+Grob[1]+Grob[2];
   ...
end;

Delphi5 报错 不兼容的类型

我试着简化它:

s := Grob[7]; 

它是有效的,还有:
s := Grob[7]+Grob[8];

这可能是因为 WideString[index] 没有返回 WideChar

我尝试将所有内容强制转换为 WideChars:

s := WideChar(Grob[7])+WideChar(Grob[8]);

但这也失败了:

不兼容类型

脚注

  • 5:Delphi 5
3个回答

10

在您的情况下,更简单和更快的方法是以下代码:

procedure Frob(const Grob: WideString);
var
   s: WideString;
begin
  SetLength(s,8);
  s[1] := Grob[7];
  s[2] := Grob[8];
  s[3] := Grob[5];
  s[4] := Grob[6];
  s[5] := Grob[3];
  s[6] := Grob[4];
  s[7] := Grob[1];
  s[8] := Grob[2];
   ...
end;

使用WideString(Grob[7])+WideString(Grob[8])表达式可以运行(它规避了Delphi 5的一个错误,即您无法从WideChars的连接创建WideString),但速度要慢得多。

创建WideString非常缓慢:它不使用Delphi内存分配器,而是使用由Windows提供的BSTR内存分配器(用于OLE),这非常慢。


如果程序预计永远不会处理需要使用两个连续的16位值进行编码的字符文本(UCS-2和UTF-16之间的关键区别),那么这将是最好的答案,所以你得到了我的投票。为了满足它应该的情况,可以使用CharNextW函数,但我个人会使用VBScript_RegExp_TLB并用“^(.{4})(.{4})$”替换为“$2$1”。 - Stijn Sanders
这是个好主意,我可能会改变代码以符合此 - 但我仍然要选择Andreas的答案; 因为它解释了为什么它不起作用。虽然你提供了“如何使其更好”的建议。 - Ian Boyd
@IanBoyd 是的,我编辑了答案来讲述 Delphi 5 的错误。 - Arnaud Bouchez
@StijnSanders 它与s := WideString(Grob[7])+WideString(Grob[8])相同。你说得对,WideChar不一定是一个Unicode字形:不仅在BMP区域之外,而且当文本使用变音符号编码时也是如此 - 请参见关于UTF-8和UTF-16比较的这个长(喷子?)线程:Unicode并不容易使用!但OP的问题不是关于这个事实的,而是关于编译问题以及如何在给定文本中交换字符(用于加密?),无论它每个字形有一个还是两个WideChar。 - Arnaud Bouchez

7

Grob[7]是一个WideChar,这不是问题所在。

问题似乎在于+运算符无法作用于宽字符。但它可以作用于宽字符串,并且任何宽字符都可以转换为宽字符串:

S := WideString(Grob[7]) + WideString(Grob[8]);

1
当你比我先完成时,我正在输入这个..在这个问题中有一个很好的讨论。 - Geoff
在我的情况下,由于我正在将一个来自“Active Directory表示”的GUID字符串转换为COM表示,所以将其分配给普通字符串,然后再转换为WideString可能会更快。 - Ian Boyd
1
@Geoff 那是我的问题! - Ian Boyd
@IanBoyd - 我刚意识到这是你的!惊讶你不得不问两次;-) - Geoff
@Geoff 嗯,这是不同的;我发誓!那个是关于追加漂亮的花哨的WideChars。在这里,我正在处理已经存在于字符串中的普通字符。但我在那里测试了我的解决方案,在这里也适用。 - Ian Boyd

4

正如Geoff在我之前提出的有关Delphi中WideString奇怪问题的另一个问题中指出的那样,我随机尝试了那里的解决方案:

procedure Frob(const Grob: WideString);
var
   s: WideString;
const
   n: WideString = ''; //n=nothing
begin
   s := 
      n+Grob[7]+Grob[8]+Grob[5]+Grob[6]+Grob[3]+Grob[4]+Grob[1]+Grob[2];
end;

它可行。Delphi 不确定 WideString[index] 的类型,所以我必须加强它。


1
好的,看起来 WideString + WideStringWideString + WideChar 是可以的(当然,无论哪种情况下结果都是一个 WideString),但是 WideChar + WideChar 是不允许的。 - Andreas Rejbrand
在Geoff链接的问题中,有一些非常奇怪的情况,无法解释。@DavidHeffernan和我会把这归咎于Delphi 5,因为WideString支持还处于起步阶段,不是所有问题都得到了解决。我相信在Delphi XE 2中一切都能正常工作。 - Ian Boyd
如果 WideChar + WideChar 是 WideString,那就不会与 UnicodeString 兼容。看起来这是一个非常有远见的决定。 - David Heffernan
具有或展现出在事件发生前的知识的“pre·scient”(/ˈpreSH(ē)ənt/)形容词。 - Ian Boyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接