[英]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.