Ошибка элемента std :: vector, которую я не понимаю - PullRequest
0 голосов
/ 01 сентября 2018

Я пытаюсь создать функцию для сериализации класса по-своему. я использовал шаблон поражения для хранения каждой формы примитивной переменной. Я получаю ошибку в моей функции сериализации. я не хочу, чтобы мой элемент был статичным в моем элементе b / c, я хочу хранить много разных случайных элементов, пожалуйста, помогите!

struct _PVS
{
public:
    template<typename _PV> _PVS(_PV &PV)
        : ele(PV)
    {}
    template<typename _PV> _PV ele;
};
class player_one {

    std::vector<_PVS*> serializing;

    const string PL_name = "JOHN!";
    unsigned short int hp = 100;
    unsigned short int shield = 55;
    string fav_food = "soup.";

public:

    player_one() {

        serializing.push_back(new _PVS(PL_name));
        serializing.push_back(new _PVS(hp));
        serializing.push_back(new _PVS(shield));
        serializing.push_back(new _PVS(fav_food));

    }

    void serialclass() {
        ofstream _F;
        string temp;
        _F.open("player_one.log");

        for (int i = 0; i < serializing.size(); i++) {
        temp = (std::string)serializing[i].ele;
            //getline to pass in whole lines for data for serializing
        }



    };

};

1 Ответ

0 голосов
/ 02 сентября 2018

двоичная сериализация

Ниже приведен пример того, как вы можете приблизиться к сериализации для низкоуровневого формата файла. Обратите внимание, что мы знаем только, как сериализовать два типа полей (uint16_t и std::string). Вы можете специализировать дополнительные типы по мере необходимости.

Формат данных

Первое, что мы хотим сделать, это выбрать формат данных. Ниже я использовал простой блочный подход, где у нас зарезервировано два байта для типа и длины каждого поля. Всякий раз, когда вы хотите сериализовать поле, вы сначала пишете число, представляющее тип, а затем число, указывающее, сколько байтов следует за заголовком.

Это известно как кодирование переменной длины.

Пример кода

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdint>
#include <iomanip>

using namespace std;

enum class SerializedType {
    Unknown,
    UnsignedShortInteger,
    String
};
struct mapInt {
public:
    const uint8_t first;
    const uint8_t second;
    mapInt(uint16_t value)
    : first((value & 0xff00)>>8),
      second(value & 0xff) {
    }
};

std::vector<uint8_t> toWireFormat(const uint16_t& value) {
    const auto mapped = mapInt(value);
    const std::vector<uint8_t> data = {
        static_cast<uint8_t>(SerializedType::UnsignedShortInteger),
        2,
        mapped.first,
        mapped.second
    };
    return data;
}

std::vector<uint8_t> toWireFormat(const std::string& value) {
    std::vector<uint8_t> data;
    data.resize(value.size() + 2);
    data[0] = static_cast<uint8_t>(SerializedType::String);
    data[1] = static_cast<uint8_t>(value.size());
    for (auto i = 0; i < value.size(); ++i) {
        data[i+2] = value.at(i);
    }
    return data;
}

std::string serializedTypeAsString(SerializedType type) {
    switch (type) {
        case SerializedType::Unknown:
            return " Unknown";
        case SerializedType::UnsignedShortInteger:
            return "uint16_t";
        case SerializedType::String:
            return "  string";
    }
}

template<class T>
void appendData(std::vector<uint8_t>& data, const T& value) {
    const auto buffer = toWireFormat(value);
    data.insert(data.end(), buffer.begin(), buffer.end());
}

class PlayerOne {
public:
    const string name;
    uint16_t hp;
    uint16_t shield;
    string favFood = "soup";

    PlayerOne() = default;
    ~PlayerOne() = default;

    void serialize(std::vector<uint8_t>& data) const {
        appendData(data, name);
        appendData(data, hp);
        appendData(data, shield);
        appendData(data, favFood);
    };
};

int main()
{
   PlayerOne ready = { "JOHN!", 100, 55, "Soup" };
   PlayerOne two = { "Sarah", 250, 0, "Cake" };

    vector<uint8_t> output;
    ready.serialize(output);
    two.serialize(output);

    cout << "Serialized two objects into " << output.size() << " bytes." << endl;
    size_t i = 0;
    while (i < output.size()) {
        const auto typeString = serializedTypeAsString(
            static_cast<SerializedType>(output.at(i)));
        const int length = output.at(i+1);
        cout << "\nType: " << typeString << ", Length: " << length << ", Data: ";
        i += 2;
        if ((i+length) > output.size()) {
            break;
        }
        for (size_t j = i; j < (i+length); ++j) {
            cout << hex << setfill('0') << setw(2) << static_cast<int>(output.at(j));
        }
        i += length;
    }
    cout << endl;
    return 0;
}

Пример вывода

Примечание: строки ниже кодируются в шестнадцатеричном формате. Строки не заканчиваются нулем для экономии места в двоичном формате. При десериализации вам придется повторно применять нулевые байтовые терминаторы.

Serialized two objects into 42 bytes.

Type:   string, Length: 5, Data: 4a4f484e21
Type: uint16_t, Length: 2, Data: 0064
Type: uint16_t, Length: 2, Data: 0037
Type:   string, Length: 4, Data: 536f7570
Type:   string, Length: 5, Data: 5361726168
Type: uint16_t, Length: 2, Data: 00fa
Type: uint16_t, Length: 2, Data: 0000
Type:   string, Length: 4, Data: 43616b65
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...