检查记录数组中的空间是不是空闲

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 文件格式的用户可能也有同样的想法:-)

以上是关于检查记录数组中的空间是不是空闲的主要内容,如果未能解决你的问题,请参考以下文章

JVM内存分配

c++堆与栈的简单认识

段空间

检查它是不是是 sqldatareader 中的最后一条记录

delete删除记录数据库空间大小不减少问题

我想检查数组中的任何值是不是在数据库中