我在C中有一个类似于数据库表记录的结构。 现在,当我使用select查询表时,我不知道会得到多少条记录。 我想将select查询中返回的所有记录存储在我的结构数据类型数组中。
哪种方法最好?
while ( records returned )
{
create new node
store the record in node
}
哪种实施最好?
我的要求是,当我拥有所有记录时, 我可能会复制它们或其他东西。 但我不需要随机访问,我也不会对特定记录进行任何搜索。
由于
答案 0 :(得分:3)
我忘了选项#4。分配固定大小的数组。当该数组已满时,分配另一个。您可以通过在链接列表中链接数组来跟踪数组,或者使用更高级别的数组来保持指向数据数组的指针。当你需要随机访问时,这个两级方案很棒,你只需要将索引分成两部分。
答案 1 :(得分:1)
'select count(*)'的一个问题是,调用之间的值可能会发生变化,因此您的“真实”选择会有一些与您期望的计数不同的项目。
我认为最好的解决方案是你的“2”。
我会亲自分配一个数组(根据需要重新分配),而不是链表。在支持不断增长的数组的语言中这更容易(例如,C ++中的std::vector<myrecord>
和C#中的List<myrecord>
。
答案 2 :(得分:1)
你忘记了选项3,它有点复杂,但它可能最适合你的特定情况。这是它通常在C ++ std :: vector中完成的方式。
分配任何舒适大小的数组。填充该数组时,分配一个1.5x到2x大的新数组,然后将填充的数组复制到此数组。释放原始阵列并将其替换为新阵列。泡沫,冲洗,重复。
答案 3 :(得分:0)
应该提出许多可能的批评。
您根本不是在讨论静态数组 - 静态数组的预定大小在编译时是固定的,对源文件是本地的,对函数是本地的。您正在谈论动态分配的数组。
您不会提供任何记录大小或记录数的指示,也不会给出下面数据库的动态指示(也就是说,当您的数据运行时,任何其他进程都可以更改任何数据)。尺寸信息不是非常关键,但另一个因素是。如果您正在进行某种报告,那么将数据提取到内存中就可以了。您不打算修改数据库,数据是准确的快照。但是,如果在修改记录时其他人可能正在修改记录,那么大纲解决方案是如何丢失其他人更新的主要示例。那是 BAD 的事情!
为什么一次需要内存中的所有数据?忽略大小限制,与按正确顺序处理每个相关记录相比,它的好处究竟是什么?你看,DBMS花了很多精力来选择相关的记录(WHERE子句)和相关的数据(SELECT列表),并允许你指定序列(ORDER BY子句),他们有最好的排序系统,他们可以负担得起(比你或我可能产生的更好)。
如果以块的形式分配数组,请注意二次行为。每次重新分配时,都必须将旧内存复制到新位置。这会破坏您的内存(旧位置可供重用,但根据定义,它太小而无法重用)。 Mark Ransom指出了一个合理的选择 - 不是世界上最简单的方案(但它避免了我提到的二次方案)。当然,你可以(并且会)用一组合适的函数来抽象它。
批量抓取(Mark Ransom也提到)也很有用。您可能希望预先分配批量提取所在的数组,这样您就不必进行额外的复制。这只是线性行为,因此不那么严重。
答案 4 :(得分:0)
创建表示阵列或列表的数据结构。假装您使用的是OO语言,并为您需要的一切创建访问器和构造器。在该数据结构内部,保留一个数组,并且正如其他人所说,当数组填充到容量时,分配一个大的新数组2x并复制到其中。只能通过定义的例程访问结构以进行访问。
这是Java和其他语言执行此操作的方式。在内部,这甚至是用C语言实现Perl的方式。
我打算说你最好的选择是找一个已经做到这一点的库...也许你可以借用这种数据结构的Perl C实现。我确信它比你或我从头开始卷起的任何东西都经过了更好的测试。 :)
答案 5 :(得分:0)
while(record = get_record()) {
records++;
records_array = (record_struct *) realloc(records_array, (sizeof record_struct)*records);
*records_array[records - 1] = record;
}
这是一个严格的例子 - 请不要在生产中使用realloc()。
答案 6 :(得分:0)
链表是一个很好的简单选项。我会顺其自然。如果您更喜欢不断增长的数组,您可以在Dave Hanson的C Interfaces and Implementations中找到一个实现,作为奖励也可以提供链接列表。
这看起来像是一个随着应用程序的发展而变化的设计决策,所以你绝对应该隐藏合适的API背后的表示。如果您还不知道如何做到这一点,Hanson的代码将为您提供一些很好的例子。