使用 SDL2 保存对象向量
Saving vector of objects using SDL2
我正在学习 SDL2,现在我正在尝试将游戏排名保存到 .bin 文件中。我已将排名数据放入一个向量中。但我无法保存数据。也许它与文件大小有关,但我无法解决。这是我现在使用的代码:
class Player {
private:
std::string name, faction, dific;
int points;
public:
Player() {};
virtual ~Player() {};
void addName(std::string s);
void addFacti(std::string s);
void addDific(std::string s);
void addPoint(int p);
std::string getName() const;
std::string getFacti() const;
std::string getDific() const;
int getPoint() const;
bool operator>(const Player& p) const;
};
Player p1; Player p2;//just two examples
//add properties to each object
std::vector<Player>classi;
classi.push_back(p1); classi.push_back(p2);
std::sort(classi.begin(), classi.end(), std::greater<Player>());
//load file
SDL_RWops* rankfile = SDL_RWFromFile("ranking.bin", "r+b");
for (int i = 0; i < classi.size(); ++i) { SDL_RWread(rankfile, &classi[i], sizeof(Player), 1); }
SDL_RWclose(rankfile);
//im able to render the objects
//save file - but it doesnt save anything
rankfile = SDL_RWFromFile("ranking.bin", "w+b");
for (int i = 0; i < classi.size(); ++i) { SDL_RWwrite(rankfile, &classi[i], sizeof(Player), 1); }
SDL_RWclose(rankfile);
这是我如何序列化包含 std::string
to/from 二进制文件的结构的示例。它不使用 SDL 功能,因为我不使用 SDL,但如果需要,修改起来并不困难。
你可能遇到了不同的问题,因为你说你的文件是空的,我担心你在写入文件之前尝试阅读文件,但你可以尝试这样的事情,看看是否有帮助。
#include <iostream>
#include <string>
#include <fstream>
#include <tuple>
template <typename T>
std::ostream &writeBinary(std::ostream &f, T data)
{
return f.write(reinterpret_cast<char *>(&data), sizeof(data));
}
std::ostream &writeBinary(std::ostream &f, const std::string &str)
{
// If file size is a concern you might use a smaller type like uint16_t.
// Just make sure to mirror the change in readBinary.
std::string::size_type sz = str.size();
if (f)
{
f.write(reinterpret_cast<char *>(&sz), sizeof(sz));
}
if (f)
{
f.write(str.data(), str.size());
}
return f;
}
template <typename T>
std::istream &readBinary(std::istream &f, T &data)
{
if (f)
{
f.read(reinterpret_cast<char *>(&data), sizeof(data));
}
return f;
}
std::istream &readBinary(std::istream &f, std::string &str)
{
std::string::size_type sz = 0;
if (f)
{
f.read(reinterpret_cast<char *>(&sz), sizeof(sz));
}
if (f)
{
str.resize(sz);
f.read(str.data(), sz);
}
return f;
}
struct Thing
{
std::string shortString;
int i;
double d;
std::string longString;
Thing()
: i(99)
, d(99.99)
{ }
bool operator==(const Thing &rhs) const
{
return std::tie(shortString, i, d, longString)
== std::tie(rhs.shortString, rhs.i, rhs.d, rhs.longString);
}
bool write(std::ofstream &f)
{
if (!writeBinary(f, shortString))
{
return false;
}
if (!writeBinary(f, i))
{
return false;
}
if (!writeBinary(f, d))
{
return false;
}
if (!writeBinary(f, longString))
{
return false;
}
return true;
}
bool read(std::ifstream &f)
{
if (!readBinary(f, shortString))
{
return false;
}
if (!readBinary(f, i))
{
return false;
}
if (!readBinary(f, d))
{
return false;
}
if (!readBinary(f, longString))
{
return false;
}
return true;
}
};
std::ostream &operator<<(std::ostream &o, const Thing &t)
{
return o << "'" << t.shortString << "'" << ", "
<< t.i << ", " << t.d << ", "
<< "'" << t.longString << "'";
}
int main()
{
Thing t1;
// Shorter string to hopefully fit in any short string optimization buffer in the string.
t1.shortString = "Short";
t1.longString = "Long string that should be long enough to not fit in the SSO buffer.";
t1.i = 42;
t1.d = 42.42;
std::cout << "t1 Before Write: " << t1 << "\n";
std::ofstream out("thing.bin", std::ios::binary);
if (!t1.write(out))
{
std::cout << "Error writing t1!\n";
return -1;
}
out.close();
std::cout << "t1 After Write: " << t1 << "\n";
Thing t2;
std::cout << "t2 Before Read: " << t2 << "\n";
std::ifstream in("thing.bin", std::ios::binary);
if (!t2.read(in))
{
std::cout << "Error reading t2!\n";
return -1;
}
in.close();
std::cout << "t2 After Read: " << t2 << "\n";
std::cout << "t1 == t2: " << std::boolalpha << (t1 == t2) << "\n";
return 0;
}
我正在学习 SDL2,现在我正在尝试将游戏排名保存到 .bin 文件中。我已将排名数据放入一个向量中。但我无法保存数据。也许它与文件大小有关,但我无法解决。这是我现在使用的代码:
class Player {
private:
std::string name, faction, dific;
int points;
public:
Player() {};
virtual ~Player() {};
void addName(std::string s);
void addFacti(std::string s);
void addDific(std::string s);
void addPoint(int p);
std::string getName() const;
std::string getFacti() const;
std::string getDific() const;
int getPoint() const;
bool operator>(const Player& p) const;
};
Player p1; Player p2;//just two examples
//add properties to each object
std::vector<Player>classi;
classi.push_back(p1); classi.push_back(p2);
std::sort(classi.begin(), classi.end(), std::greater<Player>());
//load file
SDL_RWops* rankfile = SDL_RWFromFile("ranking.bin", "r+b");
for (int i = 0; i < classi.size(); ++i) { SDL_RWread(rankfile, &classi[i], sizeof(Player), 1); }
SDL_RWclose(rankfile);
//im able to render the objects
//save file - but it doesnt save anything
rankfile = SDL_RWFromFile("ranking.bin", "w+b");
for (int i = 0; i < classi.size(); ++i) { SDL_RWwrite(rankfile, &classi[i], sizeof(Player), 1); }
SDL_RWclose(rankfile);
这是我如何序列化包含 std::string
to/from 二进制文件的结构的示例。它不使用 SDL 功能,因为我不使用 SDL,但如果需要,修改起来并不困难。
你可能遇到了不同的问题,因为你说你的文件是空的,我担心你在写入文件之前尝试阅读文件,但你可以尝试这样的事情,看看是否有帮助。
#include <iostream>
#include <string>
#include <fstream>
#include <tuple>
template <typename T>
std::ostream &writeBinary(std::ostream &f, T data)
{
return f.write(reinterpret_cast<char *>(&data), sizeof(data));
}
std::ostream &writeBinary(std::ostream &f, const std::string &str)
{
// If file size is a concern you might use a smaller type like uint16_t.
// Just make sure to mirror the change in readBinary.
std::string::size_type sz = str.size();
if (f)
{
f.write(reinterpret_cast<char *>(&sz), sizeof(sz));
}
if (f)
{
f.write(str.data(), str.size());
}
return f;
}
template <typename T>
std::istream &readBinary(std::istream &f, T &data)
{
if (f)
{
f.read(reinterpret_cast<char *>(&data), sizeof(data));
}
return f;
}
std::istream &readBinary(std::istream &f, std::string &str)
{
std::string::size_type sz = 0;
if (f)
{
f.read(reinterpret_cast<char *>(&sz), sizeof(sz));
}
if (f)
{
str.resize(sz);
f.read(str.data(), sz);
}
return f;
}
struct Thing
{
std::string shortString;
int i;
double d;
std::string longString;
Thing()
: i(99)
, d(99.99)
{ }
bool operator==(const Thing &rhs) const
{
return std::tie(shortString, i, d, longString)
== std::tie(rhs.shortString, rhs.i, rhs.d, rhs.longString);
}
bool write(std::ofstream &f)
{
if (!writeBinary(f, shortString))
{
return false;
}
if (!writeBinary(f, i))
{
return false;
}
if (!writeBinary(f, d))
{
return false;
}
if (!writeBinary(f, longString))
{
return false;
}
return true;
}
bool read(std::ifstream &f)
{
if (!readBinary(f, shortString))
{
return false;
}
if (!readBinary(f, i))
{
return false;
}
if (!readBinary(f, d))
{
return false;
}
if (!readBinary(f, longString))
{
return false;
}
return true;
}
};
std::ostream &operator<<(std::ostream &o, const Thing &t)
{
return o << "'" << t.shortString << "'" << ", "
<< t.i << ", " << t.d << ", "
<< "'" << t.longString << "'";
}
int main()
{
Thing t1;
// Shorter string to hopefully fit in any short string optimization buffer in the string.
t1.shortString = "Short";
t1.longString = "Long string that should be long enough to not fit in the SSO buffer.";
t1.i = 42;
t1.d = 42.42;
std::cout << "t1 Before Write: " << t1 << "\n";
std::ofstream out("thing.bin", std::ios::binary);
if (!t1.write(out))
{
std::cout << "Error writing t1!\n";
return -1;
}
out.close();
std::cout << "t1 After Write: " << t1 << "\n";
Thing t2;
std::cout << "t2 Before Read: " << t2 << "\n";
std::ifstream in("thing.bin", std::ios::binary);
if (!t2.read(in))
{
std::cout << "Error reading t2!\n";
return -1;
}
in.close();
std::cout << "t2 After Read: " << t2 << "\n";
std::cout << "t1 == t2: " << std::boolalpha << (t1 == t2) << "\n";
return 0;
}