Record类型的复制 ( 积分: 100 )

  • 主题发起人 主题发起人 RJU
  • 开始时间 开始时间
R

RJU

Unregistered / Unconfirmed
GUEST, unregistred user!
请教:
一个自定义类型如下
TMYTYPE=Rrecord
a:array of string;
b:array of Integer

end;

Var
MyA,MyB:TMYTYPE;
直接的复制myb:=myA,会出错,
如果用MyB.a;=MYA.a这种赋值方法在record成员多而且复杂(例如a 的类型是另一个record的数组)的时候是非常麻烦的,并且每次修改record,复制的方法都要修改,很容易造成错误。
各位对于这种情况有什么好的解决方法?
 
请教:
一个自定义类型如下
TMYTYPE=Rrecord
a:array of string;
b:array of Integer

end;

Var
MyA,MyB:TMYTYPE;
直接的复制myb:=myA,会出错,
如果用MyB.a;=MYA.a这种赋值方法在record成员多而且复杂(例如a 的类型是另一个record的数组)的时候是非常麻烦的,并且每次修改record,复制的方法都要修改,很容易造成错误。
各位对于这种情况有什么好的解决方法?
 
如果楼主用的是2006,可以使用操作符重载,很容易就解决这个问题。如果用的是D7,由于你的record类型都是array of的,说明实际上a和b都是指针,复制的时候,直接MyA:=MyB,a和b都是指针复制,数据共享了,所以出错。指针类型请慎重。好像没别的好办法。
 
myb:=myA
可以直接赋值的阿。
D7 XP下试过
 
type
TMYTYPE=Record
a:array of string;
b:array of Integer;
end;


var
Form1: TForm1;
MyA,MyB:TMYTYPE;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
with mya do
begin
setlength(a,100);
a[0]:='100';
a[1]:='1000';
end;
myb:=myA;
showmessage(myb.a[0]);
end;
 
zqw0117:我用的是DELPHI7,如果不用record,应该怎样用比较好?

ic:这时候如果你myb.a[0]:='2';那么mya.a[0]也会变成2的。
 
如果是D7估计得自己定义几个方法来复制了,例如
procedure CopyMyRecord(const Source: TMyRecord
var Dest: TMyRecord);
begin
Dest.a := Source.a;
Dest.b := Source.b;
end;
不过因为你的a和b都是array,那么这段代码好像不行。得在给Dest分配之前,用SetLength设定A的长度,然后在循环读取Source.A.例如
SetLength(Dest.A, Length(Srouce.A));
for I := Low(Source.A) to High(Source.A) do
Dest.A := Source.A;
这样完成赋值。您试试看。
 
但是显然,你的源代码里面就不能再写
MyA := MyB了,得换成
CopyMyRecord(MyB, MyA);
这样的了。
 
一个Move就能解决呀

TRec = record
Name: string[12];
Age: integer;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
R1, R2: TRec;
begin
R1.Name := 'corinth';
R1.Age := 12;
Move(R1, R2, Sizeof(TRec));
ShowMessage(R2.Name);
end;
 
zqw0117:我现在痛苦的地方就是在这里,我的record得子成员很复杂,而且有很多这样的record, 逐个赋值实在麻烦而且很容易出错,每次修改一个record都要重新修改赋值。
我想知道有没有方便的方法
 
to Corinth
您这样的record根本就不用move,直接r1 := r2就可以了。楼主的record是array of哦。
 
to RJU
呵呵,那就真的只有操作符重载能解决这个问题了,可惜D7不支持
 
用指针或许可以解决:
type
PTrlRec=^TrlRec;
TrlRec = record
Name:string;
Age:Integer;
end;
procedure CopyMyRecord(Source,Dest:PTrlRec);
begin
Move(Source^,Dest^,SizeOf(TrlRec));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
a,b:TrlRec;
begin
a.Name :='wrltest';
a.Age :=21;
CopyMyRecord(@a,@b);
edit1.text:=b.Name;
edit2.Text :=inttostr(b.Age);
end;
 
unit Unit1;
// 已經測試不會出錯。
interface

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

type
TMYTYPE = record
a:array of string;
b:array of Integer

end;

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

var
Form1: TForm1;
MyA,MyB:TMYTYPE;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
MyA:=MyB;
end;

end.
 
bbscom:MyA:=MyB的结果是mya和myb是指向同一个地址...,不是出错,是这两个变量指向同一个地方

wrl_001:看一下move得实现,应该是可以的,但我在测试中仍然是mya.[0]改变的时候,myb.[0]也跟着改变,不知道是为什么。
 
move拷贝了mya的值过来,但是,请你注意,关键问题就在array of,这是一个数组,数组永远是指针!动态数组的拷贝只拷贝指针,不信你用SizeOf(mya)看看,应该是8个字节。无论你给a和b赋值多少数据,这个字节永远不便,所以你move过来的还是指针!
 
如果必须用动态数组的话,只能是像 zqw0117 说的那样写一个 CopyMyRecord 函数实现复制。Record 的成员声明成定长数组的话是可以直接复制的。
TMYTYPE = packed Record
a: array[0..1] of string;
b: array[0..1] of Integer;
end;
 
CopyMyRecord 函数
 
抱歉,没看清题目就乱答,正如zqw0117所说的,array of声明的动态数组是一个指针,Move的也只是指针地址.

看来是没有一劳永逸的办法了,写一个函数专门复制这种类型,麻烦点,但由于这个导致出错的几率应该不大吧.
 
有倒是有办法解决,用操作符重载,但是只有2005、2006支持,D7 不支持,所以,唉,只能用我的那个CopyMyRecord这种方案了。
 
后退
顶部