2010-09-28 16 views
7

Tôi đang sử dụng Delphi 6 Professional. Tôi đang giao tiếp với một libraty DLL khai báo một kiểu gõ như sau:Làm thế nào để lặp lại các kiểu liệt kê được khởi tạo với Delphi 6 và tránh lỗi "ngoài giới hạn"?

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

Như bạn có thể thấy các giá trị khởi tạo không tiếp giáp. Nếu tôi cố gắng lặp kiểu sử dụng một vòng lặp for như sau:

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

Delphi vẫn increments e 1 mỗi vòng lặp gọi và do đó tạo ra giá trị số cho e rằng không phải là thành viên của kiểu liệt kê (ví dụ, ' 3 ') và dẫn đến lỗi' ngoài giới hạn '. Làm thế nào tôi có thể lặp lại kiểu liệt kê trong vòng lặp for chỉ tạo ra các giá trị hợp lệ cho kiểu liệt kê?

Cảm ơn.

Trả lời

13

Bằng việc xác định một tập các hằng ...

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. 

và được triển khai dưới dạng trình lặp - chỉ để giải trí ...

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. 
7

Theo như tôi có thể nhớ, không có cách nào để lặp lại theo cách bạn muốn. Nếu điều tra không được thay đổi thường xuyên, một cách giải quyết có thể là khai báo một "mảng chỉ mục", cho phép bạn lặp lại theo cách bạn muốn. Bí quyết là bạn không lặp qua các liệt kê, nhưng theo một chỉ số mà bạn có thể lần lượt "chuyển đổi" tới yếu tố có giá trị trong enum:

Tôi nghĩ rằng tôi có thể giải thích những ý tưởng tốt hơn trong mã:

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; 
3

bạn không thể

nếu các giá trị nhị phân trọng thử sử dụng một vòng lặp while như thế này

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

end; 
4

Khi bạn xác định kiểu liệt kê

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

bạn thực sự xác định loại điều tra bao gồm 17 ($ 10 + 1) giá trị có thể có. Đó là documented.

Có rất nhiều cách để thực hiện phép lặp qua các hằng số liệt kê được chỉ định (xem các câu trả lời khác), nhưng cách bạn thực hiện nó lặp lại 17 giá trị và không thể thay đổi.

Dưới đây là thêm một ví dụ lặp sử dụng thực tế là tất cả các giá trị ENUMx trừ ENUM1 là lũy thừa của 2:

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; 
Các vấn đề liên quan