簡體   English   中英

c++ 保存和讀取其中包含矢量結構的結構

[英]c++ saving and reading a struct with a vector struct in it

我是 C++ 的新手,所以我還沒有完全習慣語法。 我知道的不僅僅是 C# 語法的基礎知識,我已經使用了一年的大部分時間,而且我有 2 年的 PHP 和 python 到 go。

我正在嘗試將其中帶有向量的結構寫入文件,並在不同的時刻讀回它;

struct inventoryItem
        {
            std::string itemName;
            bool unlocked{false};
        };
        struct saveData
        {
            std::string userName{"John"};
            int hunger{100};
            int health{100};
            int money{5};
            std::vector<inventoryItem> inventory;
        };

我將它保存到文件中,如下所示:

void saveGame::createSave()
{
    saveData saveObj;
    inventoryItem newItem;

    newItem.itemName = "shoes";
    newItem.unlocked = true;
    saveObj.inventory.push_back(newItem);

    newItem.itemName = "knife";
    saveObj.inventory.push_back(newItem);

    // std::thread saveThis(save, saveObj);
    // saveThis.join();
    save(saveObj);
    return;
}

void saveGame::save(saveData toSave)
{
    std::fstream fileW(saveGame::fileName, std::ios_base::in);

    if (!fileW.good() || !fileW.is_open())
    {
        system("exit");
    } else
    {
        fileW.write((char *) &toSave, sizeof(saveData));
        fileW.close();
    }
    return;
}

我這樣取回它:

saveGame::saveData saveGame::getSave()
{
    std::fstream fileR(saveGame::fileName, std::ios_base::out);
    saveData toRetrieve;

    if (!fileR.good() || !fileR.is_open())
        system("exit");
    else
    {
        fileR.read((char *) &toRetrieve, sizeof(saveData));
    }

    return toRetrieve;
}
        saveGame::saveData data = saveObj.getSave();
        std::cout<<data.userName<<std::endl;
        std::cout<<data.health<<std::endl;
        std::cout<<data.inventory[0].itemName; // I've also tried looping through the vector, but this also did not work. Even when I don't try to access it, it will crash after it has processed the other pieces of data

現在,一切正常。 我可以訪問所有數據,除了其中的向量結構。 一旦它到達那條數據,程序就會崩潰而不會出現任何錯誤代碼。 我這樣做,但是收到一條 windows 消息說“a.exe 已停止工作”,但它不會產生調試消息。 如果可能,您能否在解釋中使用簡單的術語? 我還沒有進入高級 C++。 提前致謝

我試過遍歷向量,根本不訪問它,只是從中打印第一條數據。

我期待這個:

*CONSOLE OUTPUT*
John //username
100 // health
shoes // inventory.itemName (string)
true // inventory.unlocked (bool)
knife // inventory.itemName (string)
false // inventory.unlocked (bool)

但我反而越來越

*CONSOLE OUTPUT*
John //username
100 // health

和... BAM“a.exe 已停止工作”而沒有調試消息

std::vector<> 包含長度和指向堆 memory 的指針。您不能像這樣保存向量:

vector<int> v = {1, 2, 3};

// the following line will save the length and the address of the array
// containing the data.  NOT the data itself.
fileW.write((char *) &v, sizeof(v)); 

//...

std::vector<int> u;

// the following line will fill vector u with a length and a pointer to nowhere!

fileX.read((char *) &u, sizeof(u)); 

請注意,長度和指向數據的指針是 std::vector<> 的 PRIVATE 成員。 直接操作它們只會導致未定義的行為。

要保存動態長度數組,您必須首先定義將數組保存到文件的語法,然后定義將單個項目保存到文件中的語法。

在您的特定情況下,您還應該定義用於保存inventoryItem對象的語法,因為它包含一個可變長度的字符串。

您可以選擇要保存數據的任何語法。 它可以是二進制格式,例如長度后跟數組的內容,或者使用庫以流行的格式保存,如 xml 或 json,或 .ini。 無論您選擇哪種解決方案,您都需要編寫函數來保存和讀取您定義的類型:

    struct inventoryItem
    {
        std::string itemName;
        bool unlocked{false};

        friend std::ostream& operator << (std::ostream& os, const inventoryItem& item)
        {
             return os << itemName << ' ' << (unlocked ? "true" : "false");
        }

        friend std::istream& operator >> (std::istream& is,  inventoryItem& item)
        {
             std::string unl;
             is >> itemName >> unl;
             item.unlocked = (unl == "true");
             return is;                    
        }
    };

    struct saveData
    {
        std::string userName{"John"};
        int hunger{100};
        int health{100};
        int money{5};
        std::vector<inventoryItem> inventory;

        friend std::ostream& operator << (std::ostream& os, const saveData& data)
        {
             os << data.userName << " " 
                << data.hunger << " " 
                << data.health << " " 
                << data.money << " ";

             os << data.inventory.size() << "\n";
             for (size_t i = 0; i < data.inventory.size(); ++i)
                os << data.inventory[i] << "\n";
        }

        friend std::istream& operator >> (std::istream& is, saveData& data)
        {
             is >> data.userName >> data.hunger >> data.health >> data.money;

             size_t item_count = 0;
             is >> item_count;
             for (size_t i = 0; i < item_count; ++i)
             {
                inventoryItem item;
                is >> item;
                data.inventory.push_back(item);
             }
             return is;
        }
    };

注意:此代碼未經測試,甚至可能無法編譯,它的唯一目的是展示一種將 stream 動態數據傳入/傳出文件的簡單方法。 這種非常簡單的方法通常太天真了,用處不大。 這就是為什么你真的應該考慮使用像 boost::property_tree 這樣的庫來保存為更健壯的格式。

暫無
暫無

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

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