Как я могу использовать WriteLn с типом enum? - PullRequest
7 голосов
/ 16 декабря 2010

Я пытаюсь создать пользовательский тип данных для дней недели, но не могу его написать. Ошибка компилятора говорит об этом:

[Ошибка] hours.dpr (28): недопустимый тип в операторе записи / записи

program hours;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TypeDay = (Sun,Mon,Tue,Wed,Thu,Fri,Sat);

var day: TypeDay;

begin
     for day := Sun to Sat do
     begin
         writeln(day);
     end;
end.

Это в Delphi 7 под Windows.

Ответы [ 4 ]

17 голосов
/ 16 декабря 2010

Вам не нужно писать Ассемблер для этого;TypInfo включает все, что вам нужно для этого (получите строку, связанную с перечисляемым значением).

Этот код:

program hours;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  TypInfo;

type
  TypeDay = (Sun,Mon,Tue,Wed,Thu,Fri,Sat);

var
  day: TypeDay;
  Str:String;

begin
     for day := Sun to Sat do begin
        Str := GetEnumName(TypeInfo(TypeDay),ord(day));
         writeln(Str);
     end;
end.

И это вывод:

alt text

С уважением.

11 голосов
/ 16 декабря 2010

Tom, Writeln не поддерживает Enum в качестве параметра. Вы должны вызвать функцию Ord, чтобы получить порядковое представление. если вы хотите показать имена ваших TypeDay, вы можете написать код, подобный этому.

program hours;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TypeDay     = (Sun,Mon,Tue,Wed,Thu,Fri,Sat);
const
  TypeDayStr  : Array[TypeDay] of string = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');

var day: TypeDay;

begin
     for day := Sun to Sat do
       writeln( Ord(day));

     for day := Sun to Sat do
       writeln( TypeDayStr[day]);

     Readln;
end.
4 голосов
/ 16 декабря 2010

Вы можете использовать RTTI для записи имен перечислений.

Вот оптимизированная функция, которую я написал некоторое время назад:

program hours;

{$APPTYPE CONSOLE}

uses
  SysUtils;

function GetEnumName(aTypeInfo: pointer; aIndex: integer): PShortString;
asm // get enumerate name from RTTI
    or edx,edx
    movzx ecx,byte ptr [eax+1] // +1=TTypeInfo.Name
    mov eax,[eax+ecx+1+9+1] //BaseType
    mov eax,[eax]
    movzx ecx,byte ptr [eax+1]
    lea eax,[eax+ecx+1+9+4+1] // eax=EnumType.BaseType^.EnumType.NameList
    jz @0
@1: movzx ecx,byte ptr [eax]
    dec edx
    lea eax,eax+ecx+1 // next short string
    jnz @1
@0:
end;

type
  TypeDay = (Sun,Mon,Tue,Wed,Thu,Fri,Sat);

var day: TypeDay;

begin
     for day := Sun to Sat do
     begin
         writeln(GetEnumName(TypeInfo(TypeDay),ord(day))^);
     end;
end.

Но учтите, что эта версия не проверяетчто индекс должен быть в диапазоне.

2 голосов
/ 16 декабря 2010

Перечисления не являются строками, поэтому вам необходимо преобразовать их.
Для преобразования вы можете использовать функцию GetEnumName из модуля Delphi TypInfo, как указано на delphi.about.com .

- Йероен

...