Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.10.08;
Скачать: CL | DM;

Вниз

Интересный вопрос про типы.   Найти похожие ветки 

 
TrainerOfDolphins ©   (2006-09-20 12:18) [0]

Есть перечисляемый тип:
Type
TSomeType=(val1,val2,val3);
Вопрос:
Есть ли какой-нибудь способ быстро преобразовывать значения val1,val2,val3 в строки ‘val1’,’val2’,’val3’&
Ну скажем некая функция SomeTypeToStr (val: TSomeType):string…
Или только case val of придётся использовать?


 
MBo ©   (2006-09-20 12:20) [1]

uses TypInfo
GetEnumName


 
TrainerOfDolphins ©   (2006-09-20 12:35) [2]

Спасибо. Это уже что-то. А есть такая же? только чтобы на входе был не номер значения, а само значение типа TSomeType?


 
Игорь Шевченко ©   (2006-09-20 12:36) [3]

unit Test;

interface
{$M+}
type
 TFooBar = (fbOne, fbTwo, fbThree, fbFour);

 TFoo = class
 private
   FFooBar: TFooBar;
 published
   property FooBar : TFooBar read FFooBar write FFooBar;
 end;

implementation

end.


unit main;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TForm1 = class(TForm)
   ListBox1: TListBox;
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation
uses
 TypInfo, Test;

{$R *.DFM}

function GetListEnumType(const T: Pointer): TStringList;
var
 i: Byte;
 EnumTypeData: PTypeData;
begin
 // никакой обработки ошибок нет, сделано на скорую руку
 Result := TStringList.Create;
 EnumTypeData := GetTypeData(GetTypeData(PTypeInfo(T))^.BaseType^);
 for i := EnumTypeData^.MinValue to EnumTypeData^.MaxValue do
   Result.Add(GetEnumName(PTypeInfo(T), i))
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 PropInfo : PPropInfo;
begin
 PropInfo := GetPropInfo(TFoo.ClassInfo, "FooBar");
 ListBox1.Items.Assign(GetListEnumType(PropInfo^.PropType^));
end;

end.


 
TrainerOfDolphins ©   (2006-09-20 12:54) [4]

А как узнать количество значений перечисляемого типа?


 
MBo ©   (2006-09-20 12:56) [5]

>только чтобы на входе был не номер значения, а само значение типа TSomeType?

Используй Ord


 
MBo ©   (2006-09-20 12:56) [6]

for i := Low(TPaletteType) to High(TPaletteType) do begin
   s := GetEnumName(TypeInfo(TPaletteType), Integer(i));


 
PZ   (2006-09-20 12:59) [7]

> [3] Игорь Шевченко ©   (20.09.06 12:36)

Я не считаю возможным оспаривать Вас, но мне кажется, что через "case val of" гораздо и гораздо проще.


 
TrainerOfDolphins ©   (2006-09-20 13:05) [8]

to PZ
Но в этом случае придётся для каждого нового типа писать всё заново (хоть и не много). Настоящий нинзя программирования ничего не делает дважды... :)


 
TrainerOfDolphins ©   (2006-09-20 13:11) [9]

то MBo

> for i := Low(TPaletteType) to High(TPaletteType) do begin

На это компилятор ругается. TSomeType - не порядковый тип, а перечисляемый, поэтому невозможно сказать что у него Low, а что High...


 
PZ   (2006-09-20 13:15) [10]

> [8] TrainerOfDolphins ©   (20.09.06 13:05)

Убедил


 
MBo ©   (2006-09-20 13:29) [11]

Ordinal types include integer, character, Boolean, enumerated, and subrange types, так что все работает (для Enumerated types with explicitly assigned ordinality, конечно, нехорошо будет)
Из давно работающего проекта:
 
type
TPaletteType = (ptGray, ptGrayInverse, ptRed, ptGreen, ptBlue, ptYellow,
   ptMagenta, ptAqua, ptBGR, ptQuasiBr, ptCustom);

class procedure TByteFrames.GetPalNames(Names: TStrings);
var
 i: TPaletteType;
begin
 Names.Clear;
 for i := Low(TPaletteType) to High(TPaletteType) do
   Names.Add(GetEnumName(TypeInfo(TPaletteType), Integer(i)));
end;


 
StriderMan ©   (2006-09-20 13:37) [12]


> PZ   (20.09.06 12:59) [7]
> Я не считаю возможным оспаривать Вас, но мне кажется, что
> через "case val of" гораздо и гораздо проще.

я в таких случаях применяю такую конструкцию:

type
 TSomeType = (st1, st2, ... stN);

const
 C_SOME_TYPE_NAMES: array[TSomeType] of string = ("st1,", "st2", ... "stN");


далее понятно:
 SomeName := C_SOME_TYPE_NAMES[stX];


 
TrainerOfDolphins ©   (2006-09-20 13:40) [13]

