使用 SDL2 保存对象矢量 [英] Saving vector of objects using SDL2

查看:68
本文介绍了使用 SDL2 保存对象矢量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 SDL2,现在我正在尝试将游戏排名保存到 .bin 文件中.我已将排名数据放入向量中.但是我无法保存数据.也许这与文件大小有关,但我无法解决.这是我现在使用的代码:

Im learning SDL2 and now im trying to save a game ranking into a .bin file. I have placed the ranking data into a vector. But im unable to save the data. Perhabs it has to do with file size, but im unable to solve that. This is the code that im using now:

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 的结构序列化为二进制文件的示例.它不使用 SDL 函数,因为我不使用 SDL,但如果需要修改也不难.

Here's an example of how I might serialize a struct containing std::string to/from binary. It doesn't use the SDL functions because I don't use SDL but it wouldn't be difficult to modify if desired.

您可能会遇到不同的问题,因为您说您的文件是空的,我担心您在写入文件之前尝试读取该文件,但您可以尝试类似的操作,看看是否有帮助.

You may have a different problem since you say your file is empty, and I am concerned that you try and read the file before you write it, but you could try something like this and see if it helps.

#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 保存对象矢量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