希望高手帮忙,一个绝对难度之问题。(100分)

T

threego

Unregistered / Unconfirmed
GUEST, unregistred user!
能否设计一个有不同数目参数的数据结构。可能说得不是很清楚。举个例子:我设计了
一个记录数组(RECORD),里面想带有一个数组,可是我又不想让数组的大小固定,
如何设计该结构??
另外,是否有更好的方法将此记录数组存入数据文件中(不是数据库文件)。

干脆我再说得细一点。我正在编一个控制系统仿真软件。
我想设计一个控件。当双击该控件时能弹出参数窗口(是在运行中)
而该控件可以在运行期间动态生成,并且根据其分类(我设计它有一属性MYCLASS,用此
来分类),而有不同的参数。而且这些控件在运行生成后能联接起来(我已解决),并
存成文件以便下次调用。
其中难点在于:该控件所带的不同的参数如何设计其数据结构,又如何将其存入文件中。
我原来想用动态数组或指针,可是这就加大了存入文件中的难度(因其长度和结构不同)
到底如何才能两全其美,真是难。希望高手帮忙。
 
L

LanFairy

Unregistered / Unconfirmed
GUEST, unregistred user!
我想用动态数组还是不错的,因为你的参数不固定。
存入文件你可以
for i = low(myaray) to high(myarray)do
begin
写入文件
end;

程序启动时根据文件中记录个数设置动态数据长度。不知道我理解的对不对
 
T

threego

Unregistered / Unconfirmed
GUEST, unregistred user!
可是也要考虑到从文件中读出各控件后放到什么样的数据结构中合适呢??对吧。
读出后能随时调用,我就不用老读文件了吧。我目前是放到一个RECORD中然后再将各个
控件合到STRINGS中,这样比较方便。不过不清楚如果用上动态数组后怎么办??
望不啬赐答。
 
G

gzpbx

Unregistered / Unconfirmed
GUEST, unregistred user!
动态的我没试过,静态的应该没问题。
Ttemp = record:
x: integer;
ch: char;
st: string[4];
bool: boolean;
end;
var
a: array[1..100] of Ttemp;
F: file of Ttemp;
i: Integer;
begin
//初始化!
AssignFile(F, FileName);
Reset(F);
for i := 1 to 100do
read(F,a);
CloseFile(F);
end;
 
P

proman

Unregistered / Unconfirmed
GUEST, unregistred user!
我的意见是使用可变记录:
type ttmp
x:integer;
case of integer
1:(content:string);
2:(content:integer);
end;
写入文件可以使用tfilestream.可变部分单独存成一个文件。只在前面的记录中记录其起始
位置以及长度。
 
T

threego

Unregistered / Unconfirmed
GUEST, unregistred user!
静态的我已经可以解决。关键是静态不能解决大问题,我总不能把数组定得大大的
这样太浪费空间,又显示不出水平。
楼上的关于可变记录和TFILESTREAM可以说得详细一些吗。比较感兴趣知道。
多谢了。
 
P

proman

Unregistered / Unconfirmed
GUEST, unregistred user!
我再讲一遍,比较烦。
比如我们定一个可变记录如下:
type ttmp
ID:integer;
Pstart:integer;你的可变参数在文件中的位置
Plength:integer;在文件中参数的长度
tType:integer;类型
case of integer
1:(content:Tpen);比如是1时是一种结构
2:(content:Tbrush);2时是加一种结构
end;
你用了tfilestream写两个文件,第一个文件用来保存上面的记录,第二个文件用来保
存你的可变参数,但要在第一个文件的记录中保存它的参数在第二个文件中的起始位置和
长度。这样当你想读出来时,就可以根据第一个文件中的记录进行读取了。应该 没有问题,
而且速度很快。读第一个文件时是很简单的,回为是定长的结构,所以每次读一个结构出来
是没有问题的。
 
T

threego

Unregistered / Unconfirmed
GUEST, unregistred user!
可这样不是不能用RECORD格式的文件来存取了吗。我在程序中是用RECORD文件来进行存取的
能不能再想想办法。多谢了。
帮得上我,加多点分也无所谓呀。
 
G

gzpbx

Unregistered / Unconfirmed
GUEST, unregistred user!
你的问题要求太高了。
据我所知,record之所以能存在文件里,就是因为它的结构是固定的,
程序会自动的分配位置给它存进去!
对于你的问题我只能想到两种解决方案:
1、就像上边那个人所说的那样,定动态record,自己设定向文件里存数据的格式(协议)
2、定义想我写的静态record,多加几个参数,如果多了就用多个record存一个数据节点
你想全自动看来不太现实!
 
T

threego

Unregistered / Unconfirmed
GUEST, unregistred user!
其实我想结构倒是可以定的,我可定为如下。
type ttmp
ID:integer;
.....
data:array of array integer;
.....
end;

