检查记录数组中的空间是不是空闲
Posted
技术标签:
【中文标题】检查记录数组中的空间是不是空闲【英文标题】:Check if a space in an Array of records is free检查记录数组中的空间是否空闲 【发布时间】:2014-01-19 14:30:21 【问题描述】:我正在为我的课程在 Delphi 中编写一个数据库,但遇到了一个问题。
UserRecord = record
Forename : string[20];
Surname : string[20];
Username : string[20];
Password : string[20];
gender : boolean;
end;
var
User : UserRecord;
NewUserForm: TNewUserForm;
UserFile : file of UserRecord;
UserArray : array[1..20] of UserRecord;
这是我的代码的精简版本,我希望能够将记录“UserRecord”保存到数组 UserArray 中,这是一件简单的事情,但是如果第一个已经有一个“用户”我的数组的入口点,它将覆盖它。我需要找到一种方法来检查数组以找到数组中的一个空点,这样我就可以将它保存在那里而不是不断地覆盖第一个入口点。
【问题讨论】:
不要使用固定长度的数组。使用TList<UserRecord>
的动态数组。不要使用短字符串。使用string
。另外,性别不是Boolean
!!!
当您使用file of record
时,您应该将您的记录声明为packed
,否则您将节省填充垃圾。
哦,别再使用记录文件了!
@DavidHeffernan 除非有库存TFileStream<T>
有时它可能是一个相当不错的概念。虽然只有 20 个元素,我更喜欢 blockread
全部。 OTOH,这可能是那些只教授旧的 Wirth-Pascal 风格的课程。
不要列出给大卫,否则你的课程作业会失败:-P
【参考方案1】:
function AddUserRecord(ARecord: UserRecord; var AUserArray: array of UserRecord): integer;
var
EmptyRecord: UserRecord;
I: Integer;
begin
ZeroMemory(@EmptyRecord, SizeOf(UserRecord));
Result := -1;
for I := Low(AUserArray) to High(AUserArray) do
//Compare with an empty record
if CompareMem(@EmptyRecord, @AUserArray[I], SizeOf(UserRecord)) then
begin
AUserArray[I] := ARecord;
Result := I;
Exit;
end;
end;
procedure Test;
var
UserArray : array[1..20] of UserRecord;
User : UserRecord;
begin
//initialize record array
ZeroMemory(@UserArray, SizeOf(UserArray));
//Your logic to fill the record
//ZeroMemory(@User, SizeOf(UserRecord));
//User.Username := 'X';
AddUserRecord(User, UserArray);
end;
【讨论】:
隐式假设而不是显式值...可能有一天会咬人。另外,如果您使用Exit(value)
,那么您必须使用相当现代的Delphi,然后您可能可以比较记录而不是回退到CompareMemory
再次是的,假设这不是最好的方法并且您的答案很可靠,他说这是来自“课程作业”的错误,所以我猜他无法更改记录。所以是的,你的更好:) 但我的适用于这种情况
课程过时,有时就像一张愚蠢的彩票,什么可以改变,什么不能改变。
@Arioch'比较记录需要运算符重载【参考方案2】:
如果您想知道该行是否已填充或为空,添加显式标志的最佳方法是,您可以使用该标志来标记已删除行中的真实行,例如在 DBF 文件中。从未填充的单元格可能被视为已删除,除非您不想在运行时更改数组的长度。
type UserRecord = record
Forename : string[20];
Surname : string[20];
Username : string[20];
Password : string[20];
gender : boolean;
FreeSpot : Boolean;
end;
添加后,您必须初始化变量,因此它们不会包含错误数据甚至垃圾。您必须在存储缓冲区中运行一个循环,并将它们都标记为未使用
for I := Low( UserArray ) to High( UserArray ) do
deleteRecord( I ); // initialize buffer so we can start saving data
procedure deleteRecord(const I: integer);
begin
UserArray[ I ].FreeSpot := true;
end;
之后,您可以像这样制作数据行保存例程:
// returns the array index where the data was stored, or -1 if did not saved
function storeRecord(const data: UserRecord ): integer;
begin
for Result := Low( UserArray ) to High( UserArray ) do
if UserArray[ Result ].FreeSpot then
begin
UserArray[ Result ] := data;
UserArray[ Result ].FreeSpot := false;
Exit();
end;
Result := -1; // out of the loop - found no free cell to take
end;
如果您无法将字段添加到记录中,您可以尝试
type UserRecord = record
Forename : string[20];
Surname : string[20];
Username : string[20];
Password : string[20];
gender : boolean;
end;
UserRecordSlot = record
Data : UserRecord;
FreeSpot : Boolean;
end;
UserArray : array of UserRecordSlot;
// returns the array index where the data was stored, or -1 if did not saved
function storeRecord(const data: UserRecord ): integer;
begin
for Result := Low( UserArray ) to High( UserArray ) do
if UserArray[ Result ].FreeSpot then
begin
UserArray[ Result ].Data := data;
UserArray[ Result ].FreeSpot := false;
Exit();
end;
Result := -1; // out of the loop - found no free cell to take
end;
【讨论】:
别忘了在存储第一条记录之前必须将所有FreeSpot
成员初始化为True。
@TLama 好的。但我真的不想写所有代码 :-) 这只是主题启动者要完成和继续作业的种子
另外,FreeSpot
字段在磁盘上的意义可能不如在内存中。
@FreeConsulting 我想到了这一点,我认为在磁盘上它比在内存中更有意义:磁盘文件可以被其他程序读取,今天和未来十年。因此,如果行中有数据或没有数据,则具有清晰的标记非常重要。 DBF 文件格式的用户可能也有同样的想法:-)以上是关于检查记录数组中的空间是不是空闲的主要内容,如果未能解决你的问题,请参考以下文章