1

我在 C 中有一个类似于数据库表记录的结构。现在当我使用 select 查询表时,我不知道我会得到多少条记录。我想将选择查询返回的所有记录存储在我的结构数据类型的数组中。

哪种方法最好?

方法一:查找数组大小并分配

  1. 首先通过从表中执行 select count(*) 来获取记录数
  2. 分配一个静态数组
  3. 运行 select * from table 然后将每个记录存储在我的结构中。

方法二:使用单链表

while ( records returned )
{
    create new node 
    store the record in node 
}

哪种实现最好?

我的要求是,当我拥有所有记录时,我可能会复制它们或其他东西。但我不需要随机访问,也不会对特定记录进行任何搜索。

谢谢

4

7 回答 7

3

我忘记了选项#4。分配一个固定大小的数组。当该数组已满时,分配另一个。您可以通过将数组链接到链表中来跟踪数组,或者使用更高级别的数组来保存指向数据数组的指针。当您需要随机访问时,这种两级方案非常有用,您只需要将索引分成两部分。

于 2009-01-01T16:53:06.727 回答
1

'select count(*)' 的一个问题是值可能会在调用之间发生变化,因此您的“真实”选择将有许多与您期望的计数不同的项目。

我认为最好的解决方案是你的“2”。我会亲自分配一个数组(根据需要重新分配),而不是链表。这在支持不断增长的数组的语言中更容易(例如std::vector<myrecord>在 C++ 和List<myrecord>C# 中)。

于 2009-01-01T16:41:40.743 回答
1

您忘记了选项 3,它有点复杂,但它可能最适合您的特定情况。这是它通常在 C++ std::vector 中完成的方式。

分配一个任意大小的数组。当该数组被填充时,分配一个新的更大的数组,其大小是填充数组的 1.5 倍到 2 倍,然后将填充数组复制到这个数组。释放原始数组并用新数组替换它。起泡,冲洗,重复。

于 2009-01-01T16:49:33.787 回答
0
while(record = get_record()) {
  records++;
  records_array = (record_struct *) realloc(records_array, (sizeof record_struct)*records);
  *records_array[records - 1] = record;
}

这只是一个例子——请不要在生产环境中使用 realloc()。

于 2009-01-01T19:57:20.363 回答
0

链表是一个不错的简单选项。我会同意的。如果您更喜欢不断增长的数组,您可以在 Dave Hanson 的C Interfaces and Implementations中找到一个实现,作为奖励,它还提供了链表。

在我看来,这就像一个设计决策,可能会随着您的应用程序的发展而改变,因此您绝对应该将表示隐藏在合适的 API 后面。如果你还不知道怎么做,Hanson 的代码会给你一些很好的例子。

于 2009-01-02T05:06:24.140 回答
0

应该提出很多可能的批评。

  1. 您根本不是在谈论静态数组 - 静态数组将具有在编译时固定的预定大小,并且是源文件本地或函数本地的。您正在谈论动态分配的数组。

  2. 您没有给出任何记录大小或记录计数的指示,也没有给出底层数据库的动态程度(也就是说,任何其他进程在您的运行时是否可以更改任何数据)。尺寸信息并不是非常关键,但另一个因素是。如果您正在做某种报告,那么将数据提取到内存中就可以了;您不会修改数据库,并且数据是准确的快照。但是,如果在您修改记录时其他人可能正在修改记录,您的大纲解决方案就是如何丢失其他人更新的主要示例。那是一件坏事

  3. 为什么一次需要内存中的所有数据?忽略大小限制,与按正确顺序处理每个相关记录一次相比,这到底有什么好处?您会看到,DBMS 为能够选择相关记录(WHERE 子句)和相关数据(SELECT 列表)并允许您指定序列(ORDER BY 子句)付出了很多努力,它们拥有最好的排序系统负担得起(比你或我可能生产的更好)。

  4. 如果您以块的形式分配数组,请注意二次行为。每次重新分配时,很有可能必须将旧内存复制到新位置。这将使您的记忆碎片化(旧位置将可供重用,但根据定义将太小而无法重用)。Mark Ransom 指出了一个合理的替代方案——总体上不是世界上最简单的方案(但它避免了我提到的二次行为)。当然,您可以(并且会)通过一组合适的函数将其抽象出来。

  5. 批量获取(Mark Ransom 也提到过)也很有用。您可能希望预先分配批量提取所提取的数组,这样您就不必进行额外的复制。不过,这只是线性行为,因此不太严重。

于 2009-01-01T17:14:54.203 回答
0

创建一个数据结构来表示您的数组或列表。假设您使用 OO 语言,并为您需要的一切创建访问器和构造器。在该数据结构中,保留一个数组,并且正如其他人所说,当数组被填满时,分配一个 2 倍大的新数组并复制到其中。仅通过您定义的访问该结构的例程来访问该结构。

这就是 Java 和其他语言执行此操作的方式。在内部,这甚至是 Perl 在 C 中实现的方式。

我想说你最好的选择是寻找一个已经这样做的库......也许你可以借用 Perl 的这种数据结构的 C 实现。我敢肯定,它比您或我可以从头开始的任何东西都经过了更好的测试。:)

于 2009-01-01T17:37:05.343 回答