2012-03-15 34 views
6

Tôi muốn biết cách khai báo một bản ghi, có một số giá trị cố định. Tôi cần gửi dữ liệu bằng mẫu này: Byte($FF)-Byte(0..250)-Byte(0..250). Tôi đang sử dụng record cho điều đó và tôi muốn có giá trị đầu tiên của nó liên tục, để nó không thể được điều sai lầm. Chẳng hạn như:Làm thế nào để khai báo một giá trị cố định trong một bản ghi?

TPacket = record 
    InitByte: byte; // =255, constant 
    FirstVal, 
    SecondVal: byte; 
end; 
+3

Bạn có thể dùng đến subrange loại – OnTheFly

+0

Nếu tất cả các bạn đang làm là giá trị BYTE trong một TPacket, tôi thay vào đó sẽ sử dụng RawByteString và chỉ xác định hằng số có tên InitByte = 0, FIrstVal = 1, v.v. Tôi sẽ đảm bảo rằng giá trị ban đầu là giá trị hằng số chính xác bằng cách thực hiện nó trong CODE trong hàm PacketBuild của tôi. –

+1

Bạn sẽ sử dụng phiên bản Delphi nào? – kobik

Trả lời

12

Bạn không thể dựa vào một constructor vì, trái với Lớp học, hồ sơ không cần phải sử dụng chúng, các nhà xây dựng parameterless mặc định được sử dụng ngầm.

Nhưng bạn có thể sử dụng một lĩnh vực liên tục:

type 
    TPacket = record 
    type 
    TBytish = 0..250; 
    const 
    InitByte : Byte = 255; 
    var 
    FirstVal, 
    SecondVal: TBytish; 
    end; 

Sau đó sử dụng điều này như một thường xuyên ghi, ngoại trừ việc bạn không có (và bạn không thể) thay đổi lĩnh vực InitByte.
FillChar duy trì trường liên tục và hoạt động như mong đợi.

procedure TForm2.FormCreate(Sender: TObject); 
var 
    r: TPacket; 
begin 
    FillChar(r, SizeOf(r), #0); 
    ShowMessage(Format('InitByte = %d, FirstVal = %d, SecondVal = %d', [r.InitByte, r.FirstVal,r.SecondVal])); 
    // r.InitByte := 42; // not allowed by compiler 
    // r.FirstVal := 251; // not allowed by compiler 
    r.FirstVal := 1; 
    r.SecondVal := 2; 
    ShowMessage(Format('InitByte = %d, FirstVal = %d, SecondVal = %d', [r.InitByte, r.FirstVal,r.SecondVal])); 
end; 

Cập nhật để bao gồm các phạm vi loại lồng nhau 0..250

+1

Tuyệt vời. Câu trả lời thực sự đầu tiên. –

+0

@Giống như, gần như vậy. François, bạn đang thiếu khoảng cách giữa 'FirstVal' và' SecondVal'. Nếu tôi làm đúng, chúng phải nằm trong khoảng '0..250'. Nhưng sau đó bạn có thể đáp ứng các vấn đề với 'FillChar' mà có thể thiết lập các giá trị trong giới hạn này (với phạm vi kiểm tra tắt chắc chắn). – TLama

+1

@TLama, tôi đã dựa vào tuyên bố hồ sơ của OP và đã bỏ lỡ phạm vi. Cập nhật câu trả lời với một loại phụ ... –

2

Phiên bản hiện đại của Delphi cho phép phương thức ghi. Trong khi bạn không thể tránh người khác thay đổi lĩnh vực này bạn ít nhất có thể khởi tạo nó đúng cách:

type 
    TPacket = record 
    InitByte: byte; // =255, constant 
    FirstVal, 
    SecondVal: byte; 
    constructor Create(val1, val2 : byte); 
    end; 


constructor TPacket.Create(val1, val2: byte); 
begin 
    InitByte := 255; 
    FirstVal := val1; 
    SecondVal := val2; 
end; 
+1

Thật không may, bạn không thể thực thi việc sử dụng constructor ... –

0

Với thực tế là hồ sơ bây giờ có thể có các thuộc tính, bạn có thể xác định một kỷ lục như:

TMixedFixed = record 
strict private 
    FFixed: byte; 
    FVariable1: byte; 
    FVariable2: byte; 
public 
    property Fixed read FFixed; 
    property Variable read FVariable write FVariable; 
    constructor Create(Var1, Var2: byte); 
end; 

constructor TMixedFixed.create(Var1, Var2: byte); 
begin 
    FFixed:= 255; 
    FVariable1:= Var1; 
    FVariable2:= Var2; 
end; 

Với thực tế là các biến thực là nghiêm ngặt tư nhân bạn không nên có thể chạm vào chúng mà không có phép thuật đặc biệt. Mặc dù vậy, bạn sẽ phải sử dụng hàm tạo để bắt đầu các giá trị 'cố định'.

+0

Nó không ngăn cản khai báo biến và sử dụng nó như một bản ghi chuẩn mà không sử dụng nhà xây dựng. Bạn sẽ chỉ có rác trong 'FFixed' và không có cách nào để thay đổi nó ... –

+0

@ François, bạn không thể overrule constructor mặc định? – Johan

+0

không phải là tôi biết. Hàm khởi tạo mặc định nổi bật đến nỗi nó thậm chí ngăn cản bạn khai báo một hàm tạo parameterless khác. Bất kỳ hàm tạo tùy chỉnh nào mà bạn cung cấp cần phải có (các) tham số. Xem [docwiki] (http://docwiki.embarcadero.com/RADStudio/en/Structured_Types): "Các bản ghi được tạo tự động, sử dụng một hàm tạo không có đối số mặc định, nhưng các lớp phải được xây dựng một cách rõ ràng. Bởi vì các bản ghi có một mặc định là không constructor đối số, bất kỳ hàm tạo bản ghi do người dùng định nghĩa nào phải có một hoặc nhiều tham số. " –

0

Đây là cách đơn giản nhất:

type 
    TPacket = record 
    InitByte: byte; // =255, constant 
    FirstVal, 
    SecondVal: byte; 
    end; 

var 
    Packet : TPacket = (InitByte: 255); 

const 
    Packet1 : TPacket = (InitByte: 255); 
+1

Không, đó không phải là cách duy nhất, xem câu trả lời của tôi.Và, BTW, bạn không thể khởi tạo các biến cục bộ như biến Packet của bạn (lỗi trình biên dịch E2195). –

Các vấn đề liên quan