关于字符串:C 在文件中的特定点插入一行

C++ Inserting a line at specific point in file

我有一个包含游戏高分的文本文件,格式如下:

1
2
3
Name Score
Name Score
Name Score

文件按分数降序排列。

我想在文件的正确位置插入一个新名称及其对应的分数,以便它保持正确排序。任何建议如何做到这一点将不胜感激!

例如,给定以下文件:

1
2
3
4
Edward 100
David 90
Sarah 80
Alice 60

我想补充一下。

1
2
Name = Jodi
Score = 70

到文件,所以新文件的内容是:

1
2
3
4
5
Edward 100
David 90
Sarah 80
Jodi 70
Alice 60

谢谢

目前我有以下代码:

1
2
3
4
5
6
7
string playerName = pPlayer->GetName();
int playerScore = pPlayer->GetScore();

std::ofstream score("scores.txt", std::ios_base::app | std::ios_base::out);

score <<"\
"
<< playerName <<"" << playerScore;

这只是将名称添加到文件的末尾。我考虑阅读整个文件,然后对旧文件进行排序。但我不想这样做,因为如果文件变大可能需要很长时间。


有几种不同的方法可以做到这一点。最简单的实现是将整个文件读入向量,插入新值并写出新文件。

第二个选项是读取文件,直到找到正确的位置,"标记"在文件中的位置(例如使用 istream::tellg()),然后将以下所有元素读入向量,更新新的记录,并写回过去的一次。

第三种选择是在文件中保持列表无序,并在阅读时对信息进行排序。这样,您可以只追加到末尾,从而节省了一遍又一遍地写入文件。

实际上,我怀疑编写一个非常大的文件仍然足够快,几乎不会产生任何影响。现代硬盘驱动器每秒将写入数兆字节,而每行只有几十个字节,因此文件中需要有数百万行才能产生任何影响。比如我刚刚在我的机器上复制了一些132MB的大文件,读取和写入132MB的时间为1.2s。如果你的每条记录都是 26 字节,那就是 5000 万个"分数"。


如果你仔细定义一个类型来表示你的数据记录:

1
2
3
4
5
6
7
8
9
struct Record {
    std::string name; int score;
    friend std::istream& operator>>(std::istream& is, Record& r)       { return is >> r.name         >> r.score; }
    friend std::ostream& operator<<(std::ostream& os, Record const& r) { return os << r.name <<"\\t" << r.score; }

    bool operator<(Record const& other) const {
        return other.score < score;
    }
};

注意它知道如何

  • 从流中读取记录
  • 将其写回流
  • 按分数比较记录

那么,C 算法又是你的朋友了:

1
2
3
4
5
6
7
8
9
10
11
int main()
{
    std::ifstream ifs("input.txt");
    std::vector<Record> const insert { Record {"Jodi", 70 } };

    std::merge(
            std::istream_iterator<Record>(ifs), {},
            insert.begin(), insert.end(),
            std::ostream_iterator<Record>(std::cout,"\
"
));
}

在 Coliru 现场观看


一种方法是加载文件,然后在包含新数据的情况下重写它:

1) 您必须使用 C 文件处理 API(或任何您认为更好的 API)将文件加载到结构中。

2) 由于按顺序加载,数据将在结构中排序。然后,您必须在结构中添加所需的节点(新数据),使其保持排序状态。

3) 最后,从结构中重写你的文件。

对于您的情况,您可以使用 std::vector。您可以打开文件并将其所有行加载到该向量中。您可以通过执行字符串操作来隔离数据。
然后,将您的数据放入结构中,以使其保持排序状态。例如,您可以分割一条线,然后获取分数部分,将其解析为 int 并与新数据分数进行比较。之后,该结构包含您的数据状态。
打开文件并逐行重写。


它的行为方式取决于文件系统。一般没有解决办法。但我不认为有一个真实的文件系统可以让你做这些事情。

关于这样的操作前后文件在磁盘上的样子。文件是磁盘上的一大块。所以重写是需要完成的动作。

如果您对一些不同的方法持开放态度,可能会有解决方案。把这个文件想象成内存。如果它不在磁盘上,你会怎么做?您可以在数组中使用哪种数据结构(我们可以将文件定义为数组)?

如果您不想创建自己的,使用 sth,就完成了。我个人会使用数据库来完成这样的任务。这正是你想要的。您可以插入数据,然后对其进行排序,并且运行速度很快。它经过优化,可以在硬盘驱动器等环境中工作。如果你想把它存档,你可以使用 SQLite.