使用ofstream C ++覆盖一行

时间:2013-03-02 01:03:18

标签: c++ file line overwrite

我正在做一个小游戏,我将播放器详细信息保存在txt文件中。 该txt文件的示例:

Eric 13 8 10 10 30 10 10 50 0 0 0 0
William 1 0 10 30 30 10 10 50 0 0 0 0
John 1 0 10 30 30 10 10 50 0 0 0 0

这就是我的想法:当玩家选择在游戏时保存游戏时,save_game功能应检查是否已存在任何已保存的数据。如果有,而不是将数据附加到txt的末尾,它应该overwrite该特定行。

这是我目前的职能:

// SAVE GAME
void save_game(Player player)
{
    ofstream coutfile (SaveDestiny, ios::app);

    if (coutfile.is_open()) // if it opens correctly
    {
        // Now checking if the name already exists
        string imported_name;

        ifstream cinfile (SaveDestiny); // opens file that contains the saved games

        cinfile >> imported_name; // getting first element of file

        bool j = 0; // j = 0 while the strings don't match. j = 1 when the string was found

        while (cinfile >> imported_name) // while the end of file is not reached
        {
            if (player.name.compare(imported_name) == 0) // if the strings are the same, overwrite data
            {
                j = 1;

                coutfile << "                                                                         \r" << endl;
                break;
            }
            else // if the strings are different, keep reading
            {
                cinfile >> imported_name;
            }
        }

        // Continuing...
        coutfile << player.name << " " << player.level << " " << player.exp << " " << player.max_exp << " "
            << player.hp << " " << player.max_hp << " " << player.mp << " " << player.max_mp << " "
            << player.gold << " " << player.weapon << " " << player.shield << " " << player.heal_spell << " "
            << player.attack_spell << endl;
    }
    else
    {
        ofstream coutfile (SaveDestiny, ios::app);
        coutfile << "test";
        cout << "Unable to open file";
        cin.get();
    }

    draw_rectangle(37,8,72,14,15);  // white limits
    draw_rectangle(39,9,70,13,9);   // blue background
    cor(9,15);
    gotoxy(50,10);
    cout << "GAME SAVED!";
    gotoxy(41,12);
    cor(9,14);
    cout << "Press <Enter> to continue... ";
    cin.get();
}

2 个答案:

答案 0 :(得分:3)

在大多数现代文件系统文件中,它们不是“基于行”(或“基于记录”),而是基于字符的,因此您不能“覆盖一行”。旧行可能是20个字符长,新行可能是24个字符,在这种情况下,它将覆盖旧行下一行的前4个字符。为了完成这项工作,您必须在文件后面的行之后“推送”所有内容,这对于C ++(或C)IO工具来说是不可能的。

一个选项是编写具有固定长度的所有行,比如50个字符,这样覆盖第3行就会将字符100替换为149,即使该行实际上只需要24个字符。

另一种选择是将文件保存在基于记录的表单中,并在每次更改时写出整个文件(或者至少写出新行和后面的所有行)

答案 1 :(得分:0)

好的,我已经成功解决了这个问题,现在它的工作非常出色! :d

首先,function检查玩家名称是否已在txt上。我创建了一个启用变量jj=1时,名称存在且数据需要为overwritten!当j=0时,该函数会立即将append数据发送到txt。

好的,我们说j=1。该函数确定txt中的行数。然后,它会创建一个内置两个向量的vectornamegame variables。 之后,该函数删除txt文件的先前内容。并将向量的内容写入txt,除了需要覆盖的数据(它将跳过将该部分写入txt),因为在函数结束时,该新数据将写。 :D我希望自己足够清楚。对不起,如果有人不明白我写的东西......

这是我的新save_game功能:

// SAVE GAME
void save_game(Player player)
{
    ofstream coutfile (SaveDestiny, ios::app);

    if (coutfile.is_open()) // if it opens correctly
    {
        string imported_name;
        ifstream cinfile (SaveDestiny); // opens file that contains the saved games

        bool j = 0;

        // Now checking if the name already exists
        while (cinfile >> imported_name) // while the end of file is not reached
        {
            if (player.name.compare(imported_name) == 0) // if the strings are the same, overwrite data
            {
                j = 1; // enable overwrite
                break;
            }
            // if the strings are different, keep reading
        }
        // at this point: j = 0 to append to end. j = 1 to overwrite.

        // Overwriting data
        if (j == 1)
        {
            ifstream cinfile (SaveDestiny);

            // now determining the size of the vector (number of lines in txt)
            int line_numbers = 0;
            string line;
            while (getline(cinfile, line))
            {
                line_numbers++;
            }

            cinfile.close();    // closing
            ifstream cinfile2 (SaveDestiny);    // reopening to read from the beginning 

            // now creating the vector with the saves
            vector<vector<string>> temp_saves(line_numbers, vector<string>(2));
            string name2;
            string values;

            for (unsigned int x = 0; x < temp_saves.size(); x++)
            {
                cinfile2 >> name2;
                getline(cinfile2, values);

                temp_saves[x][0] = name2;
                temp_saves[x][1] = values;
            }

            coutfile.close(); // closing output file
            ofstream coutfile2 (SaveDestiny); // reopening in overwrite mode

            // delete all saves.txt, copying vector content to txt (except the one we want to overwrite)
            for (unsigned int x = 0; x < temp_saves.size(); x++)
            {
                if ( temp_saves[x][0].compare(player.name) != 0)
                {
                    coutfile2 << temp_saves[x][0] << temp_saves[x][1] << endl;
                }
            }
            coutfile2.close(); // closing output file
        }

        // Appending new data...
        ofstream coutfile3 (SaveDestiny, ios::app); // reopening in append mode
        coutfile3 << player.name << " " << player.level << " " << player.exp << " " << player.max_exp << " "
            << player.hp << " " << player.max_hp << " " << player.mp << " " << player.max_mp << " "
            << player.gold << " " << player.weapon << " " << player.shield << " " << player.heal_spell << " "
            << player.attack_spell << endl;
    }
    else
    {
        ofstream coutfile (SaveDestiny, ios::app);
        cout << "Unable to open file";
        cin.get();
    }

    draw_rectangle(37,8,72,14,15);  // white limits
    draw_rectangle(39,9,70,13,9);   // blue background
    cor(9,15);
    gotoxy(50,10);
    cout << "GAME SAVED!";
    gotoxy(41,12);
    cor(9,14);
    cout << "Press <Enter> to continue... ";
    cin.get();
}