Пардон, я не оценил всей грациозности этой конструкции. Я определил i:integer, поэтому Делфи и ругалась...


 
TrainerOfDolphins ©   (2006-09-20 13:42) [14]

то StriderMan

> type
>  TSomeType = (st1, st2, ... stN);
>
> const
>  C_SOME_TYPE_NAMES: array[TSomeType] of string = ("st1,",
>  "st2", ... "stN");
>
> далее понятно:
>  SomeName := C_SOME_TYPE_NAMES[stX];

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


 
StriderMan ©   (2006-09-20 13:45) [15]


> TrainerOfDolphins ©   (20.09.06 13:42) [14]
> Но опять же, это нужно делать каждый раз. А основная положительная
> черта программера - лень...

на самом деле редко бывает необходимость получить имя перечисления как оно задано в коде. Разве что для лога. В таком случае конечно однозначно [1].

Но гораздо чаще нужно получить понятное название на русском языке.


 
TrainerOfDolphins ©   (2006-09-20 14:01) [16]

To StriderMan
> Но гораздо чаще нужно получить понятное название на русском
> языке.

Если для русских названий, то твой способ, спору нет, самый короткий. Короче, чем case of...


 
Anatoly Podgoretsky ©   (2006-09-20 14:10) [17]

TrainerOfDolphins ©   (20.09.06 12:54) [4]
Count := Type(High(Type)) - Ord(Low(Type)) + 1


 
TrainerOfDolphins ©   (2006-09-20 14:31) [18]

В результате получилось очень даже не длинно:
Type
TSomeType=( val1,val2,val3);
function TSomeTypeToStr (val: TSomeType):string;
implementation
function TSomeTypeToStr (val: TSomeType):string;
var v: TSomeType;
begin
  for v:=Low(TSomeType) to High(TSomeType) do
  if v=val
  then Result:=GetEnumName(TypeInfo(TCntrlsState),ord(v));
end;


 
MBo ©   (2006-09-20 14:36) [19]

>TrainerOfDolphins ©   (20.09.06 14:31) [18]
Зачем цикл и лишние проверки?


 
TrainerOfDolphins ©   (2006-09-20 14:38) [20]

А теперь как сделать эту функцию универсальной для всех перечисляемых типов? По идее нужно передать в качестве параметра ещё и указатель  на тип. А как же быть тогда с определением типа переменных val i v? variant?
У меня пока ничего путнего не выходит...


 
TrainerOfDolphins ©   (2006-09-20 14:43) [21]


> MBo ©   (20.09.06 14:36) [19]

Туплю... :)
Type
TSomeType=( val1,val2,val3);
function TSomeTypeToStr (val: TSomeType):string;
implementation
function TSomeTypeToStr (val: TSomeType):string;
begin
 Result:=GetEnumName(TypeInfo(TCntrlsState),ord(val));
end;
Ну тогда до неприличия просто...


 
Anatoly Podgoretsky ©   (2006-09-20 14:45) [22]

TrainerOfDolphins ©   (20.09.06 14:31) [18]
И неправильно.


 
Anatoly Podgoretsky ©   (2006-09-20 14:46) [23]

Кстати компилятор должен был предупредить или мы сообщения не читаем или даже более того заблокировали их?


 
TrainerOfDolphins ©   (2006-09-20 14:53) [24]

На какое из сообщений Вы мне советуете обратить внимание? :)
Main.pas(958): Unsafe type "PAnsiChar"
[Warning] Main.pas(960): Unsafe type "PAnsiChar"
[Warning] Main.pas(1615): Unsafe code "@ operator"
[Warning] Main.pas(1615): Unsafe code "@ operator"


 
TrainerOfDolphins ©   (2006-09-20 14:55) [25]

И что не правильно?


 
Anatoly Podgoretsky ©   (2006-09-20 15:15) [26]

На сообщение, что
begin
 for v:=Low(TSomeType) to High(TSomeType) do
 if v=val
 then Result:=GetEnumName(TypeInfo(TCntrlsState),ord(v));
end;

Result may be uninitialized - или что то подобное по смыслу.


 
TrainerOfDolphins ©   (2006-09-20 15:17) [27]


> begin
>  for v:=Low(TSomeType) to High(TSomeType) do
>  if v=val
>  then Result:=GetEnumName(TypeInfo(TCntrlsState),ord(v));
>
> end

Этот код уже не актуален. Смотри [21]



Страницы: 1 вся ветка

Текущий архив: 2006.10.08;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.044 c
2-1158646489
pkm
2006-09-19 10:14
2006.10.08
Объявление массива.


2-1158766989
Image
2006-09-20 19:43
2006.10.08
Кто нибудь знает как сохранить форму вместе со всем содержимым в


2-1158991317
Steep
2006-09-23 10:01
2006.10.08
iso файлы


2-1158325089
misskio
2006-09-15 16:58
2006.10.08
формирование таблицы из выражения Execute


15-1158594576
AntiUser
2006-09-18 19:49
2006.10.08
try ... except аки заглушка