簡體   English   中英

用ofstream C ++覆蓋一行

[英]Overwrite a line with ofstream C++

我正在做一個小游戲,並將玩家詳細信息保存在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函數應檢查是否已經有保存的數據。 如果有的話,它應該overwrite該特定行,而不是將數據附加到txt的末尾。

這是我當前的功能:

// 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();
}

在大多數現代文件系統上,文件不是基於行的(或基於記錄的),而是基於字符的,因此您不能“覆蓋行”。 舊行可能長20個字符,而新行可能長24個字符,在這種情況下,它將覆蓋舊行下一行的前4個字符。 為了使這項工作有效,您將不得不在文件后面的行之后“推送”所有內容,而這對於C ++(或C)IO設備是不可能的。

一種選擇是將所有具有固定長度的行(例如50個字符)寫入,以便覆蓋第三行涉及將字符替換為100到149,即使該行實際上只需要24個字符也是如此。

另一種選擇是將文件以基於記錄的形式保存在內存中,並在每次更改時寫出整個文件(或至少寫出新行及其后的所有行)

好的,我設法解決了這個問題,現在它的工作非常出色! :D

首先,該function檢查播放器名稱是否已經在txt 我創建了一個啟用變量j j=1 ,名稱存在並且數據需要被overwritten j=0 ,函數將立即append數據append到txt。

好的,假設j=1 該函數確定txt的行數。 然后創建一個vector里面兩個向量:該name ,以及game variables 之后,該函數刪除txt文件的先前內容。 並將向量的內容寫入txt ,但需要覆蓋的數據除外(它將跳過將該部分寫入txt ),因為在函數結束時,將寫入新數據。 :DI希望我讓自己說得足夠清楚。 抱歉,如果有人聽不懂我寫的話...

這是我新的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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM