我正在开发一个 C++ 程序,该程序处理存储在二进制文件中的 Pokémon 数据。该程序从二进制文件中读取神奇宝贝记录,根据它们的能力对它们进行排序,然后将排序后的神奇宝贝写回到另一个二进制文件中。但是,我在排序功能方面遇到了问题。
struct Pokemon
{
char Name[50];
int Type;
unsigned Power;
};
sortPokemons 函数正在接收一个输入流,该输入流与包含神奇宝贝(未排序)的二进制文件关联,以及一个输出流,该输出流与我们应该存储排序的神奇宝贝(按其
Power
)的文件关联。
void sortPokemons(std::istream& is, std::ostream& os)
{
unsigned count = 1;
while (true)
{
Pokemon p = readPokemonFromBinary(is);
if (is.eof())
{
break;
}
Pokemon min;
min.Power = INT32_MAX;
while (true)
{
Pokemon c = readPokemonFromBinary(is);
if (is.eof())
{
break;
}
if (c.Power < min.Power)
{
min = c;
}
}
printPokemon(min);
is.clear(); //the eof bit is set for the inner while to end
is.seekg(count * sizeof(Pokemon), std::ios::beg);
count++;
writePokenomToBinary(min, os);
}
}
请注意,我们知道输入文件中仅包含连续的神奇宝贝记录。
以下算法不起作用,我想我知道为什么:我正在尝试模拟选择排序算法,但为了让它工作,我们需要在需要时交换元素,我不知道如何使用只有文件。是否有更优雅的方法来实现我的目标(一个新文件,其中包含按
Power
升序排列的神奇宝贝)?我的想法有效吗?
嗯。对输入流的随机访问。这可能吗?没想到啊。
但即使对您的文件类型进行随机访问,您的算法也存在缺陷。第一次循环时,您将读取整个输入文件并找到功率最低的文件,然后将其写出。伟大的。到目前为止你都很好。
第二次通过外循环时,您将跳过输入的第一条记录。但除非您的输入已经排序,否则您跳过的输入可能是文件中的下一个最低值。
我会用完全不同的方式来做这件事。我们假设输入流上可以进行随机访问。我将文件读入 std::vector 一次。你说由于记忆问题你不想这么读。 (它必须是一个非常大的文件,才会成为一个问题。)但是您可以存储一个简单的结构:
struct PowerIndex {
size_t index;
long power;
}
只需存储索引(计数)0..n 加上您读取的记录的幂。
然后排序。现在,您可以运行该向量,寻找正确的文件位置,读取记录,写入记录,然后就完成了。
而且它会是正确的。
当然,我仍然想知道通用的随机访问是否可用
std::stream
。