2016-03-03 131 views
2

如何使用for循環遍歷G1-G4的記錄字段?迭代記錄字段

TrFireGroup = record 
    idx: integer; 
    G1: integer; 
    G2: integer; 
    G3: integer; 
    G4: integer; 
    FGroup: integer; 
    MstIdx: integer; 
    Status: byte; 
    procedure Clear; 
    end; 
+1

總的來說,你沒有。你問來幹什麼?上下文會有幫助。 –

+5

最好的方法 - 將語義上緊密的字段組合到數組'G:array [1..4] Integer;' – MBo

+0

@DavidHeffernan我認爲它會比寫四個肉體更優雅if語句,但我接受你的建議。整個想法從第一次聞起來。 (: – grinner

回答

3

如果你需要維持現有記錄界面結構的兼容性,你可以使用屬性來做到這一點。將值存儲在數組中允許枚舉它們,並且可以使用現有名稱定義屬性以直接以現有方式訪問值。

program Project1;  
{$APPTYPE CONSOLE} 

type 
    TGArray = array[0..3] of integer; 
    TrFireGroup = record 
    private 
     FGArr : TGArray; 
    public 
     idx: integer; 
     FGroup: integer; 
     MstIdx: integer; 
     Status: byte;   
     property G1 : integer read FGArr[0] write FGArr[0]; 
     property G2 : integer read FGArr[1] write FGArr[1]; 
     property G3 : integer read FGArr[2] write FGArr[2]; 
     property G4 : integer read FGArr[3] write FGArr[3]; 
     property GArray : TGArray read FGArr; 
    end; 

var 
    LFireGroup : TrFireGroup; 
    j : integer; 
begin 
    LFireGroup.G1 := 1; 
    LFireGroup.G2 := 3; 
    LFireGroup.G3 := 5; 
    LFireGroup.G4 := 7; 

    for j in LFireGroup.GArray do 
    WriteLn(j);  
    ReadLn; 
end. 

如果需要記錄佈局爲二進制兼容(無論何種原因),你可以放棄一些tidyness和重新安排事物

TrFireGroup = record   
    idx: integer; 
    GArray : TGArray; 
    FGroup: integer; 
    MstIdx: integer; 
    Status: byte; 
    procedure Clear;   
    property G1 : integer read GArray[0] write GArray[0]; 
    property G2 : integer read GArray[1] write GArray[1]; 
    property G3 : integer read GArray[2] write GArray[2]; 
    property G4 : integer read GArray[3] write GArray[3];   
    end; 

離開GArray作爲一個公共領域,您還可以做索引寫入(而這是不可能的,它作爲一個普通的屬性) - 即:

for i := Low(TGArray) to High(TGArray) do 
    LFireGroup.GArray[i] := 2*i; 

另外,如果你可以放棄for/in語義你可以定義數組作爲默認屬性和直接引用記錄:

TrFireGroup = record 
    private 
     FGArr : TGArray; 
     procedure SetG(index:integer; Value:integer); 
     function GetG(index:integer) : integer; 
    public 
     property G1 : integer read FGArr[0] write FGArr[0]; 
     property G2 : integer read FGArr[1] write FGArr[1]; 
     property G3 : integer read FGArr[2] write FGArr[2]; 
     property G4 : integer read FGArr[3] write FGArr[3]; 
     property GArray[index:integer]:integer read GetG write SetG; default; 
    end; 

procedure TrFireGroup.SetG(index:integer; Value:integer); 
begin 
    FGArr[index] := Value; 
end; 

function TrFireGroup.GetG(index: Integer) : integer; 
begin 
    result := FGArr[index]; 
end; 

它可以讓你做的事:

for i := Low(TGArray) to High(TGArray) do 
    LFireGroup[i] := 2*i; 

for i := Low(TGArray) to High(TGArray) do 
    WriteLn(LFireGroup[i]); 
+0

很好的提示你使用的屬性 – fantaghirocco

2

這可能不是一個好主意,但它是可能的。

procedure Test(); 
var 
    i: Integer; 
    rec: TrFireGroup; 
    GPtr: PInteger; 
    value: Integer; 
begin 
    // Initialize rec ... 

    // Get pointer to first G? field 
    GPtr := @rec.G1; 

    // Loop over G fields 
    for i := 0 to 3 do 
    begin 
    // Use value G? field here... 
    // For example: value := GPtr^; 

    // Increment pointer, thus moving it with four bytes. 
    Inc(GPtr); 
    end; 
end; 
  • 首先獲得在拍攝的指針(GPtr)到第一場。

  • 然後,我們通過取消引用指針(GPtr^)來使用該值。

  • 最後,將指針增加到下一個值(Inc(GPtr))。 請注意增量正在將指針移動到所引用類型的大小。

    而且,由於我們使用指向Integer的指針(PInteger),所以Inc將指針移動到SizeOf(Integer),該指針前進到記錄中的下一個字段。

再次,這不是好的做法。

在這種情況下,指針算術是矯枉過正的,除非你在記錄中有數百個字段(這是非常非常罕見的),但如果你真的需要,這是一種方法。

僅供參考,對在Delphi指針和指針運算這裏非常詳細和質量解釋:

+0

謝謝quasoft,但是作爲它不是真的建議我毫不猶豫地接受你的答案什麼是聖潔的方式接受或只是upvote,或沒有他們 – grinner

+0

只接受你認爲是你的案例的正確解決方案的答案Upvote答案是正確的和/或有用的。Downvote答案沒有帶來任何價值,也沒有用處/錯誤。 – quasoft

+0

這種方法'$ ALIGN'不是很敏感麼? –

1

如果你是在最近的Delphi版本,只需要G1的電流值。 .G4(即不寫他們)也可以用這種方法:

var 
    I: Integer; 
    fg: TrFireGroup; 
    arr: TArray<Integer>; 
begin 
    ... 
    arr := [fg.G1, fg.G2, fg.G3, fg.G4]; 
    for I in arr do begin 
    Writeln(I); 
    end; 
    ... 
end; 
1

恕我直言,如果你不需要的二進制兼容性那麼最簡單的方法是使用一個variant record

TrFireGroup = record 
    idx: integer; 
    FGroup: integer; 
    MstIdx: integer; 
    Status: byte; 
    procedure Clear; 
    case Integer of 
    0: (G1: integer; G2: integer; G3: integer; G4: integer); 
    1: (GArr: array[0..3] of integer); 
end; 

這相當於舊的Delphi absolute的關鍵字。陣列和四個G?變量在內存中共享相同的點。