一个含有动态数组的结构体的问题(100分)

  • 主题发起人 主题发起人 wystrim
  • 开始时间 开始时间
W

wystrim

Unregistered / Unconfirmed
GUEST, unregistred user!
我有一程序,其中有部分功能保存保存数据,数据类型是一个含有动态数组的结构体。
type
TSeq=Record
Name:String[20];
Number:Integer;
Describe:String[20];
Value:array of real;
end;
程序中定义了全局变量:
seq1,seq2:Tseq;
通过seq1,将数据存为文件;而seq2则为读取文件中的数据时使用。
调试过程发现这样的问题:
1:用sizeof()得到seq1,seq2的长度不管在其有没有付值都不变,长度不等于46(21+4+21)
后发现在不同类型变量之间存在间隙,但不知道为什么??
2:在程序启动以后,若对seq1付值过,则用seq2读取数据时得到正确的数据(seq2中动态部
分未给定长度);若未对seq1付值,而直接用seq2读取文件中的数据(seq2中的动态数组即使
给定长度),读出的数据也是错误的,很是迷惑。程序上seq1和seq2没有任何联系。


那位大虾若能解决问题,给200分,谢谢了。
 
type
TSeq=<font color = #ff0000><strong>Packed</font></strong> Record
Name:String[20]
// 如果不加 Packed ,21 个 char 在存储时会实际占用 24 个 Byte ,这是由于字节对齐的原因
Number:Integer

Describe:String[20]
// 同上
Value:array of real
// Value 只是一个指针,不论你 SetLength 多少,其 Size 总是 4
end;
所以你原来的结果应该是 56,定义成 Packed Record 后成了 50 。
 
哦,原来是这么回事情,谢了
另一个问题还需继续请教。
 
BaKuBaKu说得也有道理,正如在一个全局引用单元中定义的两个函数的同名变量,
如果其中一个已作赋值处理,也将引致该变量在另外一个函数中起作用(如Result变量),因为该
函数所在单元是一个全局单元(也称无窗体单元,程序设计时常用来放入一些通用的
字符处理、数值处理等的函数或过程),例如:

function Demo1: string;
var
szName: string;
begin
Result := '';
......
end;

function Demo2: string;
var
szName: string;
begin
Result := '';
.....
end;
所以要在函数开始时对Result := ''进行赋值.
 
那如何对动态数组进行预设值呢??
 
To wystrim :
你的问题只在于你保存的格式,动态数组保存到文件必须首先保存它的长度,再依次保
存各个元素,读出的时候首先读出数组长度,然后设置内存中数组的长度,再依次读取元
素,最好使用 TFileStream。

To favinc : 我不知道你在说什么。

你是说下面的写法,如果 Demo2 不对 Result 赋置,那么执行 Demo1 后 Demo2 的值也会 = 'ASDF' ?
function Demo1: string;
begin
Result := 'ASDF';
end;

function Demo2: string;
begin
end;
 
To BaKuBaKu
能不能具体一点,写点程序让我看看,到底怎么样的。
 
procedure Write;
var Stream: TFileStream;
Seq: TSeq;
Len: Integer;
begin
Stream.Write(Seq.Name[1], 20);
Stream.Write(Seq.Number, SizeOf(Number));
Stream.Write(Seq.Describe[1], 20);
Len := Length(Value);
Stream.Write(Len, SizeOf(Len))
// 保存元素个数
for I:=0 to Len do Stream.Write(Value, SizeOf(Value)
// 依次保存每个元素
end;

procedure Read;
var Stream: TFileStream;
Seq: TSeq;
Len: Integer;
begin
Stream.Read(Seq.Name[1], 20);
Stream.Read(Seq.Number, SizeOf(Number));
Stream.Read(Seq.Describe[1], 20);
Stream.Read(Len, SizeOf(Integer))
// 读出元素个数
SetLength(Seq.Value, Len)
// 读出元素个数后申请足够的空间以容纳将要读出的数据
for I:=0 to Len do Stream.Read(Value, SizeOf(Value)
// 依次读取每个元素
end;

流程就是这样,但是关于固定长度字符串的流读写操作传入参数时是传第一个元素还是传
变量本身不太记得了,可能要稍微修改一下。
 
多人接受答案了。
 
后退
顶部