7

Delphi 6 Professional を使用しています。次のように列挙型を宣言する DLL libraty とやり取りしています。

TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2, ENUM4 = $4, ENUM5 = $8, ENUM6 = $10);

ご覧のとおり、初期化された値は連続していません。次のように for ループを使用して型を反復しようとすると:

var
    e: TExtDllEnum;
begin
    for e := Low(TExtToDllEnum) to High(TExtToDllEnum) do
    ... // More code
end;

Delphi は、ループの呼び出しごとに e を 1 ずつインクリメントするため、列挙型のメンバーではない e の数値 (「3」など) が作成され、「範囲外」エラーが発生します。列挙型の有効な値のみを生成する for ループで列挙型を反復するにはどうすればよいですか?

ありがとう。

4

4 に答える 4

13

一連の定数を定義することにより...

type
  TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2, ENUM4 = $4, ENUM5 = $8, ENUM6 = $10);

const
  CExtDllEnumSet = [ENUM1, ENUM2, ENUM3, ENUM4, ENUM5, ENUM6];


var
  e: TExtDllEnum;
begin
  e := Low(TExtDllEnum);
  while e <= High(TExtDllEnum) do
  begin
    if e in CExtDllEnumSet then 
      WriteLn(Ord(e));

    Inc(e);
  end;

  ReadLn;
end.

そしてイテレータとして実装 - ただの楽しみのために...

type
  TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2, ENUM4 = $4, ENUM5 = $8, ENUM6 = $10);
const
  CExtDllEnumSet = [ENUM1, ENUM2, ENUM3, ENUM4, ENUM5, ENUM6];

type
  TMyIterator = class
  private
    FValue: TExtDllEnum;
  public
    constructor Create;
    function Next: TExtDllEnum;
    function HasNext: Boolean;
  end;

  constructor TMyIterator.Create;
  begin
    FValue := Low(TExtDllEnum);
  end;

  function TMyIterator.HasNext: Boolean;
  begin
    Result := FValue <= High(TExtDllEnum);
  end;

  function TMyIterator.Next: TExtDllEnum;
  begin
    Result := FValue;

    repeat
      Inc(FValue);
    until (FValue in CExtDllEnumSet) or (FValue > High(TExtDllEnum))
  end;

var
  MyIterator: TMyIterator;
begin
  MyIterator := TMyIterator.Create;

  while MyIterator.HasNext do
    WriteLn(Ord(MyIterator.Next));

  MyIterator.Free;

  ReadLn;
end.
于 2010-09-28T23:18:11.897 に答える
7

私が覚えている限り、あなたが望むように反復する方法はありません。列挙が頻繁に変更されない場合、回避策として「インデックス配列」を宣言することができます。これにより、必要な方法で反復処理を行うことができます。秘訣は、列挙を反復するのではなく、列挙内の有効な要素に「変換」できるインデックスを反復することです。

コードでアイデアをよりよく説明できると思います:

const
  ExtDllEnumElements = 6;
  EnumIndexArray: array[0..ExtDllEnumElements - 1] of TExtDllEnum = (ENUM1, ENUM2, ENUM3, ENUM4, ENUM5, ENUM6);
var
  I: Integer;
begin
  for I := Low(EnumIndexArray) to High(EnumIndexArray) do
    WhateverYouWantWith(EnumIndexArray[I]);
end;
于 2010-09-28T22:55:55.410 に答える
4

列挙を定義するとき

TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2, ENUM4 = $4, ENUM5 = $8, ENUM6 = $10);

実際には、17 ($10 + 1) の可能な値で構成される列挙型を定義します。それは文書化されています。

割り当てられた列挙定数のみの反復を実装する方法はたくさんありますが (他の回答を参照)、17 個の値を反復処理する方法は変更できません。

ENUM1 を除くすべての ENUMx 値が 2 の累乗であるという事実を使用するもう 1 つの反復例を次に示します。

type
  TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2,
                 ENUM4 = $4, ENUM5 = $8, ENUM6 = $10);
var
    e: TExtDllEnum;

begin
  e:= Low(TExtDllEnum);
  repeat
    [..]
    if e = ENUM1 then e:= ENUM2
    else if e = High(TExtDllEnum) then Break
    else e:= e shl 1;
  until False;
end;
于 2010-09-28T23:13:07.880 に答える
3

できません

値がバイナリで重み付けされている場合は、このような while ループを使用してみてください

var
    e: TExtDllEnum;
begin
    e := 0;
    While e <= High(TExtToDllEnum) do
    begin
        ... // More code
        e := Power(2, e);
    end;

end;
于 2010-09-28T23:04:46.670 に答える