4

i have the following code snippit that won't compile:

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 complains Incompatible types.

i tried simplifying it down to:

s := Grob[7]; 

which works, and:

s := Grob[7]+Grob[8];

which does not.

i can only assume that WideString[index] does not return a WideChar.

i tried forcing things to be WideChars:

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

But that also fails:

Incompatible types

Footnotes

  • 5: Delphi 5
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219

3 Answers3

10

The easier, and faster, in your case, is the following code:

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;

Using a WideString(Grob[7])+WideString(Grob[8]) expression will work (it circumvent the Delphi 5 bug by which you can't make a WideString from a concatenation of WideChars), but is much slower.

Creation of a WideString is very slow: it does not use the Delphi memory allocator, but the BSTR memory allocator supplied by Windows (for OLE), which is damn slow.

Arnaud Bouchez
  • 42,305
  • 3
  • 71
  • 159
  • *If* the program is expected to never handle text with characters that need to be encoded with two consecutive 16-bits values (a key difference between UCS-2 and UTF-16), this would be the best answer, so you get my vote. To cater for when it should, one could use the CharNextW function, but I personally would use VBScript_RegExp_TLB and replace '^(.{4})(.{4})$' with '$2$1'. – Stijn Sanders May 03 '12 at 19:58
  • That's a great idea, and i might change the code to that - but i'm still going to have to go with Andreas's answer; as it explains *why* it's not working. While you have "how to make it better". – Ian Boyd May 03 '12 at 20:53
  • @IanBoyd Yes, I edited the answer to talk about the Delphi 5 bug. – Arnaud Bouchez May 04 '12 at 06:38
  • @StijnSanders It will be the same with `s := WideString(Grob[7])+WideString(Grob[8])`. You are wright about the fact that a `WideChar` is not necessary one Unicode glyph: not only outside the BMP area, but also when the text is encoded with diacritics - see [this long (trolling?) thread about UTF-8 and UTF-16 comparison](https://forums.embarcadero.com//thread.jspa?threadID=71190): Unicode is not easy to use! But the OP question was not about this fact, it was about compiling issue and how to swap characters within a given text (for encryption?), whatever it has one or two WideChar per glyph. – Arnaud Bouchez May 04 '12 at 06:44
7

Grob[7] is a WideChar; that's not the issue.

The issue seems to be that the + operator cannot act on wide chars. But it can act on wide strings, and any wide char can be cast to a wide string:

S := WideString(Grob[7]) + WideString(Grob[8]);
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • 1
    I was in the middle of typing this when you beat me to it.. there's a good discussion in [this question](http://stackoverflow.com/questions/7029274/how-do-i-construct-a-widestring-with-a-diacratic-in-a-non-unicode-delphi-version) – Geoff May 03 '12 at 18:34
  • In my case, since i am converting a guid string from "Active Directory representation" to COM representation, it will likely be faster to assign it to a regular string, then back to a WideString. – Ian Boyd May 03 '12 at 18:35
  • 1
    @Geoff That was *my* question! – Ian Boyd May 03 '12 at 18:35
  • @IanBoyd - I just realised it was yours! Surprised you had to ask it twice ;-) – Geoff May 03 '12 at 18:35
  • @Geoff Well it's different; i swear! That was about appending pretty fancyschmancy `WideChars`. Here i'm dealing with plain old characters already in a string. But i tested my solution there, and it works here. – Ian Boyd May 03 '12 at 18:37
4

As Geoff pointed out my other question dealing with WideString weirdness in Delphi, i randomly tried my solution from there:

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;

And it works. Delphi is confused about what type a WideString[index] in, so i have to beat it over the head.

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • 1
    OK, so it seems like `WideString + WideString` and `WideString + WideChar` are OK (the result in either case, of course, is a `WideString`), but `WideChar + WideChar` is not allowed. – Andreas Rejbrand May 03 '12 at 18:40
  • In the question Geoff linked where was some extraordinarily strange cases that defy all explanation. @DavidHeffernan and i will chalk that up to it being Delphi 5, and WideString support was in its infancy; not all the kinks were worked out. i'm sure it all works fine in Delphi XE 2 – Ian Boyd May 03 '12 at 18:43
  • If WideChar + WideChar was WideString then that would not have played well with UnicodeString. Looks like a very prescient decision. – David Heffernan May 03 '12 at 18:54
  • **pre·scient** `/ˈpreSH(ē)ənt/` *Adjective:* Having or showing knowledge of events before they take place. – Ian Boyd May 03 '12 at 20:54