就差那个DATA数组难办,其它的结构还是固定的。再请高手想法。
 
G

gzpbx

Unregistered / Unconfirmed
GUEST, unregistred user!
由于你这个二维数组是动态的,无论你往那里存,
都得有你自己定格式,你也可以把那个record它存在两个文件里,
一个存动态一个存动态,自己规定动态的存储协议!
data:array of array integer;
 
S

Sachow

Unregistered / Unconfirmed
GUEST, unregistred user!
(也许我对你的问题的理解有点偏差)
我认为用动态数组定义固定结构比用固定结构定义动态数组要好。
例:
TXtemp = record
Type: Byte;
ID: Integer;
Size: Integer;
end;
//此结构的大小是固定的
XtempArr: array of TXtemp;
//但动态数组的元素却是不定的
至于XtempArr的长度嘛,再由一个整型变量标识就可以了,这样很容易获取到你需要的
信息,而如果你的结构里定义了一个动态数组的话:
TXtemp = record
Type: Byte;
ID: Integer;
Size: Integer;
Special: array of Integer;
//动态数组,哇,同一种TXtemp数据类型的实际大小却会不一样,可怕!
end;
后者在理论上是可行的,但在实际使用当用却会有很多的不便,主要问题就是出在难以确定
结构的大小上面。我们知道,当你要把某些数据写入文件或从文件中读出的时候,最关键的
一点就是要确定读写的Count值,而如果你要读写的数据类型的尺寸是不定的话,又怎么能
确定读写的Count值呢?如果你不能通过SizeOf()来获取该数据类型的真实尺寸的话,要花
费的精力就太多了。
 
C

creation-zy

Unregistered / Unconfirmed
GUEST, unregistred user!
建议用两个文件来存放数据:
一个用于存放固定部分的信息(包括Type、ID、Size),另一个用于存放变长的信息,就像主从数据表一样。
这样的话信息定位十分简单(只要累加即可,如果还嫌麻烦,可以在固定信息中加入起始位置一项)。
实际上这两个文件可以作为同一个文件的两个部分——就像exe文件的数据段和代码段一样。
至于在内存中的表示,建议采用楼上的在结构里定义一个动态数组的方案。
 
G

gzpbx

Unregistered / Unconfirmed
GUEST, unregistred user!
我遇楼上的的意思想同
 
P

proman

Unregistered / Unconfirmed
GUEST, unregistred user!
我再讲一遍,比较烦。
比如我们定一个可变记录如下:
type ttmp
ID:integer;
Pstart:integer;你的可变参数在文件中的位置
Plength:integer;在文件中参数的长度
tType:integer;类型
case of integer
1:(content:Tpen);比如是1时是一种结构
2:(content:Tbrush);2时是加一种结构
end;
你用了tfilestream写两个文件,第一个文件用来保存上面的记录,第二个文件用来保
存你的可变参数,但要在第一个文件的记录中保存它的参数在第二个文件中的起始位置和
长度。这样当你想读出来时,就可以根据第一个文件中的记录进行读取了。应该 没有问题,
而且速度很快。读第一个文件时是很简单的,回为是定长的结构,所以每次读一个结构出来
是没有问题的。
我说的这个方法是没有问题的,我经常用,速度很快,读起来也很方便。在存数据时,数据
全部在内存里,写到硬盘上时,直接写到文件里,可以用各种方法。我通常用tfilestream.
很方便,同样另一个文件也这样写。
读时,首先把这两个文件都载入Tfilestream中,然后定义一个数组,数组的元素为我们上面定
义的结构,由于这个结构是定长的,所以我们可以用文件的尺寸除以结构的长度得出数组的
长度,然后用一句话就可以读出所有的结构到数组中:
tfilestream.read(array[0],tfilestream.size);
然后根据这个数组中的结构的数据,也就是可变参数在另一个文件中的pstart和length
到另一个文件中去读数据,也可以读到另一个数组中。这样你明白了吧,可惜我的例子太复
杂,要不给你看看你就明白了。
 
W

wuyi

Unregistered / Unconfirmed
GUEST, unregistred user!
记录中用指针指向动态数组,动态数据另外保存,就象DBF的备注文件一样。
 
T

threego

Unregistered / Unconfirmed
GUEST, unregistred user!
多谢大家的帮助。另外请PAROMAN同志能否将你的源码发给我,让我好好参考一下。
非常的多谢,虽然我知道这样会让你很麻烦。不过,我对此真的很不清楚,正是我的
弱项,所以很抱歉。再次多谢。
 
P

proman

Unregistered / Unconfirmed
GUEST, unregistred user!
怎么给你呢,把你的EMAIL给我,我整理出来给你。
 
T

threego

Unregistered / Unconfirmed
GUEST, unregistred user!
doumailbox@21cn.com,thanks.
 
顶部