简体   繁体   中英

How to convert 'set of char' to 'set of byte' in Delphi

I am new to Delphi. I was trying to compile a sample code using RAD studio and I get a compiler error saying incompatible types. And i see that, the code is trying to assign a variable of type set of Char to another variable of type set of Byte .

Values := ABC.allowedValues;

Here Values is of type set of Byte and allowedValues is of type set of Char .

I could not find a way to do the above conversion.

Very likely (like "almost certainly"), the best solution is to redesign the code. Something is probably not done in the most appropriate way if you do need to do this.

Also, if you are using a new Delphi version (2009 or newer), Char is a two-byte Unicode character, and so there is no such thing as a "true" set of Char , because the base type of a Delphi set must be an ordinal type with at most 256 distinct values. (Two bytes implies 65 536 distinct values.)

Before Delphi 2009, however, Char was indeed a single-byte character; under the hood it was simply a Byte . Today, Char = WideChar while AnsiChar is the old one-byte character type.

So let us assume that you are either using a pre-Unicode Delphi version or that you are actually working with set of AnsiChar . If you write set of Char in a modern Delphi version, the compiler will "helpfully" interpret that as set of AnsiChar and give you a warning .

A "slow" but truly type-safe approach to performing the conversion is as follows:

type
  TCharSet = set of AnsiChar;
  TByteSet = set of Byte;

function SetConvert(ACharSet: TCharSet): TByteSet;
begin
  Result := [];
  for var c in ACharSet do
    Include(Result, Ord(c))
end;

This makes use of inline variables introduced in Delphi 10.3 and for..in loops introduced in Delphi 2005 (?). Pre-10.3, you need to write

function SetConvert(ACharSet: TCharSet): TByteSet;
var
  c: AnsiChar;
begin
  Result := [];
  for c in ACharSet do
    Include(Result, Ord(c))
end;

Finally, your question is strictly speaking not well defined, since you don't specify how you want to map character sets into byte sets. Above, I assume that you want to use the mapping induced by the Ord/Chr mapping between the base types.

Variante A:

uses
  System.SysUtils;

type
  TCharSet = set of AnsiChar;
  TByteSet = set of Byte;

  TMySet=packed record
   case char of
     'A': (a : TCharSet);
     'B': (b : TByteSet);
   end;

 var
  x: TMySet;
  i: integer;
begin
  try
    x.a := ['a', 'z', 'A'..'Z'];
    for i in x.b do
     write(i, ', ');

 except
   on E: Exception do
     Writeln(E.ClassName, ': ', E.Message);
 end;

end.

Variante B:

uses
  System.SysUtils;

type
  TCharSet = set of AnsiChar;
  TByteSet = set of Byte;

var
  a: TCharSet;
  b: TByteSet absolute a;
  i: integer;
begin
  try
    a := ['a', 'z', 'A'..'Z'];
    for i in b do
      write(i, ', ');
  except
   on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